There are several ways to accomplish this.
One of the easiest ways is to have an initial data entry layout where the record is entered for the first time and then from that moment forward you view the record on a duplicated layout where the fields you do not want to have changed are visible but are locked down by unchecking "Allow Entry Into Field" in the Inspector.
Other methods include using script triggers or making the fields that you want to lock down buttons and performing some form of check to determine if entry is allowed into the field or not. These two methods have benefits over duplicating the layout in that you can program in "overwrite" checks if need be so that those who should be able to edit the data can without having to jump through too many hoops.
To start with, this way of doing things would create duplicates of the same entity in a table, a definite no-no.
Steve gives you good method for doing this. Your example of the primary address opens up a question. In a number of solutions i have worked on items like addresses and phone numbers frequently end up in a separate table with a one to many relationship. A specific address or phone number can be flagged as primary. Making it easy to keep them but change the primary when nessasary.
Something to think about in your solution.
I think if this level of protection is needed, you're better off with a separate table that logs the changes.
As siplus pointed out duplicating the record is a bad idea. It will break all the relationships to that company in the system
as they will point to the old primary key.
It seems to me that a duplicate layout where the fields are not editable is your solution. The second layout would not duplicate data (as siplus suggests), since it would still display the same data as the original layout.
You might also consider setting up an audit trail of any changes made. This would consist of a global text field with scroll bar that would contain a record of all changes. Every time a change is made (exit field trigger for each field) it would record the timestamp, account, field name changed, and the new data. The old data can also be included if captured when the field is entered (enter field trigger for each field). Just make sure the audit field cannot be accessed, except by admin users.
Hope this helps.
If for example you have a companies database, a clients database and a contracts database, you probably want to have:
- actual situation of a company (like address, phone, etc)
- actual situation of a client (see above)
- a contracts database that reflects the state a company and a client were at the moment they signed the contract.
You can have everything, by implementing changelogs for the first two entities (like benniemc sez) and lookup fields in the contracts db, which pull data from company and client at the contract creation moment and maintain that content even if the field contents of companies and clients change. Lookups are still alive, in good health and giving their share when used correctly.
If you have FM 13 you could place the field twice on the layout, one editable the other uneditable. Then set the visibility formula to hide the editable field when not empty.
If you want to log I suggest looking a ultralog by nightwing enterprises.
You might also consider setting up an audit trail of any changes made. This would consist of a global text field with scroll bar that would contain a record of all changes.
I'd advise against using a global field for storing anything than temporary data for this purpose.
It will break as soon as the solution becomes a host or gets hosted on a server.
And second: appending concurrent changes to one text field might sound easy to do but will be a pain to retrieve / manage later.
Best to use a table of some sort.
Thanks a lot to everybody for your precious answers!
I made a solution for this that has two seperate tables and an uneditable layout. In one table is company info and in another are just adresses. The adresses are related by relationnumber and a start and end date. When the adress needs to be edited i edit the original adress end date and create a new adress with a new start date. That way you lways have the current adress but you can see the adress of the company at the time they placed an order by linking the adress by including the date of that order in the relation
I have a very basic idea (sorry for that ) :
You may try a validation rule by calculation with a simple formula :
Get ( RecordOpenState ) = 1
And check the box : "validate only if field have been modified" on formula box
And attach a custom message...
Fred, this will only work when you fill ALL the "write once only" fields immediately after record creation and before any commit.
A possible solution, similar to rrichie's one but which allows you to enter the field in order to copy its content is this:
UseOnce.fmp12.zip 65.0 K
The use of hide condition and superposition of two objects is really clever indeed; added to the "long standing trick" to create a calc that allow enduser to interact but prevent modification is… definitely a must !
My idea was just "different", so basic (maybe stupid?), evolutive*, but definitely a secure way to proceed… Mine is data-level and not only layout-level. But i love to admit, mine is not a very friendly way for enduser...
Another way i used is following : create a related table (relationship with auto creation) for all the "critical fields". Then, configure privilege set to lock the related table with custom formula.
*The formula could add a lot of other conditions.