perl dbi submit checkbox values - forms

I have a form with checkboxes and I need to know what the best way to submit them to the database is. I have the following table setup:
roles users user_roles
----- ----- ----------
id id user_id
role_id
I have a page where you can edit a user and assign them different roles via checkbox, then those checkboxes are saved in the user_roles table. Since editing a user's roles can involve either deleting rows or adding rows, this is how I currently handle it:
my $form_vals = (1=>1,2=>2); #submitted by user
my $db_vals = (3=>3); #gotten out of db
So I have these two hashes and I will compare the keys in $form_vals with the keys in $db_vals, then I see that I have two extra values that are not present in the database so I add them. And vice versa I find which values are no longer selected on the form by comparing the keys in $db_vals with the keys in $form_vals and then I delete those rows from the database. My question is, does anyone know of a better/easier way to do this? It's never really seemed obvious to me how to handle checkboxes and I'd like to know what best practice is. Thanks!

I wouldn't say that this has much to do with check boxes per se.
Basically what you have is two array of arrays, [ (uid, rid), (uid, rid) ], and you want to make array1 (the one in your database) a copy of array2 (the user input from the checkboxes). You could have a multi select or a comma separated string, and the case would be the same. You have a user id, and you want that user to have only the roles supplied.
Two ways to achieve that would be to either
Put both arrays in one hash each, do foreach key on the submitted, if not present in the database one do insert. Then do the same for the database hash and delete those not present in the submitted hash
Delete everything from the member_role table and insert what's submitted.
You really have to know everything in the database and everything submitted and check twice if you don't want to delete everything and do a fresh insert. You can of course make a function doing this for you, hiding the ugliness a bit. Think about how you'd do if it was just two arrays and no database was around.

Related

Code to assign an ID when button is clicked

I have designed a simple database to keep track of company contacts. Now, I am building a form to allow employees to add contacts to the database.
On the form itself, I have all the columns except the primary key (contactID) tied to a text box. I would like the contactID value to be (the total number of entered contacts + 1) when the Add button is clicked. Basically, the first contact entered will have a contactID of 1 (0 + 1 = 1). Maybe the COUNT command factors in?
So, I am looking for assistance with what code I should place in the .Click event. Perhaps it would help to know how similar FoxPro is to SQL.
Thanks
The method you recommend for assigning ContactIDs is not a good idea. If two people are using the application at the same time, they could each create a record with the same ContactID.
My recommendation is that you use VFP's AutoIncrementing Integer capability. That is, set the relevant column to be Integer (AutoInc) in the Table Designer. Then, each new row gets the next available value, but you don't have to do any work to make it happen.
There are various ways to do this. Probably the simplest is to attempt to lock the table with flock() when saving, and if successful do:
calc max id_field to lnMax
Then when inserting your new record use lnMax+1 as the id_field value. Don't forget to
unlock all
... after saving. You'll want to ensure that 'id_field' has an index tag on it, and that you handle the case where someone else might have the table locked.
You can also do it more 'automagically' with a stored procedure.

MS Access Form and Tables

I have a specific question regarding the utilization of three tables in a database. Table 1 is called Personnel, and lists the names of the staff.
Tables 2 and 3 are identical, just listing two different types of overtime (long and short), along with the hours of the OT, Date of the OT, and Assigned to/Picked fields that are empty.
Here is the idea, I just dont know how to implement it. I would like to create a form for people to enter their OT picks, then automatically move to the next person on the list. So Rich Riphon, as an example, would be up first, would click on the link I would send, and a form would open up, showing his name, populated by the first table, and showing two drop down menus, populated from the Long OT and Short OT tables. He would select one from each (or None, which would be a option) and Submit it.
The form action would be to place his name in the Assigned field for the OT he picked, and place a Yes in the Picked field.
When the next person in the list opens the form, it has moved down to number 2 on the Personnel list, Cheryl Peterson, and shows her the remaining OT selections (excluding those that have a Yes in the Picked column).
Any suggestions or comments or better ways to do this would be appreciated.
First, I don't think ms access would be able to (easily) kick off the process based on a hyperlink. You may be able to do something by passing a macro name to a cmd prompt but it would take some mastery to get it working properly. Could you instead create a login form to get the current user? If you do that you don't really need to display the personnel list, just keep track of who has not yet responded to the OT request. Essentially at that point all you would need on your form is a listing of the available OT and a button that creates the assignment. Also it may be easier (and a better design) to only have one table for the OT listings and add a column for the type of overtime (long/short).
What if Cheryl isn't the 2nd person to get the form? Your concept goes out the window.
Instead, I would keep a table of all user names, and their security level. managers can see everything, individual users can only see their record. This would be done by using a query behind the OT Picks form, and either filtering by the current user or not filtering at all. I have done many of these types of "user control" databases and they all have worked well.
As for the actual OT tracking, I agree with Steve's post in that it should be done in one table This would be the preferred method of a concept referred to as "normalizing data". You really want to store as little data as possible to keep the size of your database down. As an example, your Login table would have the following fields:
UserID
FirstName
LastName
SecurityLevel
Address1
Address2
City
State
Phone
Etc... (whatever relevant info pertains to that person)
Your OT table would look like this:
UserID
OTDate
OTHours
OTType
Etc... (whatever else is relevant to OT)
You would then join those 2 tables on the UserID fields in both tables any time you needed to write a query to report OT hours or whatever.

