# Customize form fields specifications


CASES
    - https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/3426
    - https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/1442 
    - https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/1368
    - https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/3408



REQUIREMENTS

UI FEATURE - The ability to customize forms:
    - ROLE RIGHTS: BizAdminFull only can edit.  BizAdminLimited can view but not change
    - A "Customize" option in the Action bar menu | that is accessible to people of BizAdminFull role only
        - If a dispatcher needs a custom field set on a workorder, a bizadminfull user must login and set that up for them
        - When customize is selected a generic form pops up with a list of fields provided by the backend and their current settings and controls
            - This form can then be re-used everywhere as it's a stock object and this way we don't need to have a customize form for every existing CRUD form
    - Choosing to expose one or more of up to 16 custom fields on form in custom field section that shows when at least one is enabled
    - NO ability to edit localized text here, that's a separate central UI thing.
        - Yes, v7 allows editing of lt in a form but I've decided to focus on one thing for this and not confuse it    
    - Set whether a field is visible or not to user
        - Some stock fields will never be able to be hidden, they will be "core" fields required for AyaNova operations and will have their hidden checkbox grayed out
    - Set whether a field custom or stock is required to have a value entered or have it's value changed
        - If required then it's like a business rule and treated just like that at the back and front end
        - During business rule validation check at backend it checks if the fields are required and have entries and returns a validation error if not exactly the same as for built in rules        
    - Ideally this would be a better feature if it was everywhere, not just in a limited set of objects but rather in all substantial objects
    - Client caches the customization data when it first opens the form and then checks if it's changed when it next opens the form
        - The route that fetches the FormCustom data needs to accept a query item that is a date or concurrency token so that 
        if nothing has changed the server returns the unchanged code or instead returns all the data if it is changed to save bandwidth
    - RAVEN custom fields start with 1 not zero like in v7
        - Import v7 custom0 to RAVEN custom1
    - SERVER HANDLING
        - Custom fields are stored *with* their associated record in a single TEXT column as a serialized JSON object
            - {c1:"blah",c2:"blah",c3:"blah".....c16:"blah"}
        - According to the docs https://www.postgresql.org/docs/9.1/datatype-character.html this is pretty efficient        
        - The server doesn't validate it or anything, just stores what the client provides and retrieves what the client needs and the client co-erces the value to the correct type
        - If a user changes the underlying objects type then the client must handle discrepencies and attempt to fix it.
            - So the client end must handle adapting the value if the type changes
    - Custom field types in v7
        - Currency
        - DateAndTime
        - TimeOnly
        - DateOnly
        - Number
        - Text
        - Bool 

   
## TODO

    -  #DONE# Need a FormCustom table and model to hold the user's form customization data
        - Like DataFilter, holds a JSON fragment in one field and the form key in another field
            - JSON FRAGMENT holds items that differ from stock, Hide not valid for non hideable core fields           
                - FieldKey "fld"
                - Hide "hide"
                - Required "required"
                - Type One of values from AyDataType but not tags or enum (bool, date, date time, decimal, number, picklist(FUTURE), and text)
             - e.g.: {template:[{fld:"ltkeyfieldname",hide:"true/false",required:"true/false", type:"bool"},{fld:"ltkeyfieldname",hide:"true/false",required:"true/false", type:"text"]}

    - #DONE# Need a FormAvailableFields static collection class that contains the fields available to each form
        - This should be independent from any other class tied to a particular route or controller or db table as it could be some or none of all of those things
        - Method: GetFields(FormKey): FieldKey (localekey), Hideable (bool), SharedLTKey (bool means it's not specific to that form), Custom (bool, means it's one of the custom fields that can be set to type etc)
        - Method: GetForms() returns a list of form names
        - Method: IsValidForm(string formKey) bool exists or not
        
      
    - #DONE# Need a FormCustom controller that supports routes for:
        - #DONE# Routes for customization form populating and receiving
            - GET (formkey), gets a FormOptions object that provides the basis for building the form customization view
                - Also required at the client is the current form customizations if any which can be gotten from the other route for day to day ops below                
            - POST (formkey), accepts a FormCustom object that contains the users customization choices only
                - Validation ensures "CORE" fields cannot be customized
                - Localization changes are NOT handled here even though it's the same client end form, that is handled at the CLIENT end after it has updated this part separately through regular localized text routes
                    - To ensure proper separation of concerns

        - #DONE# Routes for the day to day form display purposes that efficiently fetch the form customization to use on demand and caches at the client
            - (GET formkey, token): Given a formkey and an *optional* concurrency token, returns one of the following:
                - If no concurrency token or doesn't match the current db one then:
                    - a list of customized fields (not the non customized ones) so the client can display the UI correctly:
                        - Basically whatever is in the FormCustom table record for that formkey
                - If concurrency token provided and is unchanged then simply returns a code 304 (NOT MODIFIED)

        - #DONE# TESTS for the above!!!

    - #DONEPut custom fields into widget object or figure out how we will handle that aspect
    

EXISTING v7:
- 10 custom fields in   
    - Client
    - Contract
    - HeadOffice
    - LoanItem
    - Part
    - Project
    - PurchaseOrder
    - Unit
    - UnitModel
    - User
    - Vendor
    - WorkorderItem


RAVEN REQUIREMENTS / CHANGES