I would like to use a parameter for the table name. The table names can be presented to the user from a database view.

I would like to use a parameter for the table name. I have an application that creates several new tables each month. I therefore need the table name to be sent into CR via a parameter. The fields for the tabkes are always identical. I can present a list (view) from the database to the end user that would display a user friendly name for the table, when the user selects the instance they want I then have the table name I want to report from.
I'm not sure if that is possible. Even if your tables have the same structure, the field names will ultimately be different. Let's say you have a {table1.field1} in your report. Now you want to run the report from table2 instead of table1. So your field now would have to become {table2.field1}. Does that make sense? I think a better approach might be to try stored procedures that will create the fields you need so the field names won't change.

FileMaker Pro 12 Auto-populating Tables

I'm new to Filemaker and need some advice on auto-populating tables.
Part 1:
I have TableA which includes many records with client information. I want a separate TableB which is identical to TableA except that it is "de-identified"; that is, it does not contain two of the fields, first name and last name.
I would like the two tables to interact such that if I add a new record to TableA, that same record (sans first and last name) appear automatically in TableB.
Part 2:
In addition to the above functionality, I would also like said functionality to be dependent on a specific field type from TableA. For example, I enter a new record, which has a "status" field set to "active," into tableA. I then want that record to be auto-popualted into TableB; however, if I add another record with a "status" of "inactive," I want that that record auto-populated into a TableC but not into TableB.
FileMaker can perform this with script triggers so long as every layout where TableA will be edited has a layout script trigger of OnRecordCommit connected to it. When the record is committed (which can happen in a number of ways), the attached script will run, which you can use to create the appropriate record in the appropriate table.
The script could create the record in a number of ways. If the primary keys for both records are the same, you could use lookups. You could export the record in TableA and then import it into the correct table. You could pass the field information as a parameter to the script. The best choice really depends on your needs.
Having said that, I would question the wisdom of this approach. It brings up a few questions that would seem to complicate matters. For example, what happens when the status changes? When a record in TableA is deleted? When fields in TableA are modified? Each of these contingencies (and others) will require thought and more complicated scripts.
So I would ask what problem you're really trying to solve. My best guess is that you are trying to keep the name information private from certain users. User accounts and privileges with dedicated layouts for each privilege can solve this without the need for duplicate tables. FileMaker privilege sets can be quite granular.
For example, you can specify that users with PrivilegeA can create records and view names, but PrivilegeB users can only view records if the status is "active" and the name fields are not available to them, while PrivilegeC users can view records if the status is "inactive" and the name fields are also not available to them.
I would definitely use filters and permissions on the "status field" to achieve this and not two mirroring tables. Unless the inactive information is drastically different, you would be complicated your solution and creating more possible pitfalls.

How can I (partially) automate the transfer of a FileMaker database structure and field contents to a second database?

I'm trying to copy some field values to a duplicate database. One record at a time. This is used for history and so I can delete some records in the original database to keep it fast.
I don't want to manually save the values in a variable because there are hundreds of fields. So I want to go to the first field, save the field name and value and then go over to the other database and save the data. Then run a 'Go to Next Field' and loop through all the fields.
This works perfectly, but here is the problem: When a field is a calculation you cannot tab into it and therefore 'Go to Next Field' doesn't work. It skips it.
I though of doing a 'Go to Object' but then I need to name all the objects and I can't find a script to name objects.
Can anyone out there think of a solution?
Thanks!
This is one of those problems where I always found it easier to do an export/import.
Export all the data you want from the one database, and then import it into the other database. All you need to do is:
Manually specify which fields you want to copy
Map the data from the export to the right fields in the new database/table
You can even write a script to do these things for you.
There are several ways to achieve this.
To make a "history file", I have found there are several cases out there, so lets take a look.
CASE ONE
Single file I just want to "keep" a very large file with historical data, because I need to erease all data in my Main file.
In this case, you should create a "clone" table (in the same file ore in other file, is the same). Then change any calculation field to the type of the calculation result (number, text, date, an so on...). Remove any "auto entered value or calculation from any field, like auto number, auto creation date, etc..). You will have a "Plain Table" with no calculations or auto entered data.
Then add a field to control duplicate data. If you have lets say an invoice number (unique) for each record, you can do this to achieve this task. But if you do not have a unique field that identifies the record as unique, then you have to create one...
To create such a field, I recommed to add a new field on the clone table and set as an aunto entered calculation and make a field combination that is unique... somthing like this: invoiceNumber & "-" & lineNumber & "-" " & date.
On the clone table make shure that validation is set up for "always", and no empty values allowed and that this value is unique.
Once you setup the clone table... then you can import your records, making sure that the auto enty option is on. Yo can do it as many times as you like, new records will be added and no duplicates.
If you want, can make a Script to do the move to historical table all the current records before deleting them.
NOTE:
This technique works fine when the data you try to keep do not have changes over time. This means, once the record is created is has no changes.
CASE TWO
A historical table must be created but some fields are updated.
In the beginnig I thougth a historical data, never changes. In some cases I found this is not the case, like the case I want to track historical invoices but at the same time, keep track if they are paid or not...
In this case you may use the same technique above, but instead of importing data... you must update data based on the "unique" fields that identifiy the record.
Hope this technique helps
FileMaker's FieldNames() function, along with GetField() can give you a list of field names and then their values