diff --git a/devdocs/research.txt b/devdocs/old-devdocs/research.txt similarity index 100% rename from devdocs/research.txt rename to devdocs/old-devdocs/research.txt diff --git a/devdocs/solutions.txt b/devdocs/old-devdocs/solutions.txt similarity index 100% rename from devdocs/solutions.txt rename to devdocs/old-devdocs/solutions.txt diff --git a/devdocs/specs/admin-settings-business.txt b/devdocs/old-devdocs/specs/admin-settings-business.txt similarity index 93% rename from devdocs/specs/admin-settings-business.txt rename to devdocs/old-devdocs/specs/admin-settings-business.txt index 861bf79b..235f22f5 100644 --- a/devdocs/specs/admin-settings-business.txt +++ b/devdocs/old-devdocs/specs/admin-settings-business.txt @@ -1,6 +1,6 @@ -https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/3488 -Was all this stuff below, however, will be different in RAVEN - +https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/3488 +Was all this stuff below, however, will be different in RAVEN + ### ADMINISTRATION - *ONBOARDING / GUIDED SETUP diff --git a/devdocs/specs/admin-settings-system-operations.txt b/devdocs/old-devdocs/specs/admin-settings-system-operations.txt similarity index 98% rename from devdocs/specs/admin-settings-system-operations.txt rename to devdocs/old-devdocs/specs/admin-settings-system-operations.txt index 93f840f5..17851a04 100644 --- a/devdocs/specs/admin-settings-system-operations.txt +++ b/devdocs/old-devdocs/specs/admin-settings-system-operations.txt @@ -1 +1 @@ -https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/3488 +https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/3488 diff --git a/devdocs/specs/authentication.txt b/devdocs/old-devdocs/specs/authentication.txt similarity index 85% rename from devdocs/specs/authentication.txt rename to devdocs/old-devdocs/specs/authentication.txt index 9de31a3e..32272cf4 100644 --- a/devdocs/specs/authentication.txt +++ b/devdocs/old-devdocs/specs/authentication.txt @@ -1,3 +1,3 @@ -Authentication - - +Authentication + + diff --git a/devdocs/specs/client-group-deprecated.txt b/devdocs/old-devdocs/specs/client-group-deprecated.txt similarity index 96% rename from devdocs/specs/client-group-deprecated.txt rename to devdocs/old-devdocs/specs/client-group-deprecated.txt index 98fb3cb2..0df705d5 100644 --- a/devdocs/specs/client-group-deprecated.txt +++ b/devdocs/old-devdocs/specs/client-group-deprecated.txt @@ -1,2 +1,2 @@ -Replace client group with tags, see case 3441, 3373 - +Replace client group with tags, see case 3441, 3373 + diff --git a/devdocs/specs/client-service-requests.txt b/devdocs/old-devdocs/specs/client-service-requests.txt similarity index 50% rename from devdocs/specs/client-service-requests.txt rename to devdocs/old-devdocs/specs/client-service-requests.txt index d3f5a12f..8b137891 100644 --- a/devdocs/specs/client-service-requests.txt +++ b/devdocs/old-devdocs/specs/client-service-requests.txt @@ -1 +1 @@ - + diff --git a/devdocs/specs/clients.txt b/devdocs/old-devdocs/specs/clients.txt similarity index 97% rename from devdocs/specs/clients.txt rename to devdocs/old-devdocs/specs/clients.txt index 3f1aa8ed..542163f5 100644 --- a/devdocs/specs/clients.txt +++ b/devdocs/old-devdocs/specs/clients.txt @@ -1 +1 @@ -C:\data\code\raven\devdocs\specs\clients.txt +C:\data\code\raven\devdocs\specs\clients.txt diff --git a/devdocs/specs/core-attachments.txt b/devdocs/old-devdocs/specs/core-attachments.txt similarity index 94% rename from devdocs/specs/core-attachments.txt rename to devdocs/old-devdocs/specs/core-attachments.txt index 5219e9bf..a47fffc1 100644 --- a/devdocs/specs/core-attachments.txt +++ b/devdocs/old-devdocs/specs/core-attachments.txt @@ -1,19 +1,19 @@ -# Attachments specifications - -NOTE: This applies to all core business object types that are basically real world and have an id and a type (all are wikiable, attachable and reviewable) Not utility type objects like datalist etc - - -## TODO - - -- Need core dlToken route for not just attachments -- There should be a notification for ops if a file attachment is physically not found when it has a db record see Attachmentcontroller line 407 - -Download / upload security JWT info: -https://stackoverflow.com/questions/29452031/how-to-handle-file-downloads-with-jwt-based-authentication/43133108#43133108 -https://stackoverflow.com/questions/45763149/asp-net-core-jwt-in-uri-query-parameter/53295042 - -- V7 attached docs / embedded wiki file docs (case 3484) - - https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/3484 - - Both need to be combined into a single attachment when imported and in the new RAVEN. +# Attachments specifications + +NOTE: This applies to all core business object types that are basically real world and have an id and a type (all are wikiable, attachable and reviewable) Not utility type objects like datalist etc + + +## TODO + + +- Need core dlToken route for not just attachments +- There should be a notification for ops if a file attachment is physically not found when it has a db record see Attachmentcontroller line 407 + +Download / upload security JWT info: +https://stackoverflow.com/questions/29452031/how-to-handle-file-downloads-with-jwt-based-authentication/43133108#43133108 +https://stackoverflow.com/questions/45763149/asp-net-core-jwt-in-uri-query-parameter/53295042 + +- V7 attached docs / embedded wiki file docs (case 3484) + - https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/3484 + - Both need to be combined into a single attachment when imported and in the new RAVEN. - no more embedded wiki docs right? \ No newline at end of file diff --git a/devdocs/specs/core-backup-and-restore.txt b/devdocs/old-devdocs/specs/core-backup-and-restore.txt similarity index 96% rename from devdocs/specs/core-backup-and-restore.txt rename to devdocs/old-devdocs/specs/core-backup-and-restore.txt index 9902f10a..0c8aee5c 100644 --- a/devdocs/specs/core-backup-and-restore.txt +++ b/devdocs/old-devdocs/specs/core-backup-and-restore.txt @@ -1,53 +1,53 @@ -BACKUP AND RESTORE SPECS - -CASES - - -REQUIREMENTS - -BACKUP -- Backup to independent text format using JSON text files like DB DUMP and Discourse does -- Backup all attached files (encrypt?) -- Encrypt the backup file archive or each file (need to determine) so that the backup file can't be read independent of RAVEN - - Encryption key needs to be user selectable because we don't want any AyaNova user to be able to restore any other AyaNova users db - -- Optionally automatically send the backups to online destinations such as - - AWS web storage - - Dropbox - - Mailbox if under certain size - - Look into whatever apis are available for other online storage services -- Download backups -- Backup during closed window where server is not available for anything but read only operations during backup window -- User configurable backup time -- User configurable encryption key in environment variable? If not set then not encrypted?? - - - - -RESTORE -- Automatically closes api before RESTORE -- Restore from backup locations can save to? - - Or at least a method to fetch and list those backups to fetch to local? -- Upload a backup file for restoration -- Decrypts data during restore process - - Must use user provided key and there should be some kind of marker file or something to verify it decrypted properly and is a valid AyaNova backup -- Restore the attached files (decrypt?) -- Uses user configurable encryption key - -ROLES -- Ops ful, biz full can - - modify backup configuration - - Restore - - Backup - -- OpsLImited and biz limited can - - view the backup and restore configuration - - Backup - - - - - - - - +BACKUP AND RESTORE SPECS + +CASES + + +REQUIREMENTS + +BACKUP +- Backup to independent text format using JSON text files like DB DUMP and Discourse does +- Backup all attached files (encrypt?) +- Encrypt the backup file archive or each file (need to determine) so that the backup file can't be read independent of RAVEN + - Encryption key needs to be user selectable because we don't want any AyaNova user to be able to restore any other AyaNova users db + +- Optionally automatically send the backups to online destinations such as + - AWS web storage + - Dropbox + - Mailbox if under certain size + - Look into whatever apis are available for other online storage services +- Download backups +- Backup during closed window where server is not available for anything but read only operations during backup window +- User configurable backup time +- User configurable encryption key in environment variable? If not set then not encrypted?? + + + + +RESTORE +- Automatically closes api before RESTORE +- Restore from backup locations can save to? + - Or at least a method to fetch and list those backups to fetch to local? +- Upload a backup file for restoration +- Decrypts data during restore process + - Must use user provided key and there should be some kind of marker file or something to verify it decrypted properly and is a valid AyaNova backup +- Restore the attached files (decrypt?) +- Uses user configurable encryption key + +ROLES +- Ops ful, biz full can + - modify backup configuration + - Restore + - Backup + +- OpsLImited and biz limited can + - view the backup and restore configuration + - Backup + + + + + + + + diff --git a/devdocs/specs/core-check-for-updates.txt b/devdocs/old-devdocs/specs/core-check-for-updates.txt similarity index 98% rename from devdocs/specs/core-check-for-updates.txt rename to devdocs/old-devdocs/specs/core-check-for-updates.txt index 645d03a6..98ef3573 100644 --- a/devdocs/specs/core-check-for-updates.txt +++ b/devdocs/old-devdocs/specs/core-check-for-updates.txt @@ -1,10 +1,10 @@ -CHECK AND UPDATE SPECS - -REQUIREMENTS - -- Must confirm current RAVEN is licensed before checking for updates with a current and valid support and updates license - - We don't want people to initiate an update if they aren't eligable - - We also don't want Raven to allow it to run if the new code was built after the current support and updates in the license expired - - Check internal license - - Check externally with Rockfish if licensed - - Probably best if it just has an update check route to Rockfish where it feeds license serial number (obfuscated?) to Rockfish so it can see which license it is currently using +CHECK AND UPDATE SPECS + +REQUIREMENTS + +- Must confirm current RAVEN is licensed before checking for updates with a current and valid support and updates license + - We don't want people to initiate an update if they aren't eligable + - We also don't want Raven to allow it to run if the new code was built after the current support and updates in the license expired + - Check internal license + - Check externally with Rockfish if licensed + - Probably best if it just has an update check route to Rockfish where it feeds license serial number (obfuscated?) to Rockfish so it can see which license it is currently using diff --git a/devdocs/specs/core-custom-fields.txt b/devdocs/old-devdocs/specs/core-custom-fields.txt similarity index 86% rename from devdocs/specs/core-custom-fields.txt rename to devdocs/old-devdocs/specs/core-custom-fields.txt index 91a4b91b..6fcf3cf1 100644 --- a/devdocs/specs/core-custom-fields.txt +++ b/devdocs/old-devdocs/specs/core-custom-fields.txt @@ -1,7 +1,7 @@ -# Custom fields specifications - - -16 custom fields for most object -custom fields can be returned in datalists -Custom fields cannot be sorted or filtered since they don't really exist in the db +# Custom fields specifications + + +16 custom fields for most object +custom fields can be returned in datalists +Custom fields cannot be sorted or filtered since they don't really exist in the db AyaNova will do it's best to show them in a grid view and on reports in the format chosen by user \ No newline at end of file diff --git a/devdocs/specs/core-customize-form-fields.txt b/devdocs/old-devdocs/specs/core-customize-form-fields.txt similarity index 98% rename from devdocs/specs/core-customize-form-fields.txt rename to devdocs/old-devdocs/specs/core-customize-form-fields.txt index 60f2d0a6..0d33d28a 100644 --- a/devdocs/specs/core-customize-form-fields.txt +++ b/devdocs/old-devdocs/specs/core-customize-form-fields.txt @@ -1,108 +1,108 @@ -# 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 - - +# 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 + + diff --git a/devdocs/specs/core-display-format-template-system.txt b/devdocs/old-devdocs/specs/core-display-format-template-system.txt similarity index 98% rename from devdocs/specs/core-display-format-template-system.txt rename to devdocs/old-devdocs/specs/core-display-format-template-system.txt index 9393b3a6..426764b4 100644 --- a/devdocs/specs/core-display-format-template-system.txt +++ b/devdocs/old-devdocs/specs/core-display-format-template-system.txt @@ -1,86 +1,86 @@ -DISPLAY FORMAT TEMPLATE SYSTEM SPECS - - - - - -************** DEPRECATED EVERYTHING BELOW ********************************** - - - - - - - -OVERVIEW -RAVEN uses a user customizable template to determine what fields in which order get sent to the client when they display a list or select from a drop down - - FILTER / SORT: The templating is ENTIRELY separate from the filtering and sorting code which is already coded sufficiently and is a separate thing - - Users with BIZ rights can set the template - - There is one template per list (not user based but global in nature) - - Template affects both "MINI" single column display of list for small devices and "FULL" format wide mode with multiple columns for larger devices - - In MINI list format displays they choose which columns go into the one single column for display that is returned - - In FULL list format display they choose which columns are returned and which order separately from MINI format display - -Narrow grids on small screens as well as picklists need to show a single field of information as required by that shop for selection, recognition etc so templated to format multiple return fields into one -Grids need a way to ensure you can see what you need on small devices as well they need to show the columns desired on larger devices -PickLists need a way to format what is returned for picking (with template) - -Display format template (aka name display format) templates are used for THREE purposes: - - to customize what is shown in XS (<600px) single column grid and inside forms in drop down boxes order for a user to identify a record uniquely for selection purposes. - - To select which columns and in which order display on the grid in > 600px sizes - - To limit bandwidth used by selecting only the necessary columns - -This is used for both small form factor grids (see core-main-grids.txt) i.e. on a phone as the only column displayed -This is also used for picklists inside forms like drop down boxes etc - -CASES -none relevant - - -REQUIREMENTS - -Client - - Template editor: - - One area is for what goes into a single column in "MINI" mode for that list - - Another separate area on the same form is for selecting which columns are returned in a wide list and in what order - - Everyone gets the same template selections, i.e. there is only one template per list type - - This differs from v7 in which each user could select the columns to display and the order but then they needed to for filtering and sort order and stuff - - Main grid lists < 600px show only a single column based on template - - Selection drop down boxes in forms for selecting other objects - - Template editor under global settings for all main list objects - - Warning displayed to client if they select more than 16 columns to send out about bandwidth usage and slowness over slower connections - - -Server - - List of templates with their column selections - - For client editor - - For server to process what the query and send for lists - - List of fields available for templates for client and server validation etc - - Caching likely useful as server will need to deal with templates constantly as users fetch almost any list or combo box source etc - - Has to be very peformant as it will be doing this a lot - - SERVER handles composing the list object name display, NOT the client - - This saves bandwidth - - Incurrs more computing ops at the server but bandwidth is more expensive than server power all around - - Clients could be shitty and slow, this elminates that prospect - - Easier to code in c# than in javascript! ;) - - PICKLISTS and RIGHTS - - Initially I had picklist objects with just name and id and anyone could fetch them of any role, however, this isn't right and - - I'm leaving the rights up to the case by case basis and will address it when the client dev drives a requirement for it - - I'm thinking if people don't want a field exposed in mini list then don't put it into the template - -Back AND front end - - Need to handle changes in fields gracefully i.e. a new field added in an update, a field removed in an update cleans out the template when detected etc - - REPORTS (FUTURE) Should send the customized templated display name field to the reports as well as all the regular including name fields - - This is because users will likely want that for many reports - - Kind of a calculated field - - Default templates come with Raven, user can customize further - -MOCK TEMPLATE -{ - full:[ -ltKey,ltKey2,ltkey3 - ], - mini:[ - ltKey, ltkey2, ltkey3 - ] +DISPLAY FORMAT TEMPLATE SYSTEM SPECS + + + + + +************** DEPRECATED EVERYTHING BELOW ********************************** + + + + + + + +OVERVIEW +RAVEN uses a user customizable template to determine what fields in which order get sent to the client when they display a list or select from a drop down + - FILTER / SORT: The templating is ENTIRELY separate from the filtering and sorting code which is already coded sufficiently and is a separate thing + - Users with BIZ rights can set the template + - There is one template per list (not user based but global in nature) + - Template affects both "MINI" single column display of list for small devices and "FULL" format wide mode with multiple columns for larger devices + - In MINI list format displays they choose which columns go into the one single column for display that is returned + - In FULL list format display they choose which columns are returned and which order separately from MINI format display + +Narrow grids on small screens as well as picklists need to show a single field of information as required by that shop for selection, recognition etc so templated to format multiple return fields into one +Grids need a way to ensure you can see what you need on small devices as well they need to show the columns desired on larger devices +PickLists need a way to format what is returned for picking (with template) + +Display format template (aka name display format) templates are used for THREE purposes: + - to customize what is shown in XS (<600px) single column grid and inside forms in drop down boxes order for a user to identify a record uniquely for selection purposes. + - To select which columns and in which order display on the grid in > 600px sizes + - To limit bandwidth used by selecting only the necessary columns + +This is used for both small form factor grids (see core-main-grids.txt) i.e. on a phone as the only column displayed +This is also used for picklists inside forms like drop down boxes etc + +CASES +none relevant + + +REQUIREMENTS + +Client + - Template editor: + - One area is for what goes into a single column in "MINI" mode for that list + - Another separate area on the same form is for selecting which columns are returned in a wide list and in what order + - Everyone gets the same template selections, i.e. there is only one template per list type + - This differs from v7 in which each user could select the columns to display and the order but then they needed to for filtering and sort order and stuff + - Main grid lists < 600px show only a single column based on template + - Selection drop down boxes in forms for selecting other objects + - Template editor under global settings for all main list objects + - Warning displayed to client if they select more than 16 columns to send out about bandwidth usage and slowness over slower connections + + +Server + - List of templates with their column selections + - For client editor + - For server to process what the query and send for lists + - List of fields available for templates for client and server validation etc + - Caching likely useful as server will need to deal with templates constantly as users fetch almost any list or combo box source etc + - Has to be very peformant as it will be doing this a lot + - SERVER handles composing the list object name display, NOT the client + - This saves bandwidth + - Incurrs more computing ops at the server but bandwidth is more expensive than server power all around + - Clients could be shitty and slow, this elminates that prospect + - Easier to code in c# than in javascript! ;) + - PICKLISTS and RIGHTS + - Initially I had picklist objects with just name and id and anyone could fetch them of any role, however, this isn't right and + - I'm leaving the rights up to the case by case basis and will address it when the client dev drives a requirement for it + - I'm thinking if people don't want a field exposed in mini list then don't put it into the template + +Back AND front end + - Need to handle changes in fields gracefully i.e. a new field added in an update, a field removed in an update cleans out the template when detected etc + - REPORTS (FUTURE) Should send the customized templated display name field to the reports as well as all the regular including name fields + - This is because users will likely want that for many reports + - Kind of a calculated field + - Default templates come with Raven, user can customize further + +MOCK TEMPLATE +{ + full:[ +ltKey,ltKey2,ltkey3 + ], + mini:[ + ltKey, ltkey2, ltkey3 + ] } \ No newline at end of file diff --git a/devdocs/specs/core-documentation.txt b/devdocs/old-devdocs/specs/core-documentation.txt similarity index 98% rename from devdocs/specs/core-documentation.txt rename to devdocs/old-devdocs/specs/core-documentation.txt index b395d20a..8ed1f4f6 100644 --- a/devdocs/specs/core-documentation.txt +++ b/devdocs/old-devdocs/specs/core-documentation.txt @@ -1,46 +1,46 @@ -Documentation - -HELP MANUAL POINTS TO CONSIDER - -ONBOARDING - - The manual and/or guides and/or built into UI guided help needs to answer all the specific questions people have when onboarding - - For example a section for technicians, dispatcher, each business role and then under that answers to basic questions: - - How do I see my workorders that are open - - How do I see who is where today - - How do order inventory - - The old manual and guide weren't job and task oriented so it doesn't directly answer questions people have, - it just shows how to use features which isn't the way people approach it when familiarizing themselves. - -PRE-SALES - - Similar to onboarding but a higher level view, just basically answering the questions "Can it do XXX??" - - Perhaps it's the same as onboarding but you have to click through for ever increasing detail so you can abandon once your question is answered - - - - - - -- User docs and manual written in Markdown format (commonmark). -- MKDOCS tool used to generate static html "site" for docs -- Docs versioned into folders by major/minor version, so different docs for 8.1 and again different for 8.2. Patch revisions don't change docs. -- Static docs site incorporated into AyaNova backend so can view the docs for that release inside it directly. -- Docs written in parallel with development as per agile principles so as soon as a feature is added it's documented as well. - -## Markdown for documentation -- [Commonmark cheat sheat](http://commonmark.org/help/) -- [Commonmark testing 'dingus'](http://commonmark.org/help/) -- Convert markdown to other formats with this tool http://pandoc.org/ - - Useful for standalone docs maybe - -- Auto generate a static site from markdown docs with this developer tool: http://www.mkdocs.org/ -- Material theme for MKDOCS https://squidfunk.github.io/mkdocs-material/ -- MKDocs WIKI (themes, solutions to tricky things etc) https://github.com/mkdocs/mkdocs/wiki - -** MKDOCS ** -- HOW TO RUN IT: python -m mkdocs serve to run the server, python -m mkdocs build to build the site -- package is tragically out of date on my debian, have to install manually -- Already had Python 2.7.13 (mkdocs page says 2.7.2 in it's example but 2.7 is ok) -- didn't have PIP so have to get that, selected python-pip in synaptic (v9.0.1-2) -- Installed mkdoc by running pip install mkdoc -- apparently not in path have to preface command with python like so: python -m mkdocs new ayanova -- Also installed the Material theme which looks a lot nicer +Documentation + +HELP MANUAL POINTS TO CONSIDER + +ONBOARDING + - The manual and/or guides and/or built into UI guided help needs to answer all the specific questions people have when onboarding + - For example a section for technicians, dispatcher, each business role and then under that answers to basic questions: + - How do I see my workorders that are open + - How do I see who is where today + - How do order inventory + - The old manual and guide weren't job and task oriented so it doesn't directly answer questions people have, + it just shows how to use features which isn't the way people approach it when familiarizing themselves. + +PRE-SALES + - Similar to onboarding but a higher level view, just basically answering the questions "Can it do XXX??" + - Perhaps it's the same as onboarding but you have to click through for ever increasing detail so you can abandon once your question is answered + + + + + + +- User docs and manual written in Markdown format (commonmark). +- MKDOCS tool used to generate static html "site" for docs +- Docs versioned into folders by major/minor version, so different docs for 8.1 and again different for 8.2. Patch revisions don't change docs. +- Static docs site incorporated into AyaNova backend so can view the docs for that release inside it directly. +- Docs written in parallel with development as per agile principles so as soon as a feature is added it's documented as well. + +## Markdown for documentation +- [Commonmark cheat sheat](http://commonmark.org/help/) +- [Commonmark testing 'dingus'](http://commonmark.org/help/) +- Convert markdown to other formats with this tool http://pandoc.org/ + - Useful for standalone docs maybe + +- Auto generate a static site from markdown docs with this developer tool: http://www.mkdocs.org/ +- Material theme for MKDOCS https://squidfunk.github.io/mkdocs-material/ +- MKDocs WIKI (themes, solutions to tricky things etc) https://github.com/mkdocs/mkdocs/wiki + +** MKDOCS ** +- HOW TO RUN IT: python -m mkdocs serve to run the server, python -m mkdocs build to build the site +- package is tragically out of date on my debian, have to install manually +- Already had Python 2.7.13 (mkdocs page says 2.7.2 in it's example but 2.7 is ok) +- didn't have PIP so have to get that, selected python-pip in synaptic (v9.0.1-2) +- Installed mkdoc by running pip install mkdoc +- apparently not in path have to preface command with python like so: python -m mkdocs new ayanova +- Also installed the Material theme which looks a lot nicer diff --git a/devdocs/specs/core-email-ops.txt b/devdocs/old-devdocs/specs/core-email-ops.txt similarity index 95% rename from devdocs/specs/core-email-ops.txt rename to devdocs/old-devdocs/specs/core-email-ops.txt index 524261b7..f4e89d07 100644 --- a/devdocs/specs/core-email-ops.txt +++ b/devdocs/old-devdocs/specs/core-email-ops.txt @@ -1,18 +1,18 @@ -EMAIL OPS SPECS - -CASES - - - -REQUIREMENTS - - -- Supports notifications via generator - -- Needs to deliver email - - Plain text, probably not html for now - - Attachments are a possibility and should be allowed for - - A simple api that can be called by generator and others as necessary - - -- FUTURE: some future features may require reading email as well +EMAIL OPS SPECS + +CASES + + + +REQUIREMENTS + + +- Supports notifications via generator + +- Needs to deliver email + - Plain text, probably not html for now + - Attachments are a possibility and should be allowed for + - A simple api that can be called by generator and others as necessary + + +- FUTURE: some future features may require reading email as well diff --git a/devdocs/specs/core-generator.txt b/devdocs/old-devdocs/specs/core-generator.txt similarity index 98% rename from devdocs/specs/core-generator.txt rename to devdocs/old-devdocs/specs/core-generator.txt index 3ce97aea..05ec66f4 100644 --- a/devdocs/specs/core-generator.txt +++ b/devdocs/old-devdocs/specs/core-generator.txt @@ -1,110 +1,110 @@ -GENERATOR SPECS - -CASES - - - -REQUIREMENTS - - -- Is accessible from OPERATIONS endpoint see core-long-running-operations.txt - - -Use db table OPERATIONS queue to submit jobs for generator to handle. - -Generator looks in table periodically for work to do and if the criteria matches starts the job by calling out to the submitting code - - Generator is only concerned with the job starting and ending and logging, that kind of thing, it does no work on it's own directly - - Start date time - - Is api locked and can it run when api is locked - - Is job exclusive, i.e. no other jobs while it's running and or api is locked - - Updates into a operationstatus table and endpoint that is open when api is locked - - Deletes status succeeded operations and their operationstatus entries after 24 hours automatically - - Deletes status FAILED operations and their logs after 2 weeks automatically - - New jobs cannot be submitted via the rest api when the REST interface is locked but it can be queried to see what is happening - - Hands off completed jobs back to submitter for resolution - - I.E. if a workorder was generated from a PM then it goes back to the PM and says "DONE THIS JOB" or "FAILED THIS JOB" and the PM code handles resubmitting a new job for next time - - This way generator does less and isn't responsible for hairy complex code that is best handled at the source of the job - - - JOB is actually handed off back to the object that submitted it into the db in the first place to do the work - - i.e. generator sees a send notification job for a workorder status change, it is ready to go so it in turn passes the job ID or info back to the workorder-process-notification code to handle and takes back the result - - i.e. a workorder may submit a "notify users about status change" job, generator sees it and in turn calls notify users code in workorder which in turn creates new jobs to send each email - generator then sees send email jobs and in each case hands them off to the email processor to deal with - - - - -TODO GO THROUGH GENERATOR CASES AND v7 GENERATOR CODE, COMPILE A LIST OF WHAT GENERATOR NEEDS TO DO - - Need a list of everything RAVEN generator will need to do - - BREAK out into small separate concerns - - Make a spec doc for each separate concern (i.e. one for the process loop, one for the LRO stuff, one for the physical delivery etc) - - -JOBSWEEPER - - Need a maintenance job class that handles periodic routine internal maintenance CoreJobManager - - Submits and handles or hands off routine jobs - - Clean up database (look for orphaned records) CoreJobDBMaintenance - - Check for license maybe or check license validity? (had some plan to automatically pull license from rockfish, to accomodate monthly rentals) CoreJobLicenseCheck - - Clear out completed jobs CoreJobSweeper - - Probably dozens of other things - -NOTIFICATION SWEEPER - - Maintains notifications tables: cleans out old ones, finds ones that are "stuck", notifies OPS about weirdness if found, removes undeliverable ones, counts retries etc - - - -RAVEN JOB SEQUENCE OF OPERATIONS - -Hypothetical Widget UPdated notification job - - Widget UPdated - - Calls into notification code in WidgetBiz or JobObject or maybe INotifyObject to see if it should create a notification - - - - -HOW AND WHAT v7 GENERATOR DOES - -These functions are called every 5 minutes by Generate in Winform desktop standalone. -- GenProcessPM.GeneratePMWorkorders(); -- GenProcessDeliveries.DeliverNotifications(); -- GenProcessClientNotifications.DeliverNotifications(); - - -GeneratePMWorkorders - - Calls for a list of pm id's of not expired and generate on date in future (for some reason it's just in future, not a specific time range, seems buggy) - - Taks the list of id's and passes them to workorder generate from pm which in turn... - - Workorder.cs Makes workorders from PM workorders copying pm wo data into service wo data - - Workorder.cs After making the service workorder the last bit of code calculates the next pm date and then adjusts the source pm to the next date - -DeliverNotifications (techs) - - Get a list via notificationlist : - // List of notifications formatted for delivery - /// and screened to be deliverable - /// - /// - /// - /// Loops through all NotifyEvenRecords - /// For pending type events, checks to see if within users selected notification window - /// foreach NotifyEventRecord it adds a NotificationListInfo - /// for each open delivery window for each subscriber to that event - /// As it Processes each deliverable notification it formats it to users - /// translation and preferences for size etc and keeps track of the address and - /// delivery type. - /// - /// - /// End result is a list ready to deliver. - /// As each one is delivered Ok it should be deleted from the NotifyEvent table by the - /// delivery Process that uses this list. - - Iterate the list and depending on deliver via method required: - - SMS (smtp) - - SMTP (email) - - POPUP - - AYANOVA MEMO - - Log delivery and remove event after each item is delivered individually - - -DeliverNotifications (clients) - - Gets a list of client notifications that are ready to deliver (they hold the entire message in EML format) - - Attempts smtp server connection, if a problem then logs it and optionally, based on global setting, will bail and retry again later, otherwise proceeds through code which in turn deletes each notification it can't deliver - - Delivers via smtp, if fail logs failure. Either way deletes the notification so it's gone forever - - +GENERATOR SPECS + +CASES + + + +REQUIREMENTS + + +- Is accessible from OPERATIONS endpoint see core-long-running-operations.txt + + +Use db table OPERATIONS queue to submit jobs for generator to handle. + +Generator looks in table periodically for work to do and if the criteria matches starts the job by calling out to the submitting code + - Generator is only concerned with the job starting and ending and logging, that kind of thing, it does no work on it's own directly + - Start date time + - Is api locked and can it run when api is locked + - Is job exclusive, i.e. no other jobs while it's running and or api is locked + - Updates into a operationstatus table and endpoint that is open when api is locked + - Deletes status succeeded operations and their operationstatus entries after 24 hours automatically + - Deletes status FAILED operations and their logs after 2 weeks automatically + - New jobs cannot be submitted via the rest api when the REST interface is locked but it can be queried to see what is happening + - Hands off completed jobs back to submitter for resolution + - I.E. if a workorder was generated from a PM then it goes back to the PM and says "DONE THIS JOB" or "FAILED THIS JOB" and the PM code handles resubmitting a new job for next time + - This way generator does less and isn't responsible for hairy complex code that is best handled at the source of the job + + - JOB is actually handed off back to the object that submitted it into the db in the first place to do the work + - i.e. generator sees a send notification job for a workorder status change, it is ready to go so it in turn passes the job ID or info back to the workorder-process-notification code to handle and takes back the result + - i.e. a workorder may submit a "notify users about status change" job, generator sees it and in turn calls notify users code in workorder which in turn creates new jobs to send each email + generator then sees send email jobs and in each case hands them off to the email processor to deal with + + + + +TODO GO THROUGH GENERATOR CASES AND v7 GENERATOR CODE, COMPILE A LIST OF WHAT GENERATOR NEEDS TO DO + - Need a list of everything RAVEN generator will need to do + - BREAK out into small separate concerns + - Make a spec doc for each separate concern (i.e. one for the process loop, one for the LRO stuff, one for the physical delivery etc) + + +JOBSWEEPER + - Need a maintenance job class that handles periodic routine internal maintenance CoreJobManager + - Submits and handles or hands off routine jobs + - Clean up database (look for orphaned records) CoreJobDBMaintenance + - Check for license maybe or check license validity? (had some plan to automatically pull license from rockfish, to accomodate monthly rentals) CoreJobLicenseCheck + - Clear out completed jobs CoreJobSweeper + - Probably dozens of other things + +NOTIFICATION SWEEPER + - Maintains notifications tables: cleans out old ones, finds ones that are "stuck", notifies OPS about weirdness if found, removes undeliverable ones, counts retries etc + + + +RAVEN JOB SEQUENCE OF OPERATIONS + +Hypothetical Widget UPdated notification job + - Widget UPdated + - Calls into notification code in WidgetBiz or JobObject or maybe INotifyObject to see if it should create a notification + + + + +HOW AND WHAT v7 GENERATOR DOES + +These functions are called every 5 minutes by Generate in Winform desktop standalone. +- GenProcessPM.GeneratePMWorkorders(); +- GenProcessDeliveries.DeliverNotifications(); +- GenProcessClientNotifications.DeliverNotifications(); + + +GeneratePMWorkorders + - Calls for a list of pm id's of not expired and generate on date in future (for some reason it's just in future, not a specific time range, seems buggy) + - Taks the list of id's and passes them to workorder generate from pm which in turn... + - Workorder.cs Makes workorders from PM workorders copying pm wo data into service wo data + - Workorder.cs After making the service workorder the last bit of code calculates the next pm date and then adjusts the source pm to the next date + +DeliverNotifications (techs) + - Get a list via notificationlist : + // List of notifications formatted for delivery + /// and screened to be deliverable + /// + /// + /// + /// Loops through all NotifyEvenRecords + /// For pending type events, checks to see if within users selected notification window + /// foreach NotifyEventRecord it adds a NotificationListInfo + /// for each open delivery window for each subscriber to that event + /// As it Processes each deliverable notification it formats it to users + /// translation and preferences for size etc and keeps track of the address and + /// delivery type. + /// + /// + /// End result is a list ready to deliver. + /// As each one is delivered Ok it should be deleted from the NotifyEvent table by the + /// delivery Process that uses this list. + - Iterate the list and depending on deliver via method required: + - SMS (smtp) + - SMTP (email) + - POPUP + - AYANOVA MEMO + - Log delivery and remove event after each item is delivered individually + + +DeliverNotifications (clients) + - Gets a list of client notifications that are ready to deliver (they hold the entire message in EML format) + - Attempts smtp server connection, if a problem then logs it and optionally, based on global setting, will bail and retry again later, otherwise proceeds through code which in turn deletes each notification it can't deliver + - Delivers via smtp, if fail logs failure. Either way deletes the notification so it's gone forever + + diff --git a/devdocs/specs/core-import-v7.txt b/devdocs/old-devdocs/specs/core-import-v7.txt similarity index 97% rename from devdocs/specs/core-import-v7.txt rename to devdocs/old-devdocs/specs/core-import-v7.txt index 5167f84b..92c620c3 100644 --- a/devdocs/specs/core-import-v7.txt +++ b/devdocs/old-devdocs/specs/core-import-v7.txt @@ -1,97 +1,97 @@ -IMPORT FROM V7 SPECS - -CASES -- https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/3503 - - -REQUIREMENTS - -- EMPTY DESTINATION DATABASE - IMPORTER will assume there is no pre-existing data that can conflict - - DB MUST BE ERASED FIRST OR IMPORT WILL FAIL (excluding fundamental things like license key, stock locales etc) -- LImited area of concern: rather than trying to do all types of import, I'm going to write this as if it's all for v7 only - - only when I write the next importer will I see if there are any savings of combining objects, but for now small classes with single responsibility -- Import v7 data into RAVEN via datadump plugin for v7 -- ROUTE: endpoint to allow upload of v7 datadump zip file . -- ROUTE: endpoint to allow delete of uploaded datadump file. -- ROUTE: endpoint to Show list of datadump files uploaded. -- ROUTE: endpoint to trigger non-selective import of specified datadump file (import all) - -- FUTURE - ROUTE: endpoint to download a picklist collection of objects found in dump suitable for user to then select specific objects (or type of objects) to import -- FUTURE - ROUTE: endpoint to trigger selective import from an uploaded datadump file - - future thing if required because user always has option of editing zip file and removing what is not required to be imported - - Supports specifying what to import so can just pick clients or something. - - Pick by name of folder I guess within zip since each object type is in it's own folder - - -- IMPORT - - user selects all or collection of folders to import from zip - - User is returned a jobid that the client can use to display the activity log - - Importer opens the archive file and iterates the folders - - Each type of object has a corresponding biz object that handles importing that type - - So, for example, each client json is handed off to a corresponding ClientBiz for import - - Importer updates the opslog as it's doing the import with summary information (3 clients imported successfully etc) -- Should close api while it's doing the import. -- Datadump files should be in backup files folder - - -ROLES -- Ops ful, biz full can submit jobs -- OpsLImited and biz limited can view the jobs (already coded) - - -OBJECTS - - [ImportAyaNova7Controller] - - [ImportAyaNova7Biz] object to back controller routes, submit job, run job and pass off import to each biz object in turn that implements: - - [IImportAyaNova7Object] interface for each biz object (e.g. ClientBiz) - - Import(AyaTypeAndID,JSONDATAfromimportfile) - - - - -OPERATION SEQUENCE - -The upload / delete / show list of datadump files part is standard api stuff and doesn't need special handling nor locking the server -Importing - - Triggered by ops user remotely by selecting datadump file for import - - - - -SCHEMA - - -- It would be helpful to have a importmap table that is used temporarily during import to store a map of v7Guid's with their imported RAVEN type and id -- This way it can be a lookup table to quickly set other imported data, i.e. client id's to match to units being imported. -IMPORTMAP - - AType - - ObjectId - - v7Guid - - - -NOTES FOR DOCS -- Only an empty database is supported for import -- Only one shot import, can't import again later -- LOCALES - - MUST be a default translation set before import because new raven keys will be added to imported v7 translation using the default translation only -- IMPORTED USERS - - In order to ensure security imported users are not imported ready to login but rather must be edited individually after import: - - All users are imported with Active status set to false and must be individually edited and set to Active=true as required - - login and passwords are not imported and need to be individually set after import as required - - no Authorization Role is set and therefore no rights to anything. A role needs to be set after import for each user -- TAGS, the following objects are imported as tags and suffixed with a period and then short versions of the object type in the tag name - - Region - - UnitModelCategory - - UnitServiceType - - WorkOrderItemType - - ClientGroup - - WorkorderCategory - - PartCategory - - DispatchZone - - ScheduleableUserGroup - - ClientNoteType - - -- CUSTOM FIELDS - - RAVEN custom fields start with 1 not zero like in v7 - - Import v7 custom0 to RAVEN custom1 +IMPORT FROM V7 SPECS + +CASES +- https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/3503 + + +REQUIREMENTS + +- EMPTY DESTINATION DATABASE - IMPORTER will assume there is no pre-existing data that can conflict + - DB MUST BE ERASED FIRST OR IMPORT WILL FAIL (excluding fundamental things like license key, stock locales etc) +- LImited area of concern: rather than trying to do all types of import, I'm going to write this as if it's all for v7 only + - only when I write the next importer will I see if there are any savings of combining objects, but for now small classes with single responsibility +- Import v7 data into RAVEN via datadump plugin for v7 +- ROUTE: endpoint to allow upload of v7 datadump zip file . +- ROUTE: endpoint to allow delete of uploaded datadump file. +- ROUTE: endpoint to Show list of datadump files uploaded. +- ROUTE: endpoint to trigger non-selective import of specified datadump file (import all) + +- FUTURE - ROUTE: endpoint to download a picklist collection of objects found in dump suitable for user to then select specific objects (or type of objects) to import +- FUTURE - ROUTE: endpoint to trigger selective import from an uploaded datadump file + - future thing if required because user always has option of editing zip file and removing what is not required to be imported + - Supports specifying what to import so can just pick clients or something. + - Pick by name of folder I guess within zip since each object type is in it's own folder + + +- IMPORT + - user selects all or collection of folders to import from zip + - User is returned a jobid that the client can use to display the activity log + - Importer opens the archive file and iterates the folders + - Each type of object has a corresponding biz object that handles importing that type + - So, for example, each client json is handed off to a corresponding ClientBiz for import + - Importer updates the opslog as it's doing the import with summary information (3 clients imported successfully etc) +- Should close api while it's doing the import. +- Datadump files should be in backup files folder + + +ROLES +- Ops ful, biz full can submit jobs +- OpsLImited and biz limited can view the jobs (already coded) + + +OBJECTS + - [ImportAyaNova7Controller] + - [ImportAyaNova7Biz] object to back controller routes, submit job, run job and pass off import to each biz object in turn that implements: + - [IImportAyaNova7Object] interface for each biz object (e.g. ClientBiz) + - Import(AyaTypeAndID,JSONDATAfromimportfile) + + + + +OPERATION SEQUENCE + +The upload / delete / show list of datadump files part is standard api stuff and doesn't need special handling nor locking the server +Importing + - Triggered by ops user remotely by selecting datadump file for import + + + + +SCHEMA + + +- It would be helpful to have a importmap table that is used temporarily during import to store a map of v7Guid's with their imported RAVEN type and id +- This way it can be a lookup table to quickly set other imported data, i.e. client id's to match to units being imported. +IMPORTMAP + - AType + - ObjectId + - v7Guid + + + +NOTES FOR DOCS +- Only an empty database is supported for import +- Only one shot import, can't import again later +- LOCALES + - MUST be a default translation set before import because new raven keys will be added to imported v7 translation using the default translation only +- IMPORTED USERS + - In order to ensure security imported users are not imported ready to login but rather must be edited individually after import: + - All users are imported with Active status set to false and must be individually edited and set to Active=true as required + - login and passwords are not imported and need to be individually set after import as required + - no Authorization Role is set and therefore no rights to anything. A role needs to be set after import for each user +- TAGS, the following objects are imported as tags and suffixed with a period and then short versions of the object type in the tag name + - Region + - UnitModelCategory + - UnitServiceType + - WorkOrderItemType + - ClientGroup + - WorkorderCategory + - PartCategory + - DispatchZone + - ScheduleableUserGroup + - ClientNoteType + + +- CUSTOM FIELDS + - RAVEN custom fields start with 1 not zero like in v7 + - Import v7 custom0 to RAVEN custom1 diff --git a/devdocs/specs/core-installation.txt b/devdocs/old-devdocs/specs/core-installation.txt similarity index 96% rename from devdocs/specs/core-installation.txt rename to devdocs/old-devdocs/specs/core-installation.txt index d4671bf4..d66da0ff 100644 --- a/devdocs/specs/core-installation.txt +++ b/devdocs/old-devdocs/specs/core-installation.txt @@ -1,4 +1,4 @@ -# Installer / installation specifications - - -Several environment variables need to be set by the installer. +# Installer / installation specifications + + +Several environment variables need to be set by the installer. diff --git a/devdocs/specs/core-internationalization.txt b/devdocs/old-devdocs/specs/core-internationalization.txt similarity index 93% rename from devdocs/specs/core-internationalization.txt rename to devdocs/old-devdocs/specs/core-internationalization.txt index 73892a8b..e6a06fd2 100644 --- a/devdocs/specs/core-internationalization.txt +++ b/devdocs/old-devdocs/specs/core-internationalization.txt @@ -1,15 +1,15 @@ -# Internationalization specifications - -DATES, TIMES, CURRENCY, (RTL?) - -REQUIREMENTS - - Client does *ALL* internationalization display locally, only exception is the server ops logs - - This saves bandwidth and hassle and leaves presentation to the client where it belongs (was a source of trouble in v7) - - User options contain the date, timezone and currency format for presentation purposes - - API data is in as neutral a format as possible, i.e. ISO whatever it is for dates and times, currency is just a number? (not going multicurrency?) - - CALENDARS - - Only the Gregorian calendar is supported - - USEFUL INFO +# Internationalization specifications + +DATES, TIMES, CURRENCY, (RTL?) + +REQUIREMENTS + - Client does *ALL* internationalization display locally, only exception is the server ops logs + - This saves bandwidth and hassle and leaves presentation to the client where it belongs (was a source of trouble in v7) + - User options contain the date, timezone and currency format for presentation purposes + - API data is in as neutral a format as possible, i.e. ISO whatever it is for dates and times, currency is just a number? (not going multicurrency?) + + CALENDARS + - Only the Gregorian calendar is supported + + USEFUL INFO https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat \ No newline at end of file diff --git a/devdocs/specs/core-license-key-system.txt b/devdocs/old-devdocs/specs/core-license-key-system.txt similarity index 98% rename from devdocs/specs/core-license-key-system.txt rename to devdocs/old-devdocs/specs/core-license-key-system.txt index bf99f789..b6df4282 100644 --- a/devdocs/specs/core-license-key-system.txt +++ b/devdocs/old-devdocs/specs/core-license-key-system.txt @@ -1,258 +1,258 @@ -License key / products - -(see marketing-sales-planning.txt specs doc for specific reasoning behind this) - -CASE FOR THIS WORK IN ROCKFISH IS: -https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/3724 - -CURRENT WORKING STATUS: - -2018-06-01 -Rough framework is in place, can fetch a key and can request a key but nothing really connected at the Rockfish end. -Rockfish will need some ui and other code to handle it -Putting that off until closer to release as Rockfish will no doubt change before then anyway (also involves a lot of UI work I'm not into right now) - - - - - -PROCESS - -LICENSE BOOTSTRAPPING - - RAVEN when boots and doesn't find a db then inits license will ensure a GUID DBID value is set in LICENSE TABLE - - This is used to match individual databases to licenses and avoid problems with registration names being the only differentiator as in v7 - - Also this is the new fetch code - - RAVEN Is unlicensed it should check for a new key on a shorter frequency loop rather than once a day? - or, providing a button to trigger that should be enough really - or when server starts it starts the GENERATE loop and checks for a key right away, so they can just reboot the server if they want an immediate license check? - - - - RAVEN DB is empty (of biz data) it's license locked and a User MUST DONE ONE OF THE FOLLOWING: - - 1) Restore a RAVEN database and reboot the server - - EMPTY DB AND EXISTING LICENSED KEY IN RF If this DBID is already present in ROCKFISH as *licensed* and FETCHED previously then: - Form displays a message, at top about restoring with link to the manual for restoring db - Rest of form is related to releasing a previously fetched key: - Has a FETCH button on it for forcing a fetch when they have requested it or know it's coming or whatever and below that - A form to fill out to request it be released for re-fetch: - User must fill out form stating reason why and their contact info for verification - The request is emailed to us via Rockfish - We decide to release or not and can contact them etc to handle it - We can release it for refetch and then it's all automatic once daily check (maybe more frequent when unlicensed?) or they can force it - - EMPTY DB AND DBID NOT IN ROCKFISH - User gets a form for requesting a trial - - by filling out a form in RAVEN (or using api tool) - - see "trial process" below for details - Form has fetch key button on it to force an immediate fetch - FUTURE: form displays a purchase link they can go to and make purchase inside RF - - -TRIAL / ONBOARDING PROCESS -========================== - -*** SEE client todo for more up to date of this *** - -FOR USER: Install RAVEN, boot, go to client endpoint in browser, get prompted for first test of contact with ROCKFISH server, - once that is ok then get prompted to fill out a form to request a trial key or attempt to fetch a key already ready for them - User fills out form providing registration name and email address, hits send, told to check email to confirm address then will receive a key after that. - They are told they can only request a new trial by erasing all the data first - -FOR CODE: - - RAVEN user requests a trial key for an empty db by filling out a form in RAVEN (or using api tool) - - registration name, email address are required fields - - This request is stored in the db because it may need to be re-sent later on subsequent erasure of biz data - - RAVEN makes and stores internally into a new DB a DBID value which uniquely identifies *THAT* database installation - - RAVEN transmits the request details (with dbid value) to ROCKFISH - - - ROCKFISH validates the request by verifying the email address provided is (is still) valid and by getting our approval after that. - - Verifies email by sending an email with a special trial code they need to enter into the license page which indicates they received the message and the email address is valid. - - When they successfully enter the trial code and it vets as good (just some simple checksum system, nothing fancy at all, just needs to be uniqueish and confirm valid, probably part of an epoch timestamp) - - If the code is good then the email is valid so the RAVEN server contacts an api route to confirm the code was entered properly which then triggers the rest of the ROCKFISH process - - If the code is good then RAVEN starts a repeating job that will periodically check the ROCKFISH server for a license response - - If the email is valid then it creates a trial request record for us to view and approve or not approve with cause entered as text which will be sent to the user (like don't use fake names or profanity or something similar) - - This part we WILL automate in future but for now it's a good "fuse" - - The DBID value is associated permanently with a SITE record in ROCKFISH - we can override this value in case of weird issue unforseen - although ideally we should be able to just shut down a "site" and create another site for that user so we have continuity - - - We get a notification of a request sitting in ROCKFISH and we approve it or not - - IF APPROVED: - - ROCKFISH generates (or looks up if repeat) a customer record, flags it as a trial type customer with a created date (for later GDPR removal or turning into a real customer record) - - (ROCKFSIH UI needs a grouping for trial customers for main customer list) - - ROCKFISH stores the DBID value in the SITE record - - ROCKFISH generates a valid TRIAL license DBID code is the temporary fetch code. - - ROCKFISH Ultimately should do this automatically unless we specifically flag something - - CLIENT LICENSE PAGE UI if refreshed or auto refreshed or whatever it will do updates the status showing licensed trial and expiry date etc - - IF NOT APPROVED - - ROCKFISH creates a not approved type of license with the fetch code so that the server will stop polling - - CLIENT DISPLAYS the not approved message right in the UI with the rejected message - - ROCKFISH sends and email to the user explaining that it's a fail and why - - RAVEN knows a request has been sent and has a license job that checks to see if a license is available periodically - - ROCKFISH returns a "no-op" type response if there is no license (as minimal as possible for bandwidth purposes since it's polling regularly) - - ROCKFISH returns a "FAIL" type response if there is a fail with reason code to display to user - - RAVEN CANCELS the check for license job and removes the request - - ROCKFISH returns a license key when available under the dbid fetch code - - ROCKFISH tags the license as "FETCHED" = true so it can't be fetched twice - - RAVEN CANCELS the check for license job and attempts to install the key in normal process and initialize - - -PURCHASE PROCESS -================ - - -FOR USER: -Assuming ShareIt system still in place: -Customer makes a purchase, (possibly through RAVEN in which case the DBID is sent with the url to ShareIt to be filled into the purchase page automatically) -Customer enters their DBID as instructed into a box on the purchase page. The order is not valid without it and it's a required field. -customer can easily copy their DB ID from within RAVEN - -We get the order and it gets transferred to ROCKFISH, license key is generated and an automated email notification is sent to user instructing that the license is ready for "pickup". -User (who is OPS full or limited or BIZ full) goes into the license page in RAVEN UI and selects "Check for new license" at which point the server does the check passing the GUID along with the check, if new license then it installs and inits and informs user. -If it's a fail for some reason informs user and no change to current license. - - -FOR CODE: - -- RAVEN needs a DBID route in licensing controller to return the DBID available to OPS full or read only OR BIZ full rights only. -- ROCKFISH needs a way to send a license key email to the customer automatically upon generation -- ROCKFISH needs a new key generation page with the new options on it - - -RENEWAL PROCESS -=============== - -FOR USER: -If perpetual: They get a renewal upcoming notice if yearly (!=ServiceMode) from ROCKFISH so they can update payment info or cancel, RAVEN will start a license check job immediately before expiry -If Service: they do nothing, it's understood that it will start to check automatically for a new key around the time of expiry of the old key until it receives a CANCELLED response or a key or a FAIL - -FOR CODE: -See below, basically raven will check with rockfish automatically and handle any problems - - - -"8" KEY FORMAT -================= -- JSON format -- secured with hash signature, only we can issue valid keys -- Features, All licenseable items (and some configuration features) are in a single "Features" collection scheduledusers, accounting "Service" (meaning it's rental), "Trial" meaning it's a trial etc. - - "ServiceMode" feature which indicates the license is for renting not perpetual so that it can trigger more constant check for new licenses or offer rental specific features and functionality - - "TrialMode" feature which indicates it's a trial so a different UI can be presented in some areas with sales links etc - - Futureproof, can put anything in there -- LicenseExpiration date that applies to all features together as a group (no more individual expiry dates) - - When the license expires it stops working. NO read only mode, nothing works except some ops routes to install a new license, that's it -- MaintenanceExpiration date that applies to support and updates subscription for all features of that license (no individual feature support expiry) - - Used by "check for updates" code to see if they are eligable for an update and to auto-update -- ID This field is critical and should contain the customer ID followed by the license ID, so for example 34-506987 - - THESE points here below for this item may be invalid if we go with DBID instead, but keeping as seems to make sense - - This way we can verify with automated tools the customer requesting without sending an actual name in text and also that they have the latest key or not - - RAVEN says "This is my key 34-506987" to ROCKFISH which replies with "Here is a newer key [key]" or "You are up to date" or "Revoked for reason: [non payment]" - - (Test keys are all 00-serialid) -- DBID - - This field is the unique DB id (GUID) of the database in use that is first generated by RAVEN when it first boots with an empty db - - It is stored in the global settings of the database and is never erased once it is set - - It is also used in conjunction with the ID field or possibly on it's own to be the fetch code -- RegTo: ALL TRIAL KEYS ARE REGISTERED TO SOMEONE NO SUCH THING AS TWO LICENSES IN CIRCULATION WITH THE SAME NAME (i.e. no more "Unregistered trial" meaning it's a trial, every user will have a specific name to test it out) - - Rockfish will issue a trial key upon first request from empty db - - An empty regto is an invalid key. -- LicenseFormat - - there will be a LicenseFormat version field which will be initially "8" - - This is for future changes to how license is formatted to ease the code burden of detecting that - - Old future release versions should work with new licenses but not the reverse - - - -ROCKFISH CODE -- FETCHROUTE: Needs a route to automatically check for presence of new licenses from RAVEN, fetch and install them - - Will return either a license or an object indicating error or nothing new to return - - -- UI: Needs a whole lot of ui and code to support - - automatic generation of license key from manual and future automated billing - - Key stored and served when required with challenge and response system by past key id and customer number maybe - automatic billing and renewals but initially generate licenses automatically based on payment info and all that shit - -RAVEN CODE -- Raven if an empty db can send a request for a key to Rockfish with a registered name -- If db empty on boot set a Guid value in the global settings table that uniquely and permanently identifies that database -- RAVEN will have two addresses for fetching a license key to different domains so that we can stay up in case of an issue - - i.e. it will try rockfish.AyaNova.com first but if it fails then fallback to rockfish.helloayanova.com as secondary -- If there is an existing key RAVEN will automatically check for a new key close to the expiry period of the old key - - If a FAIL is returned it will stop checking and tell the user at which point they must manually start the check after fixing the issue - - If a NOOP is returned it will reschedule to check again later - - If a CANCELLED is returned then the customer is no longer active and it will never check again unless user manually forces a one time check and the license changes - - If a license is returned RAVEN will attempt to install it and also clear the running check job and also clear the CANCELLED status - -- RAVEN LICENSE OBJECT / TABLE add a DBID guid column -- RAVEN LICENSE OBJECT / TABLE add a LastFetchStatus column corresponding to an enum of FAIL, ACTIVE, CANCELLED -- RAVEN LICENSE OBJECT / TABLE add a LastFetchMessage column with the last message from the ROCKFISH license route server (so FAIL can be stored and communicated to user) - - -USAGE: - -- MUST be able to support monthly billing cycle (automatic license installation or approval so user doesn't have to install key every month) - - Rockfish should have a licensed yay or nay or new available route for RAVEN to check periodically and also users can trigger a force check -- RAVEN checks periodically for new license to fetch in line with billing cycle or expiry cycle. - - SAFE fallback if can't contact license server and allow a few misses before something kicks in, but not to allow people to use unlimited by blocking rockfish for example - - - - - - - - - -PRODUCT LICENSE CHANGES FROM v7 - - -Still optional and purchased separately: -QBOI, QBI, PTI - -Possible idea: sold as "Accounting add on" and the user can use one of those of their choice and can switch which means 1 product instead of three which might make keys easier. - Possible downside is that we can't track who uses what or what we sell how much of so puts a kink in marketing or planning for deprecation or where to spend - effort, however there are other ways of addressing that. - - -//INCLUDED ADD-ON's -OLI - INCLUDED / TURNED INTO GENERIC FEATURE IMPORT / EXPORT CONTACTS and SCHEDULE TO ICAL -OutLookScheduleExport - INCLUDED / TURNED INTO GENERIC SCHED EXPORT ICAL FORMAT -Export to xls - Included with RAVEN -QuickNotification - Included with RAVEN -ImportExportDuplicate - Included with RAVEN -RI/WBI/MBI - UNNECESSARY with RAVEN - - -This all brings up the matter then that we might only have two things to license: the number of users and whether there is accounting or not. - ?? PROS and CONS INLINE WITH RAVEN DESIGN GOALS ?? - - - - -THOUGHTS -Raven license key system specs: - - -- CONSIDER supporting non-connected scenario where user is not internet connected - - - - - - - -??? -- Don't worry about obfuscation at first (maybe ever, I mean, really) -- Need automated routine that checks with rockfish to fetch a license automatically when necessary - - I.E. it's sub runs out so it starts checking if there is a newer license available and if so fetches it -- Need an alternative route and UI in Rockfish for RAVEN style license handling -- Must use a different signing key than AyaNova 7 so we don't expose v8 key stuff, (although, it's just the public part of the key to validate right?) -===================================== - -RESEARCH SOURCES -- http://www.reprisesoftware.com/blog/2017/08/implement-a-recurring-revenue-license-model/ -- https://www.linkedin.com/pulse/20140819084845-458042-the-change-from-perpetual-to-subscription-based-software-licensing -- http://software-monetization.tmcnet.com/articles/429528-long-but-rewarding-road-a-recurring-revenue-model.htm -- How to calculate pricing in a service business: https://www.patriotsoftware.com/accounting/training/blog/how-pricing-services-strategies-models-formula/ +License key / products + +(see marketing-sales-planning.txt specs doc for specific reasoning behind this) + +CASE FOR THIS WORK IN ROCKFISH IS: +https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/3724 + +CURRENT WORKING STATUS: + +2018-06-01 +Rough framework is in place, can fetch a key and can request a key but nothing really connected at the Rockfish end. +Rockfish will need some ui and other code to handle it +Putting that off until closer to release as Rockfish will no doubt change before then anyway (also involves a lot of UI work I'm not into right now) + + + + + +PROCESS + +LICENSE BOOTSTRAPPING + - RAVEN when boots and doesn't find a db then inits license will ensure a GUID DBID value is set in LICENSE TABLE + - This is used to match individual databases to licenses and avoid problems with registration names being the only differentiator as in v7 + - Also this is the new fetch code + - RAVEN Is unlicensed it should check for a new key on a shorter frequency loop rather than once a day? + or, providing a button to trigger that should be enough really + or when server starts it starts the GENERATE loop and checks for a key right away, so they can just reboot the server if they want an immediate license check? + + + - RAVEN DB is empty (of biz data) it's license locked and a User MUST DONE ONE OF THE FOLLOWING: + + 1) Restore a RAVEN database and reboot the server + + EMPTY DB AND EXISTING LICENSED KEY IN RF If this DBID is already present in ROCKFISH as *licensed* and FETCHED previously then: + Form displays a message, at top about restoring with link to the manual for restoring db + Rest of form is related to releasing a previously fetched key: + Has a FETCH button on it for forcing a fetch when they have requested it or know it's coming or whatever and below that + A form to fill out to request it be released for re-fetch: + User must fill out form stating reason why and their contact info for verification + The request is emailed to us via Rockfish + We decide to release or not and can contact them etc to handle it + We can release it for refetch and then it's all automatic once daily check (maybe more frequent when unlicensed?) or they can force it + + EMPTY DB AND DBID NOT IN ROCKFISH + User gets a form for requesting a trial + - by filling out a form in RAVEN (or using api tool) + - see "trial process" below for details + Form has fetch key button on it to force an immediate fetch + FUTURE: form displays a purchase link they can go to and make purchase inside RF + + +TRIAL / ONBOARDING PROCESS +========================== + +*** SEE client todo for more up to date of this *** + +FOR USER: Install RAVEN, boot, go to client endpoint in browser, get prompted for first test of contact with ROCKFISH server, + once that is ok then get prompted to fill out a form to request a trial key or attempt to fetch a key already ready for them + User fills out form providing registration name and email address, hits send, told to check email to confirm address then will receive a key after that. + They are told they can only request a new trial by erasing all the data first + +FOR CODE: + - RAVEN user requests a trial key for an empty db by filling out a form in RAVEN (or using api tool) + - registration name, email address are required fields + - This request is stored in the db because it may need to be re-sent later on subsequent erasure of biz data + - RAVEN makes and stores internally into a new DB a DBID value which uniquely identifies *THAT* database installation + - RAVEN transmits the request details (with dbid value) to ROCKFISH + + - ROCKFISH validates the request by verifying the email address provided is (is still) valid and by getting our approval after that. + - Verifies email by sending an email with a special trial code they need to enter into the license page which indicates they received the message and the email address is valid. + - When they successfully enter the trial code and it vets as good (just some simple checksum system, nothing fancy at all, just needs to be uniqueish and confirm valid, probably part of an epoch timestamp) + - If the code is good then the email is valid so the RAVEN server contacts an api route to confirm the code was entered properly which then triggers the rest of the ROCKFISH process + - If the code is good then RAVEN starts a repeating job that will periodically check the ROCKFISH server for a license response + - If the email is valid then it creates a trial request record for us to view and approve or not approve with cause entered as text which will be sent to the user (like don't use fake names or profanity or something similar) + - This part we WILL automate in future but for now it's a good "fuse" + - The DBID value is associated permanently with a SITE record in ROCKFISH + we can override this value in case of weird issue unforseen + although ideally we should be able to just shut down a "site" and create another site for that user so we have continuity + + - We get a notification of a request sitting in ROCKFISH and we approve it or not + - IF APPROVED: + - ROCKFISH generates (or looks up if repeat) a customer record, flags it as a trial type customer with a created date (for later GDPR removal or turning into a real customer record) + - (ROCKFSIH UI needs a grouping for trial customers for main customer list) + - ROCKFISH stores the DBID value in the SITE record + - ROCKFISH generates a valid TRIAL license DBID code is the temporary fetch code. + - ROCKFISH Ultimately should do this automatically unless we specifically flag something + - CLIENT LICENSE PAGE UI if refreshed or auto refreshed or whatever it will do updates the status showing licensed trial and expiry date etc + - IF NOT APPROVED + - ROCKFISH creates a not approved type of license with the fetch code so that the server will stop polling + - CLIENT DISPLAYS the not approved message right in the UI with the rejected message + - ROCKFISH sends and email to the user explaining that it's a fail and why + - RAVEN knows a request has been sent and has a license job that checks to see if a license is available periodically + - ROCKFISH returns a "no-op" type response if there is no license (as minimal as possible for bandwidth purposes since it's polling regularly) + - ROCKFISH returns a "FAIL" type response if there is a fail with reason code to display to user + - RAVEN CANCELS the check for license job and removes the request + - ROCKFISH returns a license key when available under the dbid fetch code + - ROCKFISH tags the license as "FETCHED" = true so it can't be fetched twice + - RAVEN CANCELS the check for license job and attempts to install the key in normal process and initialize + + +PURCHASE PROCESS +================ + + +FOR USER: +Assuming ShareIt system still in place: +Customer makes a purchase, (possibly through RAVEN in which case the DBID is sent with the url to ShareIt to be filled into the purchase page automatically) +Customer enters their DBID as instructed into a box on the purchase page. The order is not valid without it and it's a required field. +customer can easily copy their DB ID from within RAVEN + +We get the order and it gets transferred to ROCKFISH, license key is generated and an automated email notification is sent to user instructing that the license is ready for "pickup". +User (who is OPS full or limited or BIZ full) goes into the license page in RAVEN UI and selects "Check for new license" at which point the server does the check passing the GUID along with the check, if new license then it installs and inits and informs user. +If it's a fail for some reason informs user and no change to current license. + + +FOR CODE: + +- RAVEN needs a DBID route in licensing controller to return the DBID available to OPS full or read only OR BIZ full rights only. +- ROCKFISH needs a way to send a license key email to the customer automatically upon generation +- ROCKFISH needs a new key generation page with the new options on it + + +RENEWAL PROCESS +=============== + +FOR USER: +If perpetual: They get a renewal upcoming notice if yearly (!=ServiceMode) from ROCKFISH so they can update payment info or cancel, RAVEN will start a license check job immediately before expiry +If Service: they do nothing, it's understood that it will start to check automatically for a new key around the time of expiry of the old key until it receives a CANCELLED response or a key or a FAIL + +FOR CODE: +See below, basically raven will check with rockfish automatically and handle any problems + + + +"8" KEY FORMAT +================= +- JSON format +- secured with hash signature, only we can issue valid keys +- Features, All licenseable items (and some configuration features) are in a single "Features" collection scheduledusers, accounting "Service" (meaning it's rental), "Trial" meaning it's a trial etc. + - "ServiceMode" feature which indicates the license is for renting not perpetual so that it can trigger more constant check for new licenses or offer rental specific features and functionality + - "TrialMode" feature which indicates it's a trial so a different UI can be presented in some areas with sales links etc + - Futureproof, can put anything in there +- LicenseExpiration date that applies to all features together as a group (no more individual expiry dates) + - When the license expires it stops working. NO read only mode, nothing works except some ops routes to install a new license, that's it +- MaintenanceExpiration date that applies to support and updates subscription for all features of that license (no individual feature support expiry) + - Used by "check for updates" code to see if they are eligable for an update and to auto-update +- ID This field is critical and should contain the customer ID followed by the license ID, so for example 34-506987 + - THESE points here below for this item may be invalid if we go with DBID instead, but keeping as seems to make sense + - This way we can verify with automated tools the customer requesting without sending an actual name in text and also that they have the latest key or not + - RAVEN says "This is my key 34-506987" to ROCKFISH which replies with "Here is a newer key [key]" or "You are up to date" or "Revoked for reason: [non payment]" + - (Test keys are all 00-serialid) +- DBID + - This field is the unique DB id (GUID) of the database in use that is first generated by RAVEN when it first boots with an empty db + - It is stored in the global settings of the database and is never erased once it is set + - It is also used in conjunction with the ID field or possibly on it's own to be the fetch code +- RegTo: ALL TRIAL KEYS ARE REGISTERED TO SOMEONE NO SUCH THING AS TWO LICENSES IN CIRCULATION WITH THE SAME NAME (i.e. no more "Unregistered trial" meaning it's a trial, every user will have a specific name to test it out) + - Rockfish will issue a trial key upon first request from empty db + - An empty regto is an invalid key. +- LicenseFormat + - there will be a LicenseFormat version field which will be initially "8" + - This is for future changes to how license is formatted to ease the code burden of detecting that + - Old future release versions should work with new licenses but not the reverse + + + +ROCKFISH CODE +- FETCHROUTE: Needs a route to automatically check for presence of new licenses from RAVEN, fetch and install them + - Will return either a license or an object indicating error or nothing new to return + + +- UI: Needs a whole lot of ui and code to support + - automatic generation of license key from manual and future automated billing + - Key stored and served when required with challenge and response system by past key id and customer number maybe + automatic billing and renewals but initially generate licenses automatically based on payment info and all that shit + +RAVEN CODE +- Raven if an empty db can send a request for a key to Rockfish with a registered name +- If db empty on boot set a Guid value in the global settings table that uniquely and permanently identifies that database +- RAVEN will have two addresses for fetching a license key to different domains so that we can stay up in case of an issue + - i.e. it will try rockfish.AyaNova.com first but if it fails then fallback to rockfish.helloayanova.com as secondary +- If there is an existing key RAVEN will automatically check for a new key close to the expiry period of the old key + - If a FAIL is returned it will stop checking and tell the user at which point they must manually start the check after fixing the issue + - If a NOOP is returned it will reschedule to check again later + - If a CANCELLED is returned then the customer is no longer active and it will never check again unless user manually forces a one time check and the license changes + - If a license is returned RAVEN will attempt to install it and also clear the running check job and also clear the CANCELLED status + +- RAVEN LICENSE OBJECT / TABLE add a DBID guid column +- RAVEN LICENSE OBJECT / TABLE add a LastFetchStatus column corresponding to an enum of FAIL, ACTIVE, CANCELLED +- RAVEN LICENSE OBJECT / TABLE add a LastFetchMessage column with the last message from the ROCKFISH license route server (so FAIL can be stored and communicated to user) + + +USAGE: + +- MUST be able to support monthly billing cycle (automatic license installation or approval so user doesn't have to install key every month) + - Rockfish should have a licensed yay or nay or new available route for RAVEN to check periodically and also users can trigger a force check +- RAVEN checks periodically for new license to fetch in line with billing cycle or expiry cycle. + - SAFE fallback if can't contact license server and allow a few misses before something kicks in, but not to allow people to use unlimited by blocking rockfish for example + + + + + + + + + +PRODUCT LICENSE CHANGES FROM v7 + + +Still optional and purchased separately: +QBOI, QBI, PTI + +Possible idea: sold as "Accounting add on" and the user can use one of those of their choice and can switch which means 1 product instead of three which might make keys easier. + Possible downside is that we can't track who uses what or what we sell how much of so puts a kink in marketing or planning for deprecation or where to spend + effort, however there are other ways of addressing that. + + +//INCLUDED ADD-ON's +OLI - INCLUDED / TURNED INTO GENERIC FEATURE IMPORT / EXPORT CONTACTS and SCHEDULE TO ICAL +OutLookScheduleExport - INCLUDED / TURNED INTO GENERIC SCHED EXPORT ICAL FORMAT +Export to xls - Included with RAVEN +QuickNotification - Included with RAVEN +ImportExportDuplicate - Included with RAVEN +RI/WBI/MBI - UNNECESSARY with RAVEN + + +This all brings up the matter then that we might only have two things to license: the number of users and whether there is accounting or not. + ?? PROS and CONS INLINE WITH RAVEN DESIGN GOALS ?? + + + + +THOUGHTS +Raven license key system specs: + + +- CONSIDER supporting non-connected scenario where user is not internet connected + + + + + + + +??? +- Don't worry about obfuscation at first (maybe ever, I mean, really) +- Need automated routine that checks with rockfish to fetch a license automatically when necessary + - I.E. it's sub runs out so it starts checking if there is a newer license available and if so fetches it +- Need an alternative route and UI in Rockfish for RAVEN style license handling +- Must use a different signing key than AyaNova 7 so we don't expose v8 key stuff, (although, it's just the public part of the key to validate right?) +===================================== + +RESEARCH SOURCES +- http://www.reprisesoftware.com/blog/2017/08/implement-a-recurring-revenue-license-model/ +- https://www.linkedin.com/pulse/20140819084845-458042-the-change-from-perpetual-to-subscription-based-software-licensing +- http://software-monetization.tmcnet.com/articles/429528-long-but-rewarding-road-a-recurring-revenue-model.htm +- How to calculate pricing in a service business: https://www.patriotsoftware.com/accounting/training/blog/how-pricing-services-strategies-models-formula/ - SAAS pricing models: https://www.cobloom.com/blog/saas-pricing-models \ No newline at end of file diff --git a/devdocs/specs/core-list-graph-datatable-filter-sort.txt b/devdocs/old-devdocs/specs/core-list-graph-datatable-filter-sort.txt similarity index 98% rename from devdocs/specs/core-list-graph-datatable-filter-sort.txt rename to devdocs/old-devdocs/specs/core-list-graph-datatable-filter-sort.txt index be12ea1b..781c1246 100644 --- a/devdocs/specs/core-list-graph-datatable-filter-sort.txt +++ b/devdocs/old-devdocs/specs/core-list-graph-datatable-filter-sort.txt @@ -1,213 +1,213 @@ -LIST / GRAPH FILTERING SORTING AND COLUMN RETURNED - -##### DEPRECATED ALL LISTVIEW STUFF FOR NEW SPLIT METHOD SOME OF BELOW IS OUTDATED WHERE IT DEALS WITH THE "LISTVIEW" - -DATALIST -A dataList is a raw source of data for returning to client -All below is based on a datalist which is a predefined list of fields, rights and some query info for joins etc -There are specific datalists made for picklists, viewing all grid data, KPI shit, whatever is required during development -DataLists are hard coded, only a DataListView can be customized to limit, filter, sort what is returned from a pre-defined DataList -DataLists have roles associated with them, only a user of one of those roles can fetch that list (or see it as an option when doing reporting etc) - -DATALISTVIEW -A DataListView is a filtered, sorted, reduced version of a DataList -It can be saved and set to private or public -They can be made on the fly in the Client and don't need to be saved as the Client will always send the datalistview json string with the request -DataListView objects are used to filter and sort and determine display order and presence of columns in order to feed these client needs: -DataTables (was grids in v7) -Reports -Select boxes PickLists (on forms like selecting a part or a client) - -When the DataList route is hit it's used to get all of the above types of data. -A dataListView JSON string is sent with the request in order to have the server sort/filter/return - -PICKLISTS -Picklists are based on a particular DataList with rights for ANYONE -Client will be hard coded to specifiy the exact dataLIst -Users can select a datalistview for a picklist DataList which will in turn affect how it appears and what's returned - - This is like the PartDisplayFormat feature of v7 only for everything! -Users will get the default hard coded DataListView built into the DataList that is specified for that picklist unless it's changed to an alternative datalistview -There is a default PickList format and a default DataTable format pre-defined and hard coded at the server with each dataList definition object - -If the client isn't using a particular dataListView it MUST send the Lis tView json as empty string or omit it entirely. -This will instruct the server to use the pre-defined format instead - -JSON DataListView format: -ONE string of json, not separate -Contains all columns that are relevant each as an object with various props desired to be returned in order -If a column isn't filtered or sorted or included then it isn't in the collection -Order and presence determines sort, filter, return and display order -Each column object contains it's sorted, sort order and filters collection which can be empty -Sort and filter properties are optional and can be omitted -"any" property is optional in a filter and can be omitted - -UI: shows all available columns, user sets order by re-arranging and whether to include or not with a checkbox Include which defaults to true if there is any conditions on that column - -Example: - -DataListView JSON: -[{key:"COLUMN UNIQUE KEY ID",sort:"-" or "+",filter:{any:true/false,items:[{FILTER OBJECT SEE BELOW}]} }, {key:"second column unique key"},{...etc...}] - -Sort property definition -ID VS NAME -if it's an name *and* id field it won't matter because it will sort by name only -I've thought about it and can't see a use case for needing to sort by the underlying ID value, but if people want that they can just not sort the list to get -the most recent records at the top (for example) - -Filter object definition: -Has an "any" boolean property which if true means make an OR query of the conditions if more than one, if nore present or false it means AND each condition (if more than one) - - -filter:{any:true/false,items:[ - {op:"OPERATOR",value:One of an array of strings, single string or single value of any supported type, i.e. int, decimal, bool iso8601 date etc } - ]} - -ID VALUE vs NAME VALUE - Some colums represent both an ID and a text name, in those cases if the operator is Equals or NotEquals and the "value" property of the filter is a number then it's a specific ID - Otherwise if it's a string it's always filtering by the display name instead - -AUTHORIZATION: - Authorization is controlled via roles set on underlying DataList object itself - We provide a DataList suitable for picklists with ANY role access and anything with sensitive info has it's DataList Required roles to higher level - This way can still supply for picklists but hide sensitive infor for tables etc - Rights to DataListView follow rights to underlying object and also rights to make a datalistview itself - -Filter operators: - - - public const string OpEquality = "="; - public const string OpGreaterThan = ">"; - public const string OpGreaterThanOrEqualTo = ">="; - public const string OpLessThan = "<"; - public const string OpLessThanOrEqualTo = "<="; - public const string OpNotEqual = "!="; - public const string OpNotLike = "!%"; - public const string OpStartsWith = "%-"; - public const string OpEndsWith = "-%"; - public const string OpContains = "-%-"; - public const string OpNotContains = "!-%-"; - - -TAGS - At server if equality compare value is an array of strings then it's assumed to be tags, if it's a single value then it's regular - - - -Also relative date filters are supported and their implementation is entirely a CLIENT responsibility as it touches on Locale issues: - -public const string Null = "*NULL*"; -// public const string Yesterday = "{[yesterday]}"; -// public const string Today = "{[today]}"; -// public const string Tomorrow = "{[tomorrow]}"; -// public const string LastWeek = "{[lastweek]}"; -// public const string ThisWeek = "{[thisweek]}"; -// public const string NextWeek = "{[nextweek]}"; -// public const string LastMonth = "{[lastmonth]}"; -// public const string ThisMonth = "{[thismonth]}"; -// public const string NextMonth = "{[nextmonth]}"; -// public const string FourteenDayWindow = "{[14daywindow]}"; -// public const string Past = "{[past]}"; -// public const string Future = "{[future]}"; -// public const string LastYear = "{[lastyear]}"; -// public const string ThisYear = "{[thisyear]}"; -// public const string InTheLast3Months = "{[last3months]}"; -// public const string InTheLast6Months = "{[last6months]}"; -// public const string InTheLastYear = "{[lastcalendaryear]}"; - -// //Months THIS year -// public const string January = "{[january]}"; -// public const string February = "{[february]}"; -// public const string March = "{[march]}"; -// public const string April = "{[april]}"; -// public const string May = "{[may]}"; -// public const string June = "{[june]}"; -// public const string July = "{[july]}"; -// public const string August = "{[august]}"; -// public const string September = "{[september]}"; -// public const string October = "{[october]}"; -// public const string November = "{[november]}"; -// public const string December = "{[december]}"; - -Client calculates dates and sends with DataListView when requesting a list - - - - - - - - - - - - - - -******************************** DEPRECATED MOSTLY BELOW ******************************************************** - - -This all applies equally to a report or a list or a graph so all work basically the same but will refer only to "list" for simplicity: - -At client user can view a list and select from a dropdown of saved filters for that type of list which corresponds to an api route. -User creates filters in separate UI from the actual list, i.e. clicks on the filter button above a list to make or edit filter. -Two types of filters Named or Default: - User can save a filter with a name for later selection or it will always default to "Default" (localized) if not edited but will always require saving to server. - Generic "default" filter is always personal, not public / shared - - This is a client issue, Server doesn't care what the filters are called adn has no special processing for default filters -Named filters can be made public or personal. If public then all users with rights to that object can see them, personal are always only personal. -Filter is constructed from an FILTEROPTIONS object fetched from the server list route that has a list type name which is unique to that list route -and also lists all the fields filterable, their type and the translation key to display it - - e.g.: {ListKey:"widget",fields:[{fld:"name",lt:"WidgetName",type:"text"},{fld:"dollarAmount",lt:"WidgetDollarAmount",type:"currency"}]} - - List key -Certain types have extended abilities, for example dates have the classic floating AyaNova date ranges pre-defined or specific dates -Filters are saved to the database: - - Filter: Name, UserId, Public, ListKey, Filter (Json string) - - ListKey is always lower case to match biz object list key name - - Filter format: - - Array [{fld:"fieldname",op:"See filtercomparisonoperator class",value:"compareValue"},...] these are all AND in sql, no OR - - fld=name of field to filter by - - always all lower case - - Straight up field name like "name" - - Could be compound for joins like "table.name" (no a prepends the table name) - - Special indirect values such as "[TAGS]" which means cross filter with tags - - op=one of the values specified in the FilterComparisonOperator class in Biz namespace - - Note: no Like on purpose, that would require input, better to hard code a starts with, ends with, contains and not bothering with the negative of those three as I don't see it being widely used - - value = string version of direct comparison value or could be a special token meaning more - - Never an empty string, empty string is invalid value - - All Tokens are a value surrounded by this fragment: "{[XXX]}" where XXX is the token - - if empty or null then will be a token "*NULL*" - - If string then a string fragment, case is sensitive - - If date then iso style date //RAVEN NOTE: it is my intention that dates come in iso8601 UTC format from the client - - could be whole number or decimal number - - Could be a special "macro" filter value like "{[THIS_MONTH]}" - - Could be a series of id values like this "[23,45,56,123]" as in tag id's or something related to that case. - -Upon user selecting a filter to use the list query string has the regular paging info but also the filter id as a query parameter - - Server loads the filter if it's public or has the user ID if it's personal only - - If list not found then it will return a 404 instead of the list - - server loads the filter, generates the sql based on the stored filter, adds the sort by and offset / page, runs the query and then returns the data as json collection to the client - --------------------------------------------------------- -NOTES ABOUT WHY I DID THE FILTEROPTIONS LIKE I DID: -//Need a collection of fields and types and translation keys for - // - Client fetching filteroptions via list class - // - Just a static list of items localized and sent to the client - // - DataFilter validation via list class - // - static list of items to compare against - // - ToSql from DataFilter validation and query building via list class - // - Static list of filter options so that it can build sql fragment (needs to know type, possibly the field name [or that is inferred probably]) - // - Ideally each list object will have it's own chunk of code to handle it's shit with tosql just making the fragments of sql like in v7 - // - Again, a static list of items to check against - - - - //Where to store that? - //all cases are via list class so really the whole thing is self contained and no need for an interface at all --------------------------------------------------- - - -SORTING -=-=-=-=- -Sorting is done same as filtering but property on datafilter is called Sort and it's also a json Array -Fields are: "fld" which is the same column name as in a datafilter and "dir" for direction which will contain a single character either a "-" or a "+" for descending and ascending respectively -If no Sort is defined the default will be by ID number descending meaning the most recent records in that table will be first - +LIST / GRAPH FILTERING SORTING AND COLUMN RETURNED + +##### DEPRECATED ALL LISTVIEW STUFF FOR NEW SPLIT METHOD SOME OF BELOW IS OUTDATED WHERE IT DEALS WITH THE "LISTVIEW" + +DATALIST +A dataList is a raw source of data for returning to client +All below is based on a datalist which is a predefined list of fields, rights and some query info for joins etc +There are specific datalists made for picklists, viewing all grid data, KPI shit, whatever is required during development +DataLists are hard coded, only a DataListView can be customized to limit, filter, sort what is returned from a pre-defined DataList +DataLists have roles associated with them, only a user of one of those roles can fetch that list (or see it as an option when doing reporting etc) + +DATALISTVIEW +A DataListView is a filtered, sorted, reduced version of a DataList +It can be saved and set to private or public +They can be made on the fly in the Client and don't need to be saved as the Client will always send the datalistview json string with the request +DataListView objects are used to filter and sort and determine display order and presence of columns in order to feed these client needs: +DataTables (was grids in v7) +Reports +Select boxes PickLists (on forms like selecting a part or a client) + +When the DataList route is hit it's used to get all of the above types of data. +A dataListView JSON string is sent with the request in order to have the server sort/filter/return + +PICKLISTS +Picklists are based on a particular DataList with rights for ANYONE +Client will be hard coded to specifiy the exact dataLIst +Users can select a datalistview for a picklist DataList which will in turn affect how it appears and what's returned + - This is like the PartDisplayFormat feature of v7 only for everything! +Users will get the default hard coded DataListView built into the DataList that is specified for that picklist unless it's changed to an alternative datalistview +There is a default PickList format and a default DataTable format pre-defined and hard coded at the server with each dataList definition object + +If the client isn't using a particular dataListView it MUST send the Lis tView json as empty string or omit it entirely. +This will instruct the server to use the pre-defined format instead + +JSON DataListView format: +ONE string of json, not separate +Contains all columns that are relevant each as an object with various props desired to be returned in order +If a column isn't filtered or sorted or included then it isn't in the collection +Order and presence determines sort, filter, return and display order +Each column object contains it's sorted, sort order and filters collection which can be empty +Sort and filter properties are optional and can be omitted +"any" property is optional in a filter and can be omitted + +UI: shows all available columns, user sets order by re-arranging and whether to include or not with a checkbox Include which defaults to true if there is any conditions on that column + +Example: + +DataListView JSON: +[{key:"COLUMN UNIQUE KEY ID",sort:"-" or "+",filter:{any:true/false,items:[{FILTER OBJECT SEE BELOW}]} }, {key:"second column unique key"},{...etc...}] + +Sort property definition +ID VS NAME +if it's an name *and* id field it won't matter because it will sort by name only +I've thought about it and can't see a use case for needing to sort by the underlying ID value, but if people want that they can just not sort the list to get +the most recent records at the top (for example) + +Filter object definition: +Has an "any" boolean property which if true means make an OR query of the conditions if more than one, if nore present or false it means AND each condition (if more than one) + + +filter:{any:true/false,items:[ + {op:"OPERATOR",value:One of an array of strings, single string or single value of any supported type, i.e. int, decimal, bool iso8601 date etc } + ]} + +ID VALUE vs NAME VALUE + Some colums represent both an ID and a text name, in those cases if the operator is Equals or NotEquals and the "value" property of the filter is a number then it's a specific ID + Otherwise if it's a string it's always filtering by the display name instead + +AUTHORIZATION: + Authorization is controlled via roles set on underlying DataList object itself + We provide a DataList suitable for picklists with ANY role access and anything with sensitive info has it's DataList Required roles to higher level + This way can still supply for picklists but hide sensitive infor for tables etc + Rights to DataListView follow rights to underlying object and also rights to make a datalistview itself + +Filter operators: + + + public const string OpEquality = "="; + public const string OpGreaterThan = ">"; + public const string OpGreaterThanOrEqualTo = ">="; + public const string OpLessThan = "<"; + public const string OpLessThanOrEqualTo = "<="; + public const string OpNotEqual = "!="; + public const string OpNotLike = "!%"; + public const string OpStartsWith = "%-"; + public const string OpEndsWith = "-%"; + public const string OpContains = "-%-"; + public const string OpNotContains = "!-%-"; + + +TAGS - At server if equality compare value is an array of strings then it's assumed to be tags, if it's a single value then it's regular + + + +Also relative date filters are supported and their implementation is entirely a CLIENT responsibility as it touches on Locale issues: + +public const string Null = "*NULL*"; +// public const string Yesterday = "{[yesterday]}"; +// public const string Today = "{[today]}"; +// public const string Tomorrow = "{[tomorrow]}"; +// public const string LastWeek = "{[lastweek]}"; +// public const string ThisWeek = "{[thisweek]}"; +// public const string NextWeek = "{[nextweek]}"; +// public const string LastMonth = "{[lastmonth]}"; +// public const string ThisMonth = "{[thismonth]}"; +// public const string NextMonth = "{[nextmonth]}"; +// public const string FourteenDayWindow = "{[14daywindow]}"; +// public const string Past = "{[past]}"; +// public const string Future = "{[future]}"; +// public const string LastYear = "{[lastyear]}"; +// public const string ThisYear = "{[thisyear]}"; +// public const string InTheLast3Months = "{[last3months]}"; +// public const string InTheLast6Months = "{[last6months]}"; +// public const string InTheLastYear = "{[lastcalendaryear]}"; + +// //Months THIS year +// public const string January = "{[january]}"; +// public const string February = "{[february]}"; +// public const string March = "{[march]}"; +// public const string April = "{[april]}"; +// public const string May = "{[may]}"; +// public const string June = "{[june]}"; +// public const string July = "{[july]}"; +// public const string August = "{[august]}"; +// public const string September = "{[september]}"; +// public const string October = "{[october]}"; +// public const string November = "{[november]}"; +// public const string December = "{[december]}"; + +Client calculates dates and sends with DataListView when requesting a list + + + + + + + + + + + + + + +******************************** DEPRECATED MOSTLY BELOW ******************************************************** + + +This all applies equally to a report or a list or a graph so all work basically the same but will refer only to "list" for simplicity: + +At client user can view a list and select from a dropdown of saved filters for that type of list which corresponds to an api route. +User creates filters in separate UI from the actual list, i.e. clicks on the filter button above a list to make or edit filter. +Two types of filters Named or Default: + User can save a filter with a name for later selection or it will always default to "Default" (localized) if not edited but will always require saving to server. + Generic "default" filter is always personal, not public / shared + - This is a client issue, Server doesn't care what the filters are called adn has no special processing for default filters +Named filters can be made public or personal. If public then all users with rights to that object can see them, personal are always only personal. +Filter is constructed from an FILTEROPTIONS object fetched from the server list route that has a list type name which is unique to that list route +and also lists all the fields filterable, their type and the translation key to display it + - e.g.: {ListKey:"widget",fields:[{fld:"name",lt:"WidgetName",type:"text"},{fld:"dollarAmount",lt:"WidgetDollarAmount",type:"currency"}]} + - List key +Certain types have extended abilities, for example dates have the classic floating AyaNova date ranges pre-defined or specific dates +Filters are saved to the database: + - Filter: Name, UserId, Public, ListKey, Filter (Json string) + - ListKey is always lower case to match biz object list key name + - Filter format: + - Array [{fld:"fieldname",op:"See filtercomparisonoperator class",value:"compareValue"},...] these are all AND in sql, no OR + - fld=name of field to filter by + - always all lower case + - Straight up field name like "name" + - Could be compound for joins like "table.name" (no a prepends the table name) + - Special indirect values such as "[TAGS]" which means cross filter with tags + - op=one of the values specified in the FilterComparisonOperator class in Biz namespace + - Note: no Like on purpose, that would require input, better to hard code a starts with, ends with, contains and not bothering with the negative of those three as I don't see it being widely used + - value = string version of direct comparison value or could be a special token meaning more + - Never an empty string, empty string is invalid value + - All Tokens are a value surrounded by this fragment: "{[XXX]}" where XXX is the token + - if empty or null then will be a token "*NULL*" + - If string then a string fragment, case is sensitive + - If date then iso style date //RAVEN NOTE: it is my intention that dates come in iso8601 UTC format from the client + - could be whole number or decimal number + - Could be a special "macro" filter value like "{[THIS_MONTH]}" + - Could be a series of id values like this "[23,45,56,123]" as in tag id's or something related to that case. + +Upon user selecting a filter to use the list query string has the regular paging info but also the filter id as a query parameter + - Server loads the filter if it's public or has the user ID if it's personal only + - If list not found then it will return a 404 instead of the list + - server loads the filter, generates the sql based on the stored filter, adds the sort by and offset / page, runs the query and then returns the data as json collection to the client + +-------------------------------------------------------- +NOTES ABOUT WHY I DID THE FILTEROPTIONS LIKE I DID: +//Need a collection of fields and types and translation keys for + // - Client fetching filteroptions via list class + // - Just a static list of items localized and sent to the client + // - DataFilter validation via list class + // - static list of items to compare against + // - ToSql from DataFilter validation and query building via list class + // - Static list of filter options so that it can build sql fragment (needs to know type, possibly the field name [or that is inferred probably]) + // - Ideally each list object will have it's own chunk of code to handle it's shit with tosql just making the fragments of sql like in v7 + // - Again, a static list of items to check against + + + + //Where to store that? + //all cases are via list class so really the whole thing is self contained and no need for an interface at all +-------------------------------------------------- + + +SORTING +=-=-=-=- +Sorting is done same as filtering but property on datafilter is called Sort and it's also a json Array +Fields are: "fld" which is the same column name as in a datafilter and "dir" for direction which will contain a single character either a "-" or a "+" for descending and ascending respectively +If no Sort is defined the default will be by ID number descending meaning the most recent records in that table will be first + diff --git a/devdocs/specs/core-locale-currency-numbers-time-and-dates.txt b/devdocs/old-devdocs/specs/core-locale-currency-numbers-time-and-dates.txt similarity index 98% rename from devdocs/specs/core-locale-currency-numbers-time-and-dates.txt rename to devdocs/old-devdocs/specs/core-locale-currency-numbers-time-and-dates.txt index c827feb9..348e96ed 100644 --- a/devdocs/specs/core-locale-currency-numbers-time-and-dates.txt +++ b/devdocs/old-devdocs/specs/core-locale-currency-numbers-time-and-dates.txt @@ -1,42 +1,42 @@ -TIME (DATE AND TIME handling) - -SERVER RESPONSIBILITIES FOR DATES AND TIME ZONES: - - User object has a timezone offset field which is user selectable - - stores all times and dates in UTC in DB - - expects dates coming from client to be in UTC - - Does take into account timezone offset when FILTERING a LIST for sending to the client that has a relative date filter like [NEXTMONTH] - - This is the only place on the server where the user's time zone offset is used for anything - //************************ NOTE ABOUT TIME ZONES AND WHY I CHOSE TO USE A SELECTED OFFSET THE USER SETS RATHER THAN A TIME ZONE DESCRIPTOR - //.NET CORE AYANOVA SERVER RUNNING ON LINUX VS WINDOWS MAY NOT HAVE ALL TIME ZONES DEFINED AND MAY ERROR OUT - //THE ONLY SAFE WAY TO ENSURE CROSS PLATFORM TIME ZONE HANDLING FOR RELATIVE DATE FILTERS IS TO HAVE A HARD CODED TIME ZONE OFFSET - //THIS WAY USERS CAN SET IT AND IT'S INDEPENDENT OF ANY 3RD PARTY TIME ZONE DEFINITIONS ETC, MORE INFO HERE: - //https://devblogs.microsoft.com/dotnet/cross-platform-time-zones-with-net-core/ - /* - Time Zone differences - -Windows maintains its list of Time Zones in the Windows registry. You can find a list of those values here. - -In contrast, Linux distributions use the Time Zone database curated by the Internet Assigned Numbers Authority (IANA). You can find the latest copy of that database on IANA’s website. Here’s an example of what an IANA Time Zone looks like - -America/New_York - -The issue comes into play when you write your .NET Core code specifically using one of the two formats and then try to run the application on another operating system. Because the runtime is deferring the Time Zone management to the underlying operating system you will need to handle the differences if that scenario applies to you. - */ - - -LOCALE has defaults for currency, date, time handling - -CLIENT RESPONSIBILITIES FOR DATES AND TIME ZONES - - Send all datetime fields on records to the server in UTC - - Displayed dates and times are adjusted to user timezoneoffset - - Month, day of week name and am / pm designators come from localized text - - -CURRENCY - - - Displayed and accepted based on UserOption currency symbol - -NUMBER - - Displayed and accepted based on userOptions numeric format - - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat +TIME (DATE AND TIME handling) + +SERVER RESPONSIBILITIES FOR DATES AND TIME ZONES: + - User object has a timezone offset field which is user selectable + - stores all times and dates in UTC in DB + - expects dates coming from client to be in UTC + - Does take into account timezone offset when FILTERING a LIST for sending to the client that has a relative date filter like [NEXTMONTH] + - This is the only place on the server where the user's time zone offset is used for anything + //************************ NOTE ABOUT TIME ZONES AND WHY I CHOSE TO USE A SELECTED OFFSET THE USER SETS RATHER THAN A TIME ZONE DESCRIPTOR + //.NET CORE AYANOVA SERVER RUNNING ON LINUX VS WINDOWS MAY NOT HAVE ALL TIME ZONES DEFINED AND MAY ERROR OUT + //THE ONLY SAFE WAY TO ENSURE CROSS PLATFORM TIME ZONE HANDLING FOR RELATIVE DATE FILTERS IS TO HAVE A HARD CODED TIME ZONE OFFSET + //THIS WAY USERS CAN SET IT AND IT'S INDEPENDENT OF ANY 3RD PARTY TIME ZONE DEFINITIONS ETC, MORE INFO HERE: + //https://devblogs.microsoft.com/dotnet/cross-platform-time-zones-with-net-core/ + /* + Time Zone differences + +Windows maintains its list of Time Zones in the Windows registry. You can find a list of those values here. + +In contrast, Linux distributions use the Time Zone database curated by the Internet Assigned Numbers Authority (IANA). You can find the latest copy of that database on IANA’s website. Here’s an example of what an IANA Time Zone looks like + +America/New_York + +The issue comes into play when you write your .NET Core code specifically using one of the two formats and then try to run the application on another operating system. Because the runtime is deferring the Time Zone management to the underlying operating system you will need to handle the differences if that scenario applies to you. + */ + + +LOCALE has defaults for currency, date, time handling + +CLIENT RESPONSIBILITIES FOR DATES AND TIME ZONES + - Send all datetime fields on records to the server in UTC + - Displayed dates and times are adjusted to user timezoneoffset + - Month, day of week name and am / pm designators come from localized text + + +CURRENCY + + - Displayed and accepted based on UserOption currency symbol + +NUMBER + - Displayed and accepted based on userOptions numeric format + + https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat diff --git a/devdocs/specs/core-log-business.txt b/devdocs/old-devdocs/specs/core-log-business.txt similarity index 97% rename from devdocs/specs/core-log-business.txt rename to devdocs/old-devdocs/specs/core-log-business.txt index 28ac9137..e9bdba58 100644 --- a/devdocs/specs/core-log-business.txt +++ b/devdocs/old-devdocs/specs/core-log-business.txt @@ -1,73 +1,73 @@ -Business history log - -FROM CASE 79 -A central event log used to track major changes to business objects and major events of significance in AyaNova -Consumed by various widgets for record history purposes -Default feature, no need to turn on or off -Items are only removed from log when source object is deleted (and replaced with a deleted entry and textual description of deleted item) -Has to handle a scenario where there is no data for an object because in future we will likely have a purge feature or maybe a feature to turn it off and needs to accept that scenario -?FUTURE: Has some sort of checksum or verification so we can tell it wasn't fucked with (too hard to implement, would be something like a blockchain?) -?FUTURE: Needs a cleaner job that periodically looks for non-existant objects that are logged -?FUTURE: keeps logs for 45 days initially keeps forever or until object is deleted - - -ROUTES ------- -Fetch a constructed, localized log for the following: - - Supply user ID, optional time range, get back a log of everything the user did in order for all time or just the specified time range - - Supply object type, object id, optional time range, get back a log of history for that object for all time or time range specified - -Fetch the above but in raw form as data as well?? - -EVENT_TYPES ------------ -A master enum of all event types in RAVEN. -Co-used by this log feature, but also used by notification system -Also used by localized text feature to fetch text about event for display in log and notification etc -May be used for other things in future. -Common event types that apply to any object and then specific event types that apply to particular types of objects but all in the same master enum - -EventType -ALL OBJECTS -1 = created -2 = retrieved (keep just in case, but perhaps not to be used unless high level of logging required?) -3 = modified -4 = deleted - -SPECIFIC OBJECT EXAMPLE -Workorder: -4=Closed -5=Servicecompleted -6=all parts set to used in Service -7 = accepted from csr -etc - - -EVENT LOG DB SCHEMA ------------------------------------- -AYaTYPE (object type int), -AYID (object id), -AYEVENT (event of interest type int defined in central master enum of all events), -TIMESTAMP (unix epoch), -USERID, -TEXTRA (text field to identify stuff that can't be retrieved from source object, i.e. deleted record name) - - -DELETION --------- -Initially, the only way an entry is removed from the log is via deletion of the source object -When a source object is deleted, the entire history for that object is removed from the log and a new entry is created showing the deletion and textual representation of the object - - The record has the object type so no need to redundently store that, just the name: "1234" for workorder 1234 or "ABC Accounting" for the client name etc - - -PURGING (FUTURE) ----------------- -Items that might be most purgeable in any future purge scenario: -- Retrieved events -- File attachment download events -- fetch logfile - - -TODO: -1) Implement this log and routes to interact with it +Business history log + +FROM CASE 79 +A central event log used to track major changes to business objects and major events of significance in AyaNova +Consumed by various widgets for record history purposes +Default feature, no need to turn on or off +Items are only removed from log when source object is deleted (and replaced with a deleted entry and textual description of deleted item) +Has to handle a scenario where there is no data for an object because in future we will likely have a purge feature or maybe a feature to turn it off and needs to accept that scenario +?FUTURE: Has some sort of checksum or verification so we can tell it wasn't fucked with (too hard to implement, would be something like a blockchain?) +?FUTURE: Needs a cleaner job that periodically looks for non-existant objects that are logged +?FUTURE: keeps logs for 45 days initially keeps forever or until object is deleted + + +ROUTES +------ +Fetch a constructed, localized log for the following: + - Supply user ID, optional time range, get back a log of everything the user did in order for all time or just the specified time range + - Supply object type, object id, optional time range, get back a log of history for that object for all time or time range specified + +Fetch the above but in raw form as data as well?? + +EVENT_TYPES +----------- +A master enum of all event types in RAVEN. +Co-used by this log feature, but also used by notification system +Also used by localized text feature to fetch text about event for display in log and notification etc +May be used for other things in future. +Common event types that apply to any object and then specific event types that apply to particular types of objects but all in the same master enum + +EventType +ALL OBJECTS +1 = created +2 = retrieved (keep just in case, but perhaps not to be used unless high level of logging required?) +3 = modified +4 = deleted + +SPECIFIC OBJECT EXAMPLE +Workorder: +4=Closed +5=Servicecompleted +6=all parts set to used in Service +7 = accepted from csr +etc + + +EVENT LOG DB SCHEMA +------------------------------------ +AYaTYPE (object type int), +AYID (object id), +AYEVENT (event of interest type int defined in central master enum of all events), +TIMESTAMP (unix epoch), +USERID, +TEXTRA (text field to identify stuff that can't be retrieved from source object, i.e. deleted record name) + + +DELETION +-------- +Initially, the only way an entry is removed from the log is via deletion of the source object +When a source object is deleted, the entire history for that object is removed from the log and a new entry is created showing the deletion and textual representation of the object + - The record has the object type so no need to redundently store that, just the name: "1234" for workorder 1234 or "ABC Accounting" for the client name etc + + +PURGING (FUTURE) +---------------- +Items that might be most purgeable in any future purge scenario: +- Retrieved events +- File attachment download events +- fetch logfile + + +TODO: +1) Implement this log and routes to interact with it 2) Implement a cleaner job to remove events for nonexistant objects that aren't deleted \ No newline at end of file diff --git a/devdocs/specs/core-log-security.txt b/devdocs/old-devdocs/specs/core-log-security.txt similarity index 95% rename from devdocs/specs/core-log-security.txt rename to devdocs/old-devdocs/specs/core-log-security.txt index 9a90d752..cddcce8e 100644 --- a/devdocs/specs/core-log-security.txt +++ b/devdocs/old-devdocs/specs/core-log-security.txt @@ -1,14 +1,14 @@ -Security history log - -FROM CASE 1998 - - -A central event log used to track security related events of significance in AyaNova. - -- Authentication events (login, logoff) -- User creation / deletion -- User role changes - - -Auto prunes (can be set) -Has some sort of checksum or verification so we can tell it wasn't fucked with +Security history log + +FROM CASE 1998 + + +A central event log used to track security related events of significance in AyaNova. + +- Authentication events (login, logoff) +- User creation / deletion +- User role changes + + +Auto prunes (can be set) +Has some sort of checksum or verification so we can tell it wasn't fucked with diff --git a/devdocs/specs/core-long-running-operations.txt b/devdocs/old-devdocs/specs/core-long-running-operations.txt similarity index 97% rename from devdocs/specs/core-long-running-operations.txt rename to devdocs/old-devdocs/specs/core-long-running-operations.txt index 47624301..1faebe51 100644 --- a/devdocs/specs/core-long-running-operations.txt +++ b/devdocs/old-devdocs/specs/core-long-running-operations.txt @@ -1,75 +1,75 @@ -JOBS / LONG RUNNING OPERATIONS SPECS - - - -CASES - - - -REQUIREMENTS - -- An endpoint to view jobs in the table -- An endpoint to view logs of jobs -- A db schema (see below) -- biz object callable from other biz objects with following functionality - - Submit jobs - - Remove jobs - - Remove all jobs for object type and id (called when deleting an object) - - Update status of jobs - - Log ops of jobs - - - -- OPERATIONS endpoint: - - GET JOB LIST Check a list of jobs (with rights to do so). Works even when api is locked. - - GET /operations returns list of jobs sorted by lastActionDateTime or createdDateTime via query parameter - - { - "jobid":"1234", - "createdDateTime": "2015-06-19T12-01-03.45Z", - "lastActionDateTime": "2015-06-19T12-01-03.45Z", //<----determined from log, not stored in AOPSJOB - "name":"Send notifications | Import data | Backup | Restore", - "exclusive":"true/false", - "status": "sleeping | notstarted | running | succeeded | failed", - "log":"/operations/log/1234" - } - -- ROUTE: "OPERATIONS" endpoint to get log of long running operation /operations/log/1234 - - [ - { - "DateTime": "2015-06-19T12-01-03.45Z", - "Entry": "Imported 4 clients, 3 were duplicates and ignored" - }, - { - "DateTime": "2015-06-19T12-02-03.45Z", - "FAILED to import 5 workorders - data format invalid" - }, - { - "DateTime": "2015-06-19T12-04-03.45Z", - "Operation completed with errors" - } - ] - -- FUTURE: delete jobs that have not started yet -- FUTURE: cancel jobs and cancellation token - - - -SCHEMA -=-=-=-= - -AOPSJOB - - jobid long NOT NULL INDEXED UNIQUE (initially I'll use linux epoch when job created, used to tag logs etc, but keeping this open for a change later) - - Created NOT NULL - - Exclusive NOT NULL bool (true=close api and don't run any other jobs, false=process async and keep api open) - - StartAfter NOT NULL INDEXED (datetime to start the job, in cases of start now jobs the date will be minvalue) - - jobtype enum int NOT NULL of the jobtype which is an enum of all possible job types (i.e. NotifyClosed) - - ObjectId NULL source of job object id (i.e. workorder id) - - AType NULL source of job object type (i.e. workorder) - - descriptive name text NOT NULL for display in UI only, isn't filtered - - jobstatus enum int NOT NULL type (one of "sleeping | notstarted | running | succeeded | failed") - - jobinfo text NULL (json string of extra info required for job, maybe the name of an import file or who knows what, anything really can be put in here as long as it's shortish) - -AOPSJOBLOG - - jobid long not null - - created not null (indexed? Will be ordered by this a lot but it's the natural order...no?) - - statustext NOT NULL +JOBS / LONG RUNNING OPERATIONS SPECS + + + +CASES + + + +REQUIREMENTS + +- An endpoint to view jobs in the table +- An endpoint to view logs of jobs +- A db schema (see below) +- biz object callable from other biz objects with following functionality + - Submit jobs + - Remove jobs + - Remove all jobs for object type and id (called when deleting an object) + - Update status of jobs + - Log ops of jobs + + + +- OPERATIONS endpoint: + - GET JOB LIST Check a list of jobs (with rights to do so). Works even when api is locked. + - GET /operations returns list of jobs sorted by lastActionDateTime or createdDateTime via query parameter + - { + "jobid":"1234", + "createdDateTime": "2015-06-19T12-01-03.45Z", + "lastActionDateTime": "2015-06-19T12-01-03.45Z", //<----determined from log, not stored in AOPSJOB + "name":"Send notifications | Import data | Backup | Restore", + "exclusive":"true/false", + "status": "sleeping | notstarted | running | succeeded | failed", + "log":"/operations/log/1234" + } + +- ROUTE: "OPERATIONS" endpoint to get log of long running operation /operations/log/1234 + - [ + { + "DateTime": "2015-06-19T12-01-03.45Z", + "Entry": "Imported 4 clients, 3 were duplicates and ignored" + }, + { + "DateTime": "2015-06-19T12-02-03.45Z", + "FAILED to import 5 workorders - data format invalid" + }, + { + "DateTime": "2015-06-19T12-04-03.45Z", + "Operation completed with errors" + } + ] + +- FUTURE: delete jobs that have not started yet +- FUTURE: cancel jobs and cancellation token + + + +SCHEMA +=-=-=-= + +AOPSJOB + - jobid long NOT NULL INDEXED UNIQUE (initially I'll use linux epoch when job created, used to tag logs etc, but keeping this open for a change later) + - Created NOT NULL + - Exclusive NOT NULL bool (true=close api and don't run any other jobs, false=process async and keep api open) + - StartAfter NOT NULL INDEXED (datetime to start the job, in cases of start now jobs the date will be minvalue) + - jobtype enum int NOT NULL of the jobtype which is an enum of all possible job types (i.e. NotifyClosed) + - ObjectId NULL source of job object id (i.e. workorder id) + - AType NULL source of job object type (i.e. workorder) + - descriptive name text NOT NULL for display in UI only, isn't filtered + - jobstatus enum int NOT NULL type (one of "sleeping | notstarted | running | succeeded | failed") + - jobinfo text NULL (json string of extra info required for job, maybe the name of an import file or who knows what, anything really can be put in here as long as it's shortish) + +AOPSJOBLOG + - jobid long not null + - created not null (indexed? Will be ordered by this a lot but it's the natural order...no?) + - statustext NOT NULL diff --git a/devdocs/specs/core-main-grids.txt b/devdocs/old-devdocs/specs/core-main-grids.txt similarity index 98% rename from devdocs/specs/core-main-grids.txt rename to devdocs/old-devdocs/specs/core-main-grids.txt index 8048b8a8..c2f01797 100644 --- a/devdocs/specs/core-main-grids.txt +++ b/devdocs/old-devdocs/specs/core-main-grids.txt @@ -1,337 +1,337 @@ -MAIN GRID SPECS - -OVERVIEW -Main grids show all the stuff people have entered in Raven and are used for selection to edit/ view, filter and sort for reporting and mass operations. -Proposed system is a hybrid grid system that has two modes to take into account the width of the display device: - - MINI mode (XS ) < 600 pixels wide (my Pixel 3a phone is 393px) - - In this mode only one column shows and it's formatted according to the Display Format Template - - DisplayFormatTemplate is specd in the core-display-format-template-system.txt doc - - So the user chooses which columns to show in a small factor themselves, default is name only or equivalent - - As the client already does all the presentation and translation formatting it will also handle mini column concatenation - - The server's responsibility for mini is to use the mini format template which may well have different columns defined than the full - - Return the data just the same as for the wide template but it's very likely different data - - -CASES -None that are intrinsically grid related really, just 3 or so regarding specfic fields to add to grids - - -REQUIREMENTS - -Client - - Client needs to tell the server which list template is required, i.e. it's client window size when fetching a list - - HYBRID BIMODAL: MINI or default which is large (for now but consider maybe a medium down the road in planning) - - in MINI mode - - the client sends "mini=true" to the client with the grid data request - - Client receives two field list back (id and display field), displays the single field - - in large mode - - the client sends no mini= parameter as it's optional and understood to be full size - - - DATA the data object in the return contains the list of rows - - Each row contains a bunch of row objects - - Each column from the db is converted to an object and is formatted like this: - - {v:[field value],id:42[optional id value if openable]}, {v:[field value],id:42[optional id value if openable]}...etc - - rid flag: (was df) - - A column with a flag of rid:true means it's the RowId column or IsRowId and must be visible to user at client - - rid is not required because some datalists won't need one to open a record or have a practical row id due to the nature of the data - - for example ones used for REPORTING - - - - COLUMNS the list comes back as an object with not only the actual columns but also a separate property listing the set of columns in order to be displayed - - Also their data type - - Also need what type of object if openable with an url - - Client expects an arbitrary set of columns in an arbitrary order defined by server so doesn't have a pre-ordained set of things. - - The client needs to be able to handle more columns than fit horizontally - - The client needs to not wrap any column vertically but ellipse.. it instead - - Client accepts a list of fields and types etc and generates the grid and populates the data dynamically - - This means that I can make a general purpose Vue grid component, plunk it down on a form and then wrap it with what is unique about that form - -Server - - Server needs to accept a parameter from the client when a grid list is fetched that tells it if it needs to send a single column templated list - - vp="XS" I think would be sufficient (ViewPort = Extra Small) - - Grid lists need to know what their template is as more than one list might use the same template? - - SERVER SENDS LIST OF COLUMNS - - The server needs to tell the client which columns are coming back with the list and what types etc so the client can just adapt to any template setting - - column list has type of object behind each column if applicable and user has rights to open so client can make hyperlinks - - RID flagged column in column list is always the default RowID column corresponding to the underlying object and ID in the datalist - - rid column must have an id and an object type to be valid rid column - - SERVER SENDS DATA - - Data in a standard format all grid lists json format, not based on set objects (I think I can do that, probably a hybrid object with JSON data) - - Each row has each column as a object comprising of: - - Display value (the data to show, not formatted yet, that's up to the client) - - Optional: ID value (if the object is openable **** MUST CHECK RIGHTS ALSO HERE **** then this is the id to open for the client to put a hyperlink on that column) - - To save bandwidth abbreviations are used in the column definitions: - - ColumnsJSON=@"""columns"":[ {""cm"":""Widget"",""dt"":""text"",""ay"":"+ AyaType.Widget.ToString()+ "}]"; - - cm=column name translation key, dt=AyDataType, ay=AyaType to open on click of that column field (optional, not present if not openable) - - rid flagged column in each row is *ALWAYS* the rowID column specified in objectfields with it's sql attributes - - For example (wide list): - data:{ - columns:{[ {cm:"lt_client_name",dt:text,ay:2},{cm:"lt_client_notes",dt:text},{cm:"lt_last_workorder",dt:number,ay:workorder}]} - rows:{[ {},{v:"Green mechanics",id:32},"...notes...",{v:"42",id:42}, ...thousands more etc.... ]} - } - - For example (XS list) - data:{ - columns:{[ {cm:"lt_client",dt:text,ay:client}]} - rows:{ {display:"Green mechanics",id:32}, ...thousands more etc.... } - } - - - has separate property defining all columns in list, their datatype and ayatype if openable - - - -Back AND front end - - -OLD EF GRID QUERIES FOR REFERENCE -/* -This code -// #pragma warning disable EF1000 - - // //GET THE FULL LIST OF ITEMS - // var items = await ct.Widget - // .FromSqlRaw(q) - // .AsNoTracking() - // .Skip(listOptions.Offset.Value) - // .Take(listOptions.Limit.Value) - // .ToArrayAsync(); - // //GET THE RECORD COUNT - // var totalRecordCount = await ct.Widget - // .FromSqlRaw(q) - // .AsNoTracking() - // .CountAsync(); - // #pragma warning restore EF1000 - -Resulted in these queries: - - "SELECT id AS df, name, serial, dollaramount, roles, startdate, active FROM AWIDGET ORDER BY ID DESC LIMIT 2 OFFSET 1" - //PAGED FETCH LIST QUERY - SELECT a.id, a.active, a.xmin, a.count, a.customfields, a.dollaramount, a.enddate, a.name, a.notes, a.roles, a.serial, a.startdate, a.tags - FROM ( - SELECT *, xmin FROM AWIDGET ORDER BY ID DESC - ) AS a - ORDER BY (SELECT 1) - LIMIT @__p_2 OFFSET @__p_1 - 2020-01-16 10:10:28.8786|INFO|Microsoft.EntityFrameworkCore.Database.Command|Executed DbCommand (1ms) [Parameters=[@__p_2='2', @__p_1='1'], CommandType='Text', CommandTimeout='30'] - SELECT a.id, a.active, a.xmin, a.count, a.customfields, a.dollaramount, a.enddate, a.name, a.notes, a.roles, a.serial, a.startdate, a.tags - FROM ( - SELECT *, xmin FROM AWIDGET ORDER BY ID DESC - ) AS a - ORDER BY (SELECT 1) - LIMIT @__p_2 OFFSET @__p_1 - - //COUNT QUERY - SELECT COUNT(*)::INT - FROM ( - SELECT *, xmin FROM AWIDGET ORDER BY ID DESC - ) AS a - 2020-01-16 10:10:28.8991|INFO|Microsoft.EntityFrameworkCore.Database.Command|Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30'] - SELECT COUNT(*)::INT - FROM ( - SELECT *, xmin FROM AWIDGET ORDER BY ID DESC - ) AS a - */ - -And this response: -{ - "data": [ - { - "id": 99, - "concurrency": 4125297, - "name": "Gorgeous Wooden Chips 123", - "serial": 99, - "dollarAmount": 141.04, - "active": true, - "roles": 65536, - "startDate": "2020-01-16T20:31:02.427985Z", - "endDate": "2020-01-16T21:42:59.036309Z", - "notes": "Magnam rem soluta consequatur ut voluptas sit repellat. Vel veniam voluptatem aliquam. Dolor facilis aliquid qui quos amet.\n\nEst in eligendi cumque ut in repellat sed ut tempore. Accusantium deserunt odio voluptates quia. Est eveniet exercitationem autem quam. Delectus vel pariatur voluptatem sit velit nisi est voluptates. Voluptatem qui aut cum provident dolores dolor repellat quidem deleniti. Quo incidunt aut nisi minus qui velit.\n\nError natus incidunt maxime est. Esse vitae libero laboriosam iste. In eos ad. Aut provident repellendus adipisci sed ullam id. Eius aliquam voluptatem quae reiciendis mollitia illo recusandae nulla dolorum. Omnis deserunt ea hic non.", - "count": null, - "customFields": "{\"c1\":\"2019-09-15T10:18:56.8261768Z\",\"c2\":\"Qui ipsam explicabo provident est molestiae est et est ipsum. Qui quis non rem ipsum. Odit quasi veniam fuga dolor. Illum excepturi voluptatem ducimus qui sunt fugit quam delectus.\",\"c3\":43969672,\"c4\":true,\"c5\":0.634534356945443}", - "tags": [ - "zone-1" - ] - }, - { - "id": 98, - "concurrency": 4125290, - "name": "Tasty Rubber Towels 122", - "serial": 98, - "dollarAmount": 736.05, - "active": true, - "roles": 131071, - "startDate": "2020-01-16T20:42:08.10882Z", - "endDate": "2020-01-16T22:52:54.031664Z", - "notes": "Quo esse at esse quia. Est placeat voluptas. Velit fugit est quis nemo officia culpa officia et nam. Consequatur mollitia laboriosam tempora. Optio aut est quam fuga illum non mollitia quis.\n\nQui accusantium placeat voluptas eum. Voluptatem excepturi enim qui sunt. Delectus sequi illum libero repellat. Impedit illum sint consectetur.\n\nCum voluptatem nihil quis mollitia ut. Alias alias quis. Natus voluptatem ut omnis. In dolorem a et quia minus omnis ut. Ratione non velit nam corrupti repellendus quia voluptatum ut.", - "count": null, - "customFields": "{\"c1\":\"2020-11-08T09:13:34.4131282Z\",\"c2\":\"Consequatur ab sunt minima soluta aut quaerat aliquid aspernatur nihil. Et est incidunt. Minima rerum voluptatem sequi deleniti ducimus est soluta laboriosam excepturi. Aut vitae ut vel ea est. Voluptates officia in omnis blanditiis beatae exercitationem unde quibusdam.\",\"c3\":11364789,\"c4\":false,\"c5\":0.635780450718375}", - "tags": [ - "silver" - ] - } - ], - "paging": { - "count": 100, - "offset": 1, - "limit": 2, - "first": "http://test.helloayanova.com/api/v8/Widget/ListWidgets?pageNo=1&pageSize=2", - "previous": null, - "next": "http://test.helloayanova.com/api/v8/Widget/ListWidgets?pageNo=2&pageSize=2", - "last": "http://test.helloayanova.com/api/v8/Widget/ListWidgets?pageNo=50&pageSize=2" - } -} - - -=========================================================== SCRATCH AREA =============================================================== -sample current response for widget list: -se body -Download - -{ - "data": [ - { - "id": 99, - "concurrency": 3902247, - "name": "Awesome Wooden Shirt 123", - "serial": 99, - "dollarAmount": 630.45, - "active": true, - "roles": 8, - "startDate": "2020-01-08T15:29:39.626944Z", - "endDate": "2020-01-08T17:37:12.605146Z", - "notes": "Praesentium quisquam sit deserunt. Perferendis explicabo ipsam odit ab sequi mollitia ut. Sunt sint natus nihil quas quas est ut et. Non sed enim ut enim ut sed nisi reprehenderit.\n\nUt distinctio non. Rerum quam beatae illo qui fugiat fugiat totam. Vitae eveniet provident et consequuntur maxime perspiciatis et. Dolores veritatis sunt. Quia quae quo pariatur consequatur quia qui dolor. Vero aliquid voluptatem eos dicta provident atque eum.\n\nEt culpa rerum quis minus cumque eius facilis. Neque ad neque ratione. Eveniet exercitationem doloremque. Aut accusantium et voluptas. Laboriosam ipsa sit voluptatum voluptatem distinctio aut iusto et et. Et dolorem labore tempore odit.", - "count": null, - "customFields": "{\"c1\":\"2020-02-21T02:43:22.9011395Z\",\"c2\":\"Totam eligendi sed repudiandae delectus autem quas. At ut quasi quia tempore. Sit omnis modi a maiores quia est. Nam dolor amet. Inventore ea aut eum iusto quasi in nostrum. Aliquid voluptatibus error exercitationem accusamus molestias dolorem reprehenderit non.\",\"c3\":29779562,\"c4\":false,\"c5\":0.494726251109841}", - "tags": [ - "xanthic" - ] - }, - { - "id": 98, - "concurrency": 3902238, - "name": "Awesome Cotton Keyboard 122", - "serial": 98, - "dollarAmount": 926.28, - "active": true, - "roles": 65536, - "startDate": "2020-01-08T15:51:11.298854Z", - "endDate": "2020-01-08T16:57:08.492466Z", - "notes": "Qui inventore dicta. In sit non ducimus doloremque iste quos aut dicta. At et impedit et. Nesciunt saepe voluptatem debitis sed.\n\nQuisquam rerum expedita omnis in sit eos itaque. Libero temporibus voluptatum laborum dolorem optio voluptas voluptates. Impedit voluptatem qui. Natus dolores maxime in harum.\n\nLibero dolor delectus. Molestiae praesentium quis autem ut. Neque dolore voluptatem omnis. Quo ut consequatur rem.", - "count": null, - "customFields": "{\"c1\":\"2019-11-05T04:23:27.6063023Z\",\"c2\":\"Commodi vitae neque sit alias cumque cupiditate. A quos dolorem qui est commodi voluptate aut facilis. Perspiciatis quasi doloribus aut autem expedita excepturi qui nesciunt officiis.\",\"c3\":98808200,\"c4\":true,\"c5\":0.369711980861478}", - "tags": [ - "green", - "brown", - "zone-4" - ] - }, - { - "id": 97, - "concurrency": 3902230, - "name": "Rustic Granite Pizza 121", - "serial": 97, - "dollarAmount": 742.41, - "active": true, - "roles": 4, - "startDate": "2020-01-08T15:45:02.554965Z", - "endDate": "2020-01-08T17:38:51.771714Z", - "notes": "Maiores rerum consequatur eligendi. Mollitia error consequuntur quis vitae. Itaque totam quae quisquam est autem. Sunt et id non cum aperiam doloremque et qui. Qui est dolores officia et dolorem consequuntur molestias blanditiis nostrum.\n\nItaque tenetur cupiditate tempora exercitationem rerum sunt. Vel sit reiciendis. Dolorem vero velit praesentium enim. Nam soluta sed et tempore sint officia at doloremque facilis. Numquam ut dicta aut alias et repellendus consequatur ducimus quod. Natus quis aspernatur ut quibusdam dolores.\n\nVelit libero labore. Fuga quasi quis veniam minima aut. Odio est ducimus consectetur mollitia hic necessitatibus quaerat. Asperiores et qui qui.", - "count": null, - "customFields": "{\"c1\":\"2020-11-09T04:44:19.7102148Z\",\"c2\":\"Quisquam qui iusto voluptatibus incidunt dolore. Placeat praesentium aperiam harum culpa quas repellat aut corporis dolor. Explicabo et voluptatem. Debitis aliquam illo dolor eius esse quaerat aliquid rerum qui. Officiis quis consectetur consequatur fuga numquam earum fuga.\",\"c3\":20027131,\"c4\":true,\"c5\":0.225979427446602}", - "tags": [ - "brown", - "blue" - ] - } - ], - "paging": { - "count": 100, - "offset": 1, - "limit": 3, - "first": "http://localhost:7575/api/v8/Widget/ListWidgets?pageNo=1&pageSize=3", - "previous": null, - "next": "http://localhost:7575/api/v8/Widget/ListWidgets?pageNo=2&pageSize=3", - "last": "http://localhost:7575/api/v8/Widget/ListWidgets?pageNo=34&pageSize=3" - }, - "columns":[ - {name:"lt_client_name",datatype:text,ayatype:client},{name:"lt_client_notes",datatype:text},{name:"lt_last_workorder",datatype:number,ayatype:workorder} - ] -} - - -{ - "data": [ - ...all rows here ... - ] - } - ], - "paging": { - ...paging data... - }, - "columns":{ - ...column definitions .... - } -} - - -=-=-=-=-=-=- -PICKLIST FORMAT: -{ - "data": [ - { - "id": 93, - "name": "Awesome Cotton Sausages 117" - } - ], - "paging": { - "count": 100, - "offset": 0, - "limit": 1, - "first": "http://localhost:7575/api/v8/Widget/PickList?pageNo=1&pageSize=1", - "previous": null, - "next": "http://localhost:7575/api/v8/Widget/PickList?pageNo=1&pageSize=1", - "last": "http://localhost:7575/api/v8/Widget/PickList?pageNo=100&pageSize=1" - } -} - -... - -LIST format: - - -Response body -Download - -{ - "data": [ - { - "id": 100, - "concurrency": 3903699, - "name": "Licensed Granite Cheese 124", - "serial": 100, - "dollarAmount": 764.57, - "active": true, - "roles": 8, - "startDate": "2020-01-13T11:54:35.30427Z", - "endDate": "2020-01-13T13:32:24.675256Z", - "notes": "Consequuntur odio itaque quaerat et aspernatur rerum quis. Nam et ex assumenda deleniti. Vel est eum non exercitationem doloremque eos. Nesciunt voluptas et.\n\nCupiditate voluptatem pariatur. Totam et velit labore fugiat repudiandae. Harum consequatur quaerat ducimus animi dolores repellat dolorum. Necessitatibus sapiente non eveniet fugiat. Soluta voluptatem nihil omnis. Quasi et saepe nulla alias illum dolorem necessitatibus ut veniam.\n\nId est ullam quis est velit esse accusantium voluptas consequatur. Nesciunt error ab hic officia ullam sit. Vel inventore voluptatibus nam iure aut velit ducimus repellendus enim. Quisquam consequatur unde.", - "count": null, - "customFields": "{\"c1\":\"2020-09-27T12:59:50.4196015Z\",\"c2\":\"Id voluptatem cum id veniam hic accusamus labore deserunt. Ut non et possimus maiores repudiandae quia ea. Harum quo eius dicta iste laborum culpa in cumque illo.\",\"c3\":41534342,\"c4\":true,\"c5\":0.081620920487503}", - "tags": [ - "jade", - "brown", - "quince", - "zone-6", - "zone-7" - ] - } - ], - "paging": { - "count": 100, - "offset": 0, - "limit": 1, - "first": "http://localhost:7575/api/v8/Widget/ListWidgets?pageNo=1&pageSize=1", - "previous": null, - "next": "http://localhost:7575/api/v8/Widget/ListWidgets?pageNo=1&pageSize=1", - "last": "http://localhost:7575/api/v8/Widget/ListWidgets?pageNo=100&pageSize=1" - } +MAIN GRID SPECS + +OVERVIEW +Main grids show all the stuff people have entered in Raven and are used for selection to edit/ view, filter and sort for reporting and mass operations. +Proposed system is a hybrid grid system that has two modes to take into account the width of the display device: + - MINI mode (XS ) < 600 pixels wide (my Pixel 3a phone is 393px) + - In this mode only one column shows and it's formatted according to the Display Format Template + - DisplayFormatTemplate is specd in the core-display-format-template-system.txt doc + - So the user chooses which columns to show in a small factor themselves, default is name only or equivalent + - As the client already does all the presentation and translation formatting it will also handle mini column concatenation + - The server's responsibility for mini is to use the mini format template which may well have different columns defined than the full + - Return the data just the same as for the wide template but it's very likely different data + + +CASES +None that are intrinsically grid related really, just 3 or so regarding specfic fields to add to grids + + +REQUIREMENTS + +Client + - Client needs to tell the server which list template is required, i.e. it's client window size when fetching a list + - HYBRID BIMODAL: MINI or default which is large (for now but consider maybe a medium down the road in planning) + - in MINI mode + - the client sends "mini=true" to the client with the grid data request + - Client receives two field list back (id and display field), displays the single field + - in large mode + - the client sends no mini= parameter as it's optional and understood to be full size + + - DATA the data object in the return contains the list of rows + - Each row contains a bunch of row objects + - Each column from the db is converted to an object and is formatted like this: + - {v:[field value],id:42[optional id value if openable]}, {v:[field value],id:42[optional id value if openable]}...etc + - rid flag: (was df) + - A column with a flag of rid:true means it's the RowId column or IsRowId and must be visible to user at client + - rid is not required because some datalists won't need one to open a record or have a practical row id due to the nature of the data + - for example ones used for REPORTING + + + - COLUMNS the list comes back as an object with not only the actual columns but also a separate property listing the set of columns in order to be displayed + - Also their data type + - Also need what type of object if openable with an url + - Client expects an arbitrary set of columns in an arbitrary order defined by server so doesn't have a pre-ordained set of things. + - The client needs to be able to handle more columns than fit horizontally + - The client needs to not wrap any column vertically but ellipse.. it instead + - Client accepts a list of fields and types etc and generates the grid and populates the data dynamically + - This means that I can make a general purpose Vue grid component, plunk it down on a form and then wrap it with what is unique about that form + +Server + - Server needs to accept a parameter from the client when a grid list is fetched that tells it if it needs to send a single column templated list + - vp="XS" I think would be sufficient (ViewPort = Extra Small) + - Grid lists need to know what their template is as more than one list might use the same template? + - SERVER SENDS LIST OF COLUMNS + - The server needs to tell the client which columns are coming back with the list and what types etc so the client can just adapt to any template setting + - column list has type of object behind each column if applicable and user has rights to open so client can make hyperlinks + - RID flagged column in column list is always the default RowID column corresponding to the underlying object and ID in the datalist + - rid column must have an id and an object type to be valid rid column + - SERVER SENDS DATA + - Data in a standard format all grid lists json format, not based on set objects (I think I can do that, probably a hybrid object with JSON data) + - Each row has each column as a object comprising of: + - Display value (the data to show, not formatted yet, that's up to the client) + - Optional: ID value (if the object is openable **** MUST CHECK RIGHTS ALSO HERE **** then this is the id to open for the client to put a hyperlink on that column) + - To save bandwidth abbreviations are used in the column definitions: + - ColumnsJSON=@"""columns"":[ {""cm"":""Widget"",""dt"":""text"",""ay"":"+ AyaType.Widget.ToString()+ "}]"; + - cm=column name translation key, dt=AyDataType, ay=AyaType to open on click of that column field (optional, not present if not openable) + - rid flagged column in each row is *ALWAYS* the rowID column specified in objectfields with it's sql attributes + - For example (wide list): + data:{ + columns:{[ {cm:"lt_client_name",dt:text,ay:2},{cm:"lt_client_notes",dt:text},{cm:"lt_last_workorder",dt:number,ay:workorder}]} + rows:{[ {},{v:"Green mechanics",id:32},"...notes...",{v:"42",id:42}, ...thousands more etc.... ]} + } + - For example (XS list) + data:{ + columns:{[ {cm:"lt_client",dt:text,ay:client}]} + rows:{ {display:"Green mechanics",id:32}, ...thousands more etc.... } + } + + - has separate property defining all columns in list, their datatype and ayatype if openable + + + +Back AND front end + + +OLD EF GRID QUERIES FOR REFERENCE +/* +This code +// #pragma warning disable EF1000 + + // //GET THE FULL LIST OF ITEMS + // var items = await ct.Widget + // .FromSqlRaw(q) + // .AsNoTracking() + // .Skip(listOptions.Offset.Value) + // .Take(listOptions.Limit.Value) + // .ToArrayAsync(); + // //GET THE RECORD COUNT + // var totalRecordCount = await ct.Widget + // .FromSqlRaw(q) + // .AsNoTracking() + // .CountAsync(); + // #pragma warning restore EF1000 + +Resulted in these queries: + + "SELECT id AS df, name, serial, dollaramount, roles, startdate, active FROM AWIDGET ORDER BY ID DESC LIMIT 2 OFFSET 1" + //PAGED FETCH LIST QUERY + SELECT a.id, a.active, a.xmin, a.count, a.customfields, a.dollaramount, a.enddate, a.name, a.notes, a.roles, a.serial, a.startdate, a.tags + FROM ( + SELECT *, xmin FROM AWIDGET ORDER BY ID DESC + ) AS a + ORDER BY (SELECT 1) + LIMIT @__p_2 OFFSET @__p_1 + 2020-01-16 10:10:28.8786|INFO|Microsoft.EntityFrameworkCore.Database.Command|Executed DbCommand (1ms) [Parameters=[@__p_2='2', @__p_1='1'], CommandType='Text', CommandTimeout='30'] + SELECT a.id, a.active, a.xmin, a.count, a.customfields, a.dollaramount, a.enddate, a.name, a.notes, a.roles, a.serial, a.startdate, a.tags + FROM ( + SELECT *, xmin FROM AWIDGET ORDER BY ID DESC + ) AS a + ORDER BY (SELECT 1) + LIMIT @__p_2 OFFSET @__p_1 + + //COUNT QUERY + SELECT COUNT(*)::INT + FROM ( + SELECT *, xmin FROM AWIDGET ORDER BY ID DESC + ) AS a + 2020-01-16 10:10:28.8991|INFO|Microsoft.EntityFrameworkCore.Database.Command|Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30'] + SELECT COUNT(*)::INT + FROM ( + SELECT *, xmin FROM AWIDGET ORDER BY ID DESC + ) AS a + */ + +And this response: +{ + "data": [ + { + "id": 99, + "concurrency": 4125297, + "name": "Gorgeous Wooden Chips 123", + "serial": 99, + "dollarAmount": 141.04, + "active": true, + "roles": 65536, + "startDate": "2020-01-16T20:31:02.427985Z", + "endDate": "2020-01-16T21:42:59.036309Z", + "notes": "Magnam rem soluta consequatur ut voluptas sit repellat. Vel veniam voluptatem aliquam. Dolor facilis aliquid qui quos amet.\n\nEst in eligendi cumque ut in repellat sed ut tempore. Accusantium deserunt odio voluptates quia. Est eveniet exercitationem autem quam. Delectus vel pariatur voluptatem sit velit nisi est voluptates. Voluptatem qui aut cum provident dolores dolor repellat quidem deleniti. Quo incidunt aut nisi minus qui velit.\n\nError natus incidunt maxime est. Esse vitae libero laboriosam iste. In eos ad. Aut provident repellendus adipisci sed ullam id. Eius aliquam voluptatem quae reiciendis mollitia illo recusandae nulla dolorum. Omnis deserunt ea hic non.", + "count": null, + "customFields": "{\"c1\":\"2019-09-15T10:18:56.8261768Z\",\"c2\":\"Qui ipsam explicabo provident est molestiae est et est ipsum. Qui quis non rem ipsum. Odit quasi veniam fuga dolor. Illum excepturi voluptatem ducimus qui sunt fugit quam delectus.\",\"c3\":43969672,\"c4\":true,\"c5\":0.634534356945443}", + "tags": [ + "zone-1" + ] + }, + { + "id": 98, + "concurrency": 4125290, + "name": "Tasty Rubber Towels 122", + "serial": 98, + "dollarAmount": 736.05, + "active": true, + "roles": 131071, + "startDate": "2020-01-16T20:42:08.10882Z", + "endDate": "2020-01-16T22:52:54.031664Z", + "notes": "Quo esse at esse quia. Est placeat voluptas. Velit fugit est quis nemo officia culpa officia et nam. Consequatur mollitia laboriosam tempora. Optio aut est quam fuga illum non mollitia quis.\n\nQui accusantium placeat voluptas eum. Voluptatem excepturi enim qui sunt. Delectus sequi illum libero repellat. Impedit illum sint consectetur.\n\nCum voluptatem nihil quis mollitia ut. Alias alias quis. Natus voluptatem ut omnis. In dolorem a et quia minus omnis ut. Ratione non velit nam corrupti repellendus quia voluptatum ut.", + "count": null, + "customFields": "{\"c1\":\"2020-11-08T09:13:34.4131282Z\",\"c2\":\"Consequatur ab sunt minima soluta aut quaerat aliquid aspernatur nihil. Et est incidunt. Minima rerum voluptatem sequi deleniti ducimus est soluta laboriosam excepturi. Aut vitae ut vel ea est. Voluptates officia in omnis blanditiis beatae exercitationem unde quibusdam.\",\"c3\":11364789,\"c4\":false,\"c5\":0.635780450718375}", + "tags": [ + "silver" + ] + } + ], + "paging": { + "count": 100, + "offset": 1, + "limit": 2, + "first": "http://test.helloayanova.com/api/v8/Widget/ListWidgets?pageNo=1&pageSize=2", + "previous": null, + "next": "http://test.helloayanova.com/api/v8/Widget/ListWidgets?pageNo=2&pageSize=2", + "last": "http://test.helloayanova.com/api/v8/Widget/ListWidgets?pageNo=50&pageSize=2" + } +} + + +=========================================================== SCRATCH AREA =============================================================== +sample current response for widget list: +se body +Download + +{ + "data": [ + { + "id": 99, + "concurrency": 3902247, + "name": "Awesome Wooden Shirt 123", + "serial": 99, + "dollarAmount": 630.45, + "active": true, + "roles": 8, + "startDate": "2020-01-08T15:29:39.626944Z", + "endDate": "2020-01-08T17:37:12.605146Z", + "notes": "Praesentium quisquam sit deserunt. Perferendis explicabo ipsam odit ab sequi mollitia ut. Sunt sint natus nihil quas quas est ut et. Non sed enim ut enim ut sed nisi reprehenderit.\n\nUt distinctio non. Rerum quam beatae illo qui fugiat fugiat totam. Vitae eveniet provident et consequuntur maxime perspiciatis et. Dolores veritatis sunt. Quia quae quo pariatur consequatur quia qui dolor. Vero aliquid voluptatem eos dicta provident atque eum.\n\nEt culpa rerum quis minus cumque eius facilis. Neque ad neque ratione. Eveniet exercitationem doloremque. Aut accusantium et voluptas. Laboriosam ipsa sit voluptatum voluptatem distinctio aut iusto et et. Et dolorem labore tempore odit.", + "count": null, + "customFields": "{\"c1\":\"2020-02-21T02:43:22.9011395Z\",\"c2\":\"Totam eligendi sed repudiandae delectus autem quas. At ut quasi quia tempore. Sit omnis modi a maiores quia est. Nam dolor amet. Inventore ea aut eum iusto quasi in nostrum. Aliquid voluptatibus error exercitationem accusamus molestias dolorem reprehenderit non.\",\"c3\":29779562,\"c4\":false,\"c5\":0.494726251109841}", + "tags": [ + "xanthic" + ] + }, + { + "id": 98, + "concurrency": 3902238, + "name": "Awesome Cotton Keyboard 122", + "serial": 98, + "dollarAmount": 926.28, + "active": true, + "roles": 65536, + "startDate": "2020-01-08T15:51:11.298854Z", + "endDate": "2020-01-08T16:57:08.492466Z", + "notes": "Qui inventore dicta. In sit non ducimus doloremque iste quos aut dicta. At et impedit et. Nesciunt saepe voluptatem debitis sed.\n\nQuisquam rerum expedita omnis in sit eos itaque. Libero temporibus voluptatum laborum dolorem optio voluptas voluptates. Impedit voluptatem qui. Natus dolores maxime in harum.\n\nLibero dolor delectus. Molestiae praesentium quis autem ut. Neque dolore voluptatem omnis. Quo ut consequatur rem.", + "count": null, + "customFields": "{\"c1\":\"2019-11-05T04:23:27.6063023Z\",\"c2\":\"Commodi vitae neque sit alias cumque cupiditate. A quos dolorem qui est commodi voluptate aut facilis. Perspiciatis quasi doloribus aut autem expedita excepturi qui nesciunt officiis.\",\"c3\":98808200,\"c4\":true,\"c5\":0.369711980861478}", + "tags": [ + "green", + "brown", + "zone-4" + ] + }, + { + "id": 97, + "concurrency": 3902230, + "name": "Rustic Granite Pizza 121", + "serial": 97, + "dollarAmount": 742.41, + "active": true, + "roles": 4, + "startDate": "2020-01-08T15:45:02.554965Z", + "endDate": "2020-01-08T17:38:51.771714Z", + "notes": "Maiores rerum consequatur eligendi. Mollitia error consequuntur quis vitae. Itaque totam quae quisquam est autem. Sunt et id non cum aperiam doloremque et qui. Qui est dolores officia et dolorem consequuntur molestias blanditiis nostrum.\n\nItaque tenetur cupiditate tempora exercitationem rerum sunt. Vel sit reiciendis. Dolorem vero velit praesentium enim. Nam soluta sed et tempore sint officia at doloremque facilis. Numquam ut dicta aut alias et repellendus consequatur ducimus quod. Natus quis aspernatur ut quibusdam dolores.\n\nVelit libero labore. Fuga quasi quis veniam minima aut. Odio est ducimus consectetur mollitia hic necessitatibus quaerat. Asperiores et qui qui.", + "count": null, + "customFields": "{\"c1\":\"2020-11-09T04:44:19.7102148Z\",\"c2\":\"Quisquam qui iusto voluptatibus incidunt dolore. Placeat praesentium aperiam harum culpa quas repellat aut corporis dolor. Explicabo et voluptatem. Debitis aliquam illo dolor eius esse quaerat aliquid rerum qui. Officiis quis consectetur consequatur fuga numquam earum fuga.\",\"c3\":20027131,\"c4\":true,\"c5\":0.225979427446602}", + "tags": [ + "brown", + "blue" + ] + } + ], + "paging": { + "count": 100, + "offset": 1, + "limit": 3, + "first": "http://localhost:7575/api/v8/Widget/ListWidgets?pageNo=1&pageSize=3", + "previous": null, + "next": "http://localhost:7575/api/v8/Widget/ListWidgets?pageNo=2&pageSize=3", + "last": "http://localhost:7575/api/v8/Widget/ListWidgets?pageNo=34&pageSize=3" + }, + "columns":[ + {name:"lt_client_name",datatype:text,ayatype:client},{name:"lt_client_notes",datatype:text},{name:"lt_last_workorder",datatype:number,ayatype:workorder} + ] +} + + +{ + "data": [ + ...all rows here ... + ] + } + ], + "paging": { + ...paging data... + }, + "columns":{ + ...column definitions .... + } +} + + +=-=-=-=-=-=- +PICKLIST FORMAT: +{ + "data": [ + { + "id": 93, + "name": "Awesome Cotton Sausages 117" + } + ], + "paging": { + "count": 100, + "offset": 0, + "limit": 1, + "first": "http://localhost:7575/api/v8/Widget/PickList?pageNo=1&pageSize=1", + "previous": null, + "next": "http://localhost:7575/api/v8/Widget/PickList?pageNo=1&pageSize=1", + "last": "http://localhost:7575/api/v8/Widget/PickList?pageNo=100&pageSize=1" + } +} + +... + +LIST format: + + +Response body +Download + +{ + "data": [ + { + "id": 100, + "concurrency": 3903699, + "name": "Licensed Granite Cheese 124", + "serial": 100, + "dollarAmount": 764.57, + "active": true, + "roles": 8, + "startDate": "2020-01-13T11:54:35.30427Z", + "endDate": "2020-01-13T13:32:24.675256Z", + "notes": "Consequuntur odio itaque quaerat et aspernatur rerum quis. Nam et ex assumenda deleniti. Vel est eum non exercitationem doloremque eos. Nesciunt voluptas et.\n\nCupiditate voluptatem pariatur. Totam et velit labore fugiat repudiandae. Harum consequatur quaerat ducimus animi dolores repellat dolorum. Necessitatibus sapiente non eveniet fugiat. Soluta voluptatem nihil omnis. Quasi et saepe nulla alias illum dolorem necessitatibus ut veniam.\n\nId est ullam quis est velit esse accusantium voluptas consequatur. Nesciunt error ab hic officia ullam sit. Vel inventore voluptatibus nam iure aut velit ducimus repellendus enim. Quisquam consequatur unde.", + "count": null, + "customFields": "{\"c1\":\"2020-09-27T12:59:50.4196015Z\",\"c2\":\"Id voluptatem cum id veniam hic accusamus labore deserunt. Ut non et possimus maiores repudiandae quia ea. Harum quo eius dicta iste laborum culpa in cumque illo.\",\"c3\":41534342,\"c4\":true,\"c5\":0.081620920487503}", + "tags": [ + "jade", + "brown", + "quince", + "zone-6", + "zone-7" + ] + } + ], + "paging": { + "count": 100, + "offset": 0, + "limit": 1, + "first": "http://localhost:7575/api/v8/Widget/ListWidgets?pageNo=1&pageSize=1", + "previous": null, + "next": "http://localhost:7575/api/v8/Widget/ListWidgets?pageNo=1&pageSize=1", + "last": "http://localhost:7575/api/v8/Widget/ListWidgets?pageNo=100&pageSize=1" + } } \ No newline at end of file diff --git a/devdocs/specs/core-notification.txt b/devdocs/old-devdocs/specs/core-notification.txt similarity index 98% rename from devdocs/specs/core-notification.txt rename to devdocs/old-devdocs/specs/core-notification.txt index 31f78f1e..14fe109b 100644 --- a/devdocs/specs/core-notification.txt +++ b/devdocs/old-devdocs/specs/core-notification.txt @@ -1,377 +1,377 @@ -# Notification specifications - - - - -############### LAST STATE OF THIS 2020-05-15 12:56:44: - Had gone over cases and triaged them, not super fleshed out yet how it works behind the scenes but basically - same as v7, object save triggers notification check which puts items into and takes them out of notify event table - recurring job processes them - Ideally would like to see event of interest check with cached data but need to consider how many different things would be in that, could be huge - since I will be adding so many new notification types and they are more complex. - - client end is a list type form also each object can notify directly on demand and all users have default notification subscription - - No longer templating but rather using short single text string with link back to open instead and optionally links to open report / attachment or whatever - also no delivery days or hours fuckery anymore, all deliveries happen all the time as appropriate to the event deliver date. If user wants that they can configure - their device email notification settings, not our concern anymore. - - No reports are attached anymore, no need to generate a report outside of a User login session via the client!!! - - -########################################################### -BACKEND TODO / SYSTEM FOR RAVEN - -IMPLEMENTATION PATH / PLAN - code as minimal a route as possible to get to working notifications end to end with minimal subset - first is test notification which is done as an implementation of the GeneralNotification Event type and is delivered to the current use running the test - This will go through all potential problems or maybe trigger a troubleshoot route at the server that checks all and reports back with any issues found - Also needs to be localized (do the test route thing, that just makes the most sense. The test route should accept the type of notification i.e. inapp or smtp, act accordingly if it's a customer user vs regular if there is any difference) - Should report to user exactly any issues found at any level preventing it from happening - Should submit as a job and await running in place like other ones so that its actually working end to end with the generator - OR - should it submit and send immediately bypassing generator as just an immediate test. - OR - maybe it's an option for the user to choose. - - widget / user crud ops and tag filtered in both App and in smtp - Then viewed in UI and worked with, properly shows count waiting etc - Examine system, bulletproof it as much as possible from first impressions - Make sure all controls work for - Once have that then can flesh out all the rest afterwards - -todo: Make the notification subscription front end page - At least enough to subscription to widget biz notifications - with translation keys - route needed of existing subs - route to add sub - route to delete sub - ui list of subs editable and saveable as a collection? - biz object - do it like widgets list and widget items, list up front and edit behind - TODO: - Do from front end back to server - SubscriptionList datalist needed first - timespan ui type for grid display - then edit form and routes can be added - Going to need a timespan control for editing - - -todo: make the ops notification front end page -todo: make the biz notification page -todo: implement the Widget and User crud notification systems as per spec with an eye to replicating everywhere and allowing for specialty other types in system - i.e. not just crud but future stuff like workorder status change etc - also this is where the tags come into play -todo: make the job objects -todo: should be able to send a test notification to any user from user form (or user list via Customer form) as a means of ensuring the system works -todo: sql filter at server for timespan type -TODO: Translation keys needed: - NotifyDeliveryMethod - NotifyEventType - NotifyDeliveryAddress - tags - - - -todo: updating subscriptions must clear out old events and notifications if they are affected -TODO: check before any thing that might create a dupe -todo: have removed the old v7 SMTP retry deliveries for simplification - instead, it will now act as if this is always set to true - Probe email server first if can't contact then skip smtp delivers (same as v7 when this setting true) - New: will make every effort to err on the side of assuming delivery happened in any issue during delivery - This will be one way to ensure it doesn't pile on the emails because of some spurious issue that actually delivered but it seemed like it might not have - User will be able to go into notifyevent table adn remove any items they don't want delivered in case of issue - -TODO: import v7 needs to create users for each contact and set their default for deliveries of notifications based on old region and send notification setting - Make a case for this and or implement it with this work so it doesn't get lost - -CREATING NOTIFICATIONS -OBJECTS Saving an object triggers notification processing for that object: - - in v7 biz object just submits any possible notification and later it's checked to see if anyone subscribes - would be better to short circuit that at the biz object to stop if no events of interest - - TODO: Every corebiz object needs at least to support created / updated with tag type as a minimum - - type and id is submitted to eventofinterest checker (possibly also tags I think) - AyaType, ID, eventlist,objectbefore,objectafter - eventofinterest db table contains each type and event id - some types are generic and apply to all corebiz for example - i.e. tags used on an object or added - but a workorder object would be best suited to check if a workorder is interesting event? - monolithic class for all notifications goes through a giant switch? - - HASH to prevent dupes - hash all the relevant bits of a notification that make it unique then check the db table to see if that hash exists already, this is a fast way to prevent dupes - should notify if this happens a lot maybe? - Post delivery maybe keep a hash of the event notified on so it doesn't re-notify the exact same thing repeatedly after it was already sent - - SUBSCRIPTION - All users have an implied / assumed default subscription InApp to default notifications - User's indicate subscription with record in subscription table - Table has one row PER delivery method they want, default is APP type delivery meaning inside application - SMTP is alternative and will deliver via email to email account or phone sms etc - FUTURE may have alternatives here - DUPES are ignored - This table is consulted for all decisions about notifications, no more eventofinterest separate table nor subscriber - DUPES - there can be near dupes here because user may have multiple of identical but vary in only: - Delivery method - advancenoticetimespan (e.g. contract expiring could be one 90 days in advance to renegotiate and then one 10 days in advance for notify service to cancel etc) - tags - notify applies if has these tags - empty means any - s - notify cancelled if has these tags - empty means any - out trumps an in, default is safer option - - CONDITION - has optional condition fields (in v7 was guidvalue for wo status type, but we need more [investigate?]) - - DELIVERY METHODS - no more date ranges for delivery windows - Two methods initially - SMTP - APP (meaning in notifications system inside application basically the old POPUP) - -UI TODO - Subscription form for user - Subscription form for client (personal or set by administrator, probably set by administrator) - Mass set for many users at once - - -V8 TABLES / OBJECTS -JOBS - NotifySweeper - APP notifications - deletes all APP notifications older than 90 days (if they want to keep it then can turn it into a reminder or SAVE it somehow) - NotifyEvent - - deletes any notifyevent with no event date created more than 90 days ago - If has event date and it's passed then deletes it if created more than 90 days ago (pretty sure there are no back dated events, once it's passed it's past) - NotifyDeliveryLog - deletes all log items older than 90 days - Notify - Scan the notifyevent table and deliver notifications accordingly - -GlobalBizSettings - Add Notification system ACTIVE bool value - -GlobalOpsNotificationSettings (copy from backup settings) - SMTP creds, return address - -ALL COREBIZ - Need CRUD check for notification events - Need to handle check of new tags vs existing tags (delta of tags) for any notification type - Need central common code just like biz rules check that processes notifications upon any changes - asks notifysubscription code which notifications to process - subscriptions code has either cached or on db lookup to see all that apply, returns an array of notifyeventtypes to be processed - Processes each notifyeventtype that it handles or passes off to central one maybe in some cases if common code - -/NotifyEventType enum - A collection of every possible notification event in one central location (rather than the old system where each object type held it's own collection) - -Translation keys for each notify event type as these will display in the UI and in sent emails etc - -NotifyDeliveryMethod enum - SMTP, INAPP (more in future) - -NotifySubscriptionBiz - handles checking for subscription relevancy and returning to biz object caller what types of notify events to process - handles CRUD and biz rules for notifysubscriptions - -NotifyEventBiz - handles CRUD for notify events, called statically from all over the place - puts events in the table, removes them, updates them - Has no part in delivery except maybe to provide list to delivery object - provides list for admin user to remove items if they want and to view what is in there to be processed - -NotificationBiz - handles CRUD for (app) Notification items displayed to user in app UI - handles flagging as seen and deleting etc - -NotifyDeliveryBiz - handle delivery and logging to notifydeliverylog - called by generator periodically - -MailMessageDelivery - Maybe a separate object to abstract deliving emails - - -/notifysubscription table - contains all user (and customer user) subscriptions to events and delivery method, if user wants two delivery -methods they have two entries here, no other table indicates events to be tracked, has user id - also ayatype must be specific not GLOBAL to avoid a "sorcerers apprentice" runaway issue and many role related issues potentially - so for example a CreatedWithTag notification or UpdatedWithTag notification will work on any object with that tag if a specific type i.e. customer with that tag - Then they can control by tag as well, tags are used to filter and include (or any if no tags), s filter out and trump tags - These are also used for tag type conditions - (aID, userId, ayatype, aEventType, advancenoticetimespan, agevalue, idvalue, decvalue, aDeliveryMethod, deliveryaddress, linkreportid, tags, s, HASH) - -/Notifyevent table - contains all events, created by updating objects or directly in some cases and used by generator for processing as deliveries - created (timestamp used to clean out old stuck events), ayatype, objectid, eventtype, appliestouserid (single subscriber event), aEventDate, ASAVEDMESSAGE, HASH? - -notifydeliverylog table - intended for troubleshooting, logs deliveries with a cap on how many records it retains. Keeping this as a separate and distinct OPS ui thing - (ayatype, objectID, aEventType, aGuidValue, aDeliveryDate, aToUserID, aDeliveryMethod, aDelivered, aErrorMessage, aToClientID, HASH ) - -/notification table - was popup, now the ones that show in the APP type notify delivery in the UI list; has fields for opening source and reading message and indicating read - Note: deliberately no delivery date, if it's in this table it's delivered to user, advancenotice and genprocess handle whether it's in this table or not - eventtype should generally be enough for message but the "message" field contains any extra info - COLUMNS: id, userid, ayatype, objectid, eventtype (for message in ui), message - -########################################################### - - -Important cases: -client viewing ui (was popup in v7) https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/3783 - - - -ALL EVENT TYPES INITIAL RELEASE -================================ - - -## OLD -WorkOrderStatusChange [GENERAL] [CONDITION: WOSTATUS integer] -ContractExpiring (User notify, add more notify before time frames in cases) [GENERAL] -CSRAccepted [CUSTOMER] -CSRRejected [CUSTOMER] -NewWorkorder [CUSTOMER] -WorkorderStatusChange [CUSTOMER] [CONDITION: WOSTATUS integer] -### DEPRECATED, WOSTATUS "Finished" status type event now replaces this ### WorkorderClosed [CUSTOMER] -### HOLD for v.next lots of cases around customer satisfaction survey etc not initial release though WorkorderFollowUp [CUSTOMER]###### -QuoteStatusChanged [CUSTOMER] [CONDITION: QUOTESTATUS integer] -ServiceBank[Currency/Hours/Incidents]Depleted [GENERAL] -NewCSR [GENERAL] -NewMemo [PERSONAL] -QuickNotification DEPRECATED replaced by GeneralNotification below [PERSONAL] -QuoteCreatedUpdated - a bit weird, which is it created or updated? :) [GENERAL] -ScheduleMarkerImminent (now "reminder") [PERSONAL] -ScheduleMarkerCreated (now "reminder") [PERSONAL] -WorkOrderItemScheduledUserCreatedUpdated [PERSONAL] -WorkOrderItemScheduledUserEventImminent [PERSONAL] -### CHANGED same concept but uses a COMPLETED type status as the trigger, so I guess it's WorkorderPastCompletionDate or something### WorkorderCloseByDatePassed (user) [general] -WorkorderStatusChanged (user) [GENERAL] [CONDITION: WOSTATUS integer] -WorkOrderItemOutsideServiceOverdue [general] -WorkOrderItemOutsideServiceReceivedBack [GENERAL] -WorkOrderItemPartRequestPartsReceived [GENERAL] - - -## NEW -DEADMAN_Job_procesor_fail direct email and other notifications? - Not sure how this could work to be honest, it would need to have a generator to do the checking unless we're talking about another timer somewhere else -Daily_Notify_health_check (biz and ops) [GENERAL] CREATED BY NOTIFY DELIVERY PROCESSOR -Nightly_Notify_health_check (biz and ops)[GENERAL] created by notify delivery processor -BackupStatus case 3786 (biz and ops) [GENERAL] - (OR is this more of a general OPERATIONS notifications without choosing specific type because anyone in ops needs all) -UpcomingServiceEvent case 3725 [CUSTOMER] -WorkOrderItemPartRequestCreated case 3652 [GENERAL] -ContractExpiring - Customer version in addition to User version [CUSTOMER] -WorkorderTotalExceedsThreshold - Custom notification case 1745 "the andy" [GENERAL] [CONDITION: DOLLARTOTAL money value] -WorkOrderStatusAge "deadman" delivery if *SPECIFIC* status not changed to different status before XX time period [GENERAL] [CONDITION: AGEVALUE] -https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/1137 - NOTE: this will need a timespan with a different title - -QuoteStatusAge [PERSONAL (prepared by), GENERAL] [CONDITION: AGEVALUE] -UnitWarranyExpiry case 1361 [GENERAL] -UnitMeterReadingMultipleExceeded case 1254 [GENERAL] -GeneralNotification case 3792 used for all system and old Quick notifications [EVERYONE] - Always present for inapp, user can add more for email if they want and filters or whatever but there is always a built in non-visible subscription to inapp for this - -deprecated, use objectCRUD events for this: TagNotification case 3799 [CONDITION: tag, , ayatype global/specific] - (Note: this is actually just general notification if an object is created or updated and the tagging is optional) - -CRUD Notifications: - (note: tag filterable and select type specifically. Global is not a valid type for this to avoid issues) - (note: - - ### WHAT DOES THIS MEAN?:differs from tag notification above in that only applies on a CHANGE of TAGS, this is an always for this op and tags are just an optional filter) - - [CONDITION: tag, , ayatype specific] - ObjectCreated - ObjectUpdated - ObjectDeleted - ObjectAge since creation (this will cover a shitload of use cases, for example workorder follow up could be done this way etc) [CONDITION: AGEVALUE] - -PERSONAL? OR COVERED BY TAG FILTER ALREADY BETTER? - WorkOrderItemPartRequestPartsReceivedWhenIAmScheduled [PERSONAL] - WorkOrderItemOutsideServiceReceivedBackWhenIAmScheduled - WorkOrderItemOutsideServiceOverdueWhenIAmScheduled - WorkorderCloseByDatePassedWhenIAmScheduled - WorkorderStatusChangedWhenIAmScheduled [PERSONAL] - - -Not for certain but in the hopper to think about: -On demand ad-hoc notification case 3466 for specific object only - not sure how to handle that, but it's a very intruiging idea, maybe it's a v.next one though? - or maybe the tags thing will handle this? - - -CUSTOMER NOTIFICATIONS AND CHANGES -A bcc field for all customer notification subscriptions per case 3398 - -SCRATCHPAD IDEAS -=-=-=-=-=-=-=-=-=- - -OVERVIEW -General - thinking of reforming it, making all notifications very short since user can go to directly view data online anyway now, why have an overly time consuming system to format and shit - i.e. no notification more than an SMS (160 characters but will accept more and split them up to 1600) tweet in length (280 characters) - - In cases where user wants to send a link to an attachment / report / wiki that's another thing entirely but the message is still super short - - All notifications can be optionally filtered IN or OUT via tags on notification related object. I.E. a workorder status change can be ignored or only see if it's tagged "region-new-york" etc - - All users can receive general notifications which come from both the system itself and from other users using the new ad-hoc send notification from any form - -UI -Subscribe from the object itself's menu rather than centralized subscription setup (new) -Admin can still subscribe users on their behalf (new) - -SYSTEM --=-=-=-=-=-=-=-=-=- -EVENT_OF_INTEREST_CLASS - -Internal workings: - - Should cache the event of interest for quick saving processing and save db getting hammered every time an object is saved - - - -One enum list of NotificationType for any possible notification that can be processed - Notify type is divided by actual type and then by actual delivery method -No delivery schedule anymore, let user decide how to handle at their device end, not our concern, just deliver immediately always -Notify BEfore should support multiple time frames, not just one -Users not involved should not be notified, have choice on that` - e.g. if a user is not booked on a workorder and is just a lowly tech they don't care about other workorder status changes - - -Types of notifications sitting in delivery queue: - Deliver if something not changed before date "DEADMAN SWITCH" - upon change that negates it from source object it removes the event as no longer required - Deliver immediately regardless - easy peasy - - - - - - - -DELIVERY TYPES - Email - UI - (previusly was ayanova memo, but, that's toast now, removing it) -DELIVERY FORMAT - Custom templates for each notification set up centrally? - - - -Hypothetical sequence of operations for designing raven notification and tie into jobs and processor - -WidgetStatusChange notification - - OnChange event triggered in [WIDGETBIZ] with before and after state of widget in question (immediately after save or delete or whatever is of interest) - - OnChange processor See if any users are subscribed to this event [CENTRAL_NOTIFICATION_CLASS THIS MUST BE SUPER EFFICIENT AS IT WILL BE HAMMERED] - (events of interest / core central event bus handler of some kind??) - - CENTRAL_NOTIFICATION_CLASS event of interest should cache in memory events of interest and trigger cache invalidation by [EVENT_OF_INTEREST_CLASS] subscription change - - If no then bail out early - - If yes then compares the before and after state of the widget and the given list of events of interest and processes notifications in turn - - Create a notification event in a table of pending notification events [CENTRAL_NOTIFICATION_CLASS] - - See v7 schema for ideas - -Deliver notifications - - Job triggers and HandleJob is called on [CENTRAL_NOTIFICATION_CLASS] which in turn checks if any events ready to Deliver - - Hands off NOTIFY_EVENT to deliver one at a time to a [NOTIFICATION_DELIVERY_CLASS] which in turn calls each [NOTIFICATION_DELIVERY_DELIVERY_TYPE-SMTP/POPUP/WHATEVER] - - -Maintenance - - [CoreJobNotificationSweeper class] maintains the notifications tables see generator spec for thoughts - - - +# Notification specifications + + + + +############### LAST STATE OF THIS 2020-05-15 12:56:44: + Had gone over cases and triaged them, not super fleshed out yet how it works behind the scenes but basically + same as v7, object save triggers notification check which puts items into and takes them out of notify event table + recurring job processes them + Ideally would like to see event of interest check with cached data but need to consider how many different things would be in that, could be huge + since I will be adding so many new notification types and they are more complex. + + client end is a list type form also each object can notify directly on demand and all users have default notification subscription + + No longer templating but rather using short single text string with link back to open instead and optionally links to open report / attachment or whatever + also no delivery days or hours fuckery anymore, all deliveries happen all the time as appropriate to the event deliver date. If user wants that they can configure + their device email notification settings, not our concern anymore. + + No reports are attached anymore, no need to generate a report outside of a User login session via the client!!! + + +########################################################### +BACKEND TODO / SYSTEM FOR RAVEN + +IMPLEMENTATION PATH / PLAN - code as minimal a route as possible to get to working notifications end to end with minimal subset + first is test notification which is done as an implementation of the GeneralNotification Event type and is delivered to the current use running the test + This will go through all potential problems or maybe trigger a troubleshoot route at the server that checks all and reports back with any issues found + Also needs to be localized (do the test route thing, that just makes the most sense. The test route should accept the type of notification i.e. inapp or smtp, act accordingly if it's a customer user vs regular if there is any difference) + Should report to user exactly any issues found at any level preventing it from happening + Should submit as a job and await running in place like other ones so that its actually working end to end with the generator + OR + should it submit and send immediately bypassing generator as just an immediate test. + OR + maybe it's an option for the user to choose. + + widget / user crud ops and tag filtered in both App and in smtp + Then viewed in UI and worked with, properly shows count waiting etc + Examine system, bulletproof it as much as possible from first impressions + Make sure all controls work for + Once have that then can flesh out all the rest afterwards + +todo: Make the notification subscription front end page + At least enough to subscription to widget biz notifications + with translation keys + route needed of existing subs + route to add sub + route to delete sub + ui list of subs editable and saveable as a collection? + biz object + do it like widgets list and widget items, list up front and edit behind + TODO: + Do from front end back to server + SubscriptionList datalist needed first + timespan ui type for grid display + then edit form and routes can be added + Going to need a timespan control for editing + + +todo: make the ops notification front end page +todo: make the biz notification page +todo: implement the Widget and User crud notification systems as per spec with an eye to replicating everywhere and allowing for specialty other types in system + i.e. not just crud but future stuff like workorder status change etc + also this is where the tags come into play +todo: make the job objects +todo: should be able to send a test notification to any user from user form (or user list via Customer form) as a means of ensuring the system works +todo: sql filter at server for timespan type +TODO: Translation keys needed: + NotifyDeliveryMethod + NotifyEventType + NotifyDeliveryAddress + tags + + + +todo: updating subscriptions must clear out old events and notifications if they are affected +TODO: check before any thing that might create a dupe +todo: have removed the old v7 SMTP retry deliveries for simplification + instead, it will now act as if this is always set to true + Probe email server first if can't contact then skip smtp delivers (same as v7 when this setting true) + New: will make every effort to err on the side of assuming delivery happened in any issue during delivery + This will be one way to ensure it doesn't pile on the emails because of some spurious issue that actually delivered but it seemed like it might not have + User will be able to go into notifyevent table adn remove any items they don't want delivered in case of issue + +TODO: import v7 needs to create users for each contact and set their default for deliveries of notifications based on old region and send notification setting + Make a case for this and or implement it with this work so it doesn't get lost + +CREATING NOTIFICATIONS +OBJECTS Saving an object triggers notification processing for that object: + - in v7 biz object just submits any possible notification and later it's checked to see if anyone subscribes + would be better to short circuit that at the biz object to stop if no events of interest + - TODO: Every corebiz object needs at least to support created / updated with tag type as a minimum + - type and id is submitted to eventofinterest checker (possibly also tags I think) + AyaType, ID, eventlist,objectbefore,objectafter + eventofinterest db table contains each type and event id + some types are generic and apply to all corebiz for example + i.e. tags used on an object or added + but a workorder object would be best suited to check if a workorder is interesting event? + monolithic class for all notifications goes through a giant switch? + - HASH to prevent dupes + hash all the relevant bits of a notification that make it unique then check the db table to see if that hash exists already, this is a fast way to prevent dupes + should notify if this happens a lot maybe? + Post delivery maybe keep a hash of the event notified on so it doesn't re-notify the exact same thing repeatedly after it was already sent + - SUBSCRIPTION + All users have an implied / assumed default subscription InApp to default notifications + User's indicate subscription with record in subscription table + Table has one row PER delivery method they want, default is APP type delivery meaning inside application + SMTP is alternative and will deliver via email to email account or phone sms etc + FUTURE may have alternatives here + DUPES are ignored + This table is consulted for all decisions about notifications, no more eventofinterest separate table nor subscriber + DUPES - there can be near dupes here because user may have multiple of identical but vary in only: + Delivery method + advancenoticetimespan (e.g. contract expiring could be one 90 days in advance to renegotiate and then one 10 days in advance for notify service to cancel etc) + tags - notify applies if has these tags + empty means any + s - notify cancelled if has these tags + empty means any + out trumps an in, default is safer option + + CONDITION + has optional condition fields (in v7 was guidvalue for wo status type, but we need more [investigate?]) + - DELIVERY METHODS + no more date ranges for delivery windows + Two methods initially + SMTP + APP (meaning in notifications system inside application basically the old POPUP) + +UI TODO + Subscription form for user + Subscription form for client (personal or set by administrator, probably set by administrator) + Mass set for many users at once + + +V8 TABLES / OBJECTS +JOBS + NotifySweeper + APP notifications - deletes all APP notifications older than 90 days (if they want to keep it then can turn it into a reminder or SAVE it somehow) + NotifyEvent - + deletes any notifyevent with no event date created more than 90 days ago + If has event date and it's passed then deletes it if created more than 90 days ago (pretty sure there are no back dated events, once it's passed it's past) + NotifyDeliveryLog - deletes all log items older than 90 days + Notify + Scan the notifyevent table and deliver notifications accordingly + +GlobalBizSettings + Add Notification system ACTIVE bool value + +GlobalOpsNotificationSettings (copy from backup settings) + SMTP creds, return address + +ALL COREBIZ + Need CRUD check for notification events + Need to handle check of new tags vs existing tags (delta of tags) for any notification type + Need central common code just like biz rules check that processes notifications upon any changes + asks notifysubscription code which notifications to process + subscriptions code has either cached or on db lookup to see all that apply, returns an array of notifyeventtypes to be processed + Processes each notifyeventtype that it handles or passes off to central one maybe in some cases if common code + +/NotifyEventType enum + A collection of every possible notification event in one central location (rather than the old system where each object type held it's own collection) + +Translation keys for each notify event type as these will display in the UI and in sent emails etc + +NotifyDeliveryMethod enum + SMTP, INAPP (more in future) + +NotifySubscriptionBiz + handles checking for subscription relevancy and returning to biz object caller what types of notify events to process + handles CRUD and biz rules for notifysubscriptions + +NotifyEventBiz + handles CRUD for notify events, called statically from all over the place + puts events in the table, removes them, updates them + Has no part in delivery except maybe to provide list to delivery object + provides list for admin user to remove items if they want and to view what is in there to be processed + +NotificationBiz + handles CRUD for (app) Notification items displayed to user in app UI + handles flagging as seen and deleting etc + +NotifyDeliveryBiz + handle delivery and logging to notifydeliverylog + called by generator periodically + +MailMessageDelivery + Maybe a separate object to abstract deliving emails + + +/notifysubscription table - contains all user (and customer user) subscriptions to events and delivery method, if user wants two delivery +methods they have two entries here, no other table indicates events to be tracked, has user id + also ayatype must be specific not GLOBAL to avoid a "sorcerers apprentice" runaway issue and many role related issues potentially + so for example a CreatedWithTag notification or UpdatedWithTag notification will work on any object with that tag if a specific type i.e. customer with that tag + Then they can control by tag as well, tags are used to filter and include (or any if no tags), s filter out and trump tags + These are also used for tag type conditions + (aID, userId, ayatype, aEventType, advancenoticetimespan, agevalue, idvalue, decvalue, aDeliveryMethod, deliveryaddress, linkreportid, tags, s, HASH) + +/Notifyevent table - contains all events, created by updating objects or directly in some cases and used by generator for processing as deliveries + created (timestamp used to clean out old stuck events), ayatype, objectid, eventtype, appliestouserid (single subscriber event), aEventDate, ASAVEDMESSAGE, HASH? + +notifydeliverylog table - intended for troubleshooting, logs deliveries with a cap on how many records it retains. Keeping this as a separate and distinct OPS ui thing + (ayatype, objectID, aEventType, aGuidValue, aDeliveryDate, aToUserID, aDeliveryMethod, aDelivered, aErrorMessage, aToClientID, HASH ) + +/notification table - was popup, now the ones that show in the APP type notify delivery in the UI list; has fields for opening source and reading message and indicating read + Note: deliberately no delivery date, if it's in this table it's delivered to user, advancenotice and genprocess handle whether it's in this table or not + eventtype should generally be enough for message but the "message" field contains any extra info + COLUMNS: id, userid, ayatype, objectid, eventtype (for message in ui), message + +########################################################### + + +Important cases: +client viewing ui (was popup in v7) https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/3783 + + + +ALL EVENT TYPES INITIAL RELEASE +================================ + + +## OLD +WorkOrderStatusChange [GENERAL] [CONDITION: WOSTATUS integer] +ContractExpiring (User notify, add more notify before time frames in cases) [GENERAL] +CSRAccepted [CUSTOMER] +CSRRejected [CUSTOMER] +NewWorkorder [CUSTOMER] +WorkorderStatusChange [CUSTOMER] [CONDITION: WOSTATUS integer] +### DEPRECATED, WOSTATUS "Finished" status type event now replaces this ### WorkorderClosed [CUSTOMER] +### HOLD for v.next lots of cases around customer satisfaction survey etc not initial release though WorkorderFollowUp [CUSTOMER]###### +QuoteStatusChanged [CUSTOMER] [CONDITION: QUOTESTATUS integer] +ServiceBank[Currency/Hours/Incidents]Depleted [GENERAL] +NewCSR [GENERAL] +NewMemo [PERSONAL] +QuickNotification DEPRECATED replaced by GeneralNotification below [PERSONAL] +QuoteCreatedUpdated - a bit weird, which is it created or updated? :) [GENERAL] +ScheduleMarkerImminent (now "reminder") [PERSONAL] +ScheduleMarkerCreated (now "reminder") [PERSONAL] +WorkOrderItemScheduledUserCreatedUpdated [PERSONAL] +WorkOrderItemScheduledUserEventImminent [PERSONAL] +### CHANGED same concept but uses a COMPLETED type status as the trigger, so I guess it's WorkorderPastCompletionDate or something### WorkorderCloseByDatePassed (user) [general] +WorkorderStatusChanged (user) [GENERAL] [CONDITION: WOSTATUS integer] +WorkOrderItemOutsideServiceOverdue [general] +WorkOrderItemOutsideServiceReceivedBack [GENERAL] +WorkOrderItemPartRequestPartsReceived [GENERAL] + + +## NEW +DEADMAN_Job_procesor_fail direct email and other notifications? + Not sure how this could work to be honest, it would need to have a generator to do the checking unless we're talking about another timer somewhere else +Daily_Notify_health_check (biz and ops) [GENERAL] CREATED BY NOTIFY DELIVERY PROCESSOR +Nightly_Notify_health_check (biz and ops)[GENERAL] created by notify delivery processor +BackupStatus case 3786 (biz and ops) [GENERAL] + (OR is this more of a general OPERATIONS notifications without choosing specific type because anyone in ops needs all) +UpcomingServiceEvent case 3725 [CUSTOMER] +WorkOrderItemPartRequestCreated case 3652 [GENERAL] +ContractExpiring - Customer version in addition to User version [CUSTOMER] +WorkorderTotalExceedsThreshold - Custom notification case 1745 "the andy" [GENERAL] [CONDITION: DOLLARTOTAL money value] +WorkOrderStatusAge "deadman" delivery if *SPECIFIC* status not changed to different status before XX time period [GENERAL] [CONDITION: AGEVALUE] +https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/1137 + NOTE: this will need a timespan with a different title + +QuoteStatusAge [PERSONAL (prepared by), GENERAL] [CONDITION: AGEVALUE] +UnitWarranyExpiry case 1361 [GENERAL] +UnitMeterReadingMultipleExceeded case 1254 [GENERAL] +GeneralNotification case 3792 used for all system and old Quick notifications [EVERYONE] + Always present for inapp, user can add more for email if they want and filters or whatever but there is always a built in non-visible subscription to inapp for this + +deprecated, use objectCRUD events for this: TagNotification case 3799 [CONDITION: tag, , ayatype global/specific] + (Note: this is actually just general notification if an object is created or updated and the tagging is optional) + +CRUD Notifications: + (note: tag filterable and select type specifically. Global is not a valid type for this to avoid issues) + (note: + + ### WHAT DOES THIS MEAN?:differs from tag notification above in that only applies on a CHANGE of TAGS, this is an always for this op and tags are just an optional filter) + + [CONDITION: tag, , ayatype specific] + ObjectCreated + ObjectUpdated + ObjectDeleted + ObjectAge since creation (this will cover a shitload of use cases, for example workorder follow up could be done this way etc) [CONDITION: AGEVALUE] + +PERSONAL? OR COVERED BY TAG FILTER ALREADY BETTER? + WorkOrderItemPartRequestPartsReceivedWhenIAmScheduled [PERSONAL] + WorkOrderItemOutsideServiceReceivedBackWhenIAmScheduled + WorkOrderItemOutsideServiceOverdueWhenIAmScheduled + WorkorderCloseByDatePassedWhenIAmScheduled + WorkorderStatusChangedWhenIAmScheduled [PERSONAL] + + +Not for certain but in the hopper to think about: +On demand ad-hoc notification case 3466 for specific object only + not sure how to handle that, but it's a very intruiging idea, maybe it's a v.next one though? + or maybe the tags thing will handle this? + + +CUSTOMER NOTIFICATIONS AND CHANGES +A bcc field for all customer notification subscriptions per case 3398 + +SCRATCHPAD IDEAS +=-=-=-=-=-=-=-=-=- + +OVERVIEW +General + thinking of reforming it, making all notifications very short since user can go to directly view data online anyway now, why have an overly time consuming system to format and shit + i.e. no notification more than an SMS (160 characters but will accept more and split them up to 1600) tweet in length (280 characters) + + In cases where user wants to send a link to an attachment / report / wiki that's another thing entirely but the message is still super short + + All notifications can be optionally filtered IN or OUT via tags on notification related object. I.E. a workorder status change can be ignored or only see if it's tagged "region-new-york" etc + + All users can receive general notifications which come from both the system itself and from other users using the new ad-hoc send notification from any form + +UI +Subscribe from the object itself's menu rather than centralized subscription setup (new) +Admin can still subscribe users on their behalf (new) + +SYSTEM +-=-=-=-=-=-=-=-=-=- +EVENT_OF_INTEREST_CLASS + +Internal workings: + + Should cache the event of interest for quick saving processing and save db getting hammered every time an object is saved + + + +One enum list of NotificationType for any possible notification that can be processed + Notify type is divided by actual type and then by actual delivery method +No delivery schedule anymore, let user decide how to handle at their device end, not our concern, just deliver immediately always +Notify BEfore should support multiple time frames, not just one +Users not involved should not be notified, have choice on that` + e.g. if a user is not booked on a workorder and is just a lowly tech they don't care about other workorder status changes + + +Types of notifications sitting in delivery queue: + Deliver if something not changed before date "DEADMAN SWITCH" + upon change that negates it from source object it removes the event as no longer required + Deliver immediately regardless + easy peasy + + + + + + + +DELIVERY TYPES + Email + UI + (previusly was ayanova memo, but, that's toast now, removing it) +DELIVERY FORMAT + Custom templates for each notification set up centrally? + + + +Hypothetical sequence of operations for designing raven notification and tie into jobs and processor + +WidgetStatusChange notification + - OnChange event triggered in [WIDGETBIZ] with before and after state of widget in question (immediately after save or delete or whatever is of interest) + - OnChange processor See if any users are subscribed to this event [CENTRAL_NOTIFICATION_CLASS THIS MUST BE SUPER EFFICIENT AS IT WILL BE HAMMERED] + (events of interest / core central event bus handler of some kind??) + - CENTRAL_NOTIFICATION_CLASS event of interest should cache in memory events of interest and trigger cache invalidation by [EVENT_OF_INTEREST_CLASS] subscription change + - If no then bail out early + - If yes then compares the before and after state of the widget and the given list of events of interest and processes notifications in turn + - Create a notification event in a table of pending notification events [CENTRAL_NOTIFICATION_CLASS] + - See v7 schema for ideas + +Deliver notifications + - Job triggers and HandleJob is called on [CENTRAL_NOTIFICATION_CLASS] which in turn checks if any events ready to Deliver + - Hands off NOTIFY_EVENT to deliver one at a time to a [NOTIFICATION_DELIVERY_CLASS] which in turn calls each [NOTIFICATION_DELIVERY_DELIVERY_TYPE-SMTP/POPUP/WHATEVER] + + +Maintenance + - [CoreJobNotificationSweeper class] maintains the notifications tables see generator spec for thoughts + + + diff --git a/devdocs/specs/core-ops-metrics.txt b/devdocs/old-devdocs/specs/core-ops-metrics.txt similarity index 97% rename from devdocs/specs/core-ops-metrics.txt rename to devdocs/old-devdocs/specs/core-ops-metrics.txt index 37ce4d06..6bc8df02 100644 --- a/devdocs/specs/core-ops-metrics.txt +++ b/devdocs/old-devdocs/specs/core-ops-metrics.txt @@ -1,66 +1,66 @@ -SYSOPS METRICS / HEALTH CHECKS - - - - -Right now as of May 7th 2018 here are the remaining outstanding issues for metrics: - -TODO OUTSTANDING ISSUES - -1) Need to make my own dashboard for non endpoint stats for Graphana. Actually a dashboard that covers all AyaNova would be good -https://www.influxdata.com/blog/how-to-use-grafana-with-influxdb-to-monitor-time-series-data/ -2) Save the dashboard as JSON text for the manual -3) See about making my own Grafana / INfluxdb container and include it in compose.yml for AyaNova server so can deploy it easily (with my own panels pre-built) -4) DOCUMENT -5) Skim below and see if I have covered it all. - - -Need to revise my metrics to bring in mvccore instead of mvc?: - - https://github.com/AppMetrics/AppMetrics/issues/261#issuecomment-404051808 - -Might be time to order all this to the best effectiveness if it isn't already. - - - -OLD OLD OLD OLD -This is old stuff I was using during research and initial implementation some of it may still be relevant later -=-=-=-=-=-=-=-=-=- - -APRIL 26 2018 - DID SOME RESEARCH, THIS IS ACTUALLY A VERY COMPLEX TOPIC AND BEST HANDLED WITH A 3RD PARTY TOOL -- There is an open source metrics tool and an open source db it can work with the is a time series data store (influxdb, elasticsearch) designed for exactly this scenario -- Influxdb has a docker container available -- Shitty thing is I would need some of this information for support purposes built in, not requiring some fancy 3rd party tools which are very cool for a large setup, -but a small one man show doesn't require that. -- Perhaps RAVEN can have a big corporate edition that is all intended to be containerized and comes with influxdb and preconfigured with metrics on. -- It handles both metrics and "HEALTH CHECK" issues in one package - -- I'm not sure if this is a v1.0 feature, though it would help in development to see what's what route writes -- If it can be an optional thing that can be turned on then that would be ideal -- https://al-hardy.blog/2017/04/28/asp-net-core-monitoring-with-influxdb-grafana/ -- https://www.app-metrics.io/ - - - -Ops Metrics - - - CASE 3502 Add metrics - - CASE 3502 Metric: record count in each table or at least major ones as a snapshot metric so can compare month to month. - - CASE 3497 ACTIVE user count - Log user login, last login and login per X period - - CASE 3499 "Slow" I want to know if anything is slow, not what the user says but what the code determines - - - - - - some kind of internal metrics to track changes over time in operations with thresholds to trigger logs maybe? - - Has to be super fast, maybe an internal counter / cache in memory and a periodic job that writes it out to DB, i.e. don't write to db metrics on every get operation etc - - Average response time? - - Busyness / unique logins or tokens in use? A way to see how many distinct users are connecting over a period of time so we know how utilized it is? - - Utilization? - - Areas / routes used in AyaNova and how often / frequently they are used (we could use this for feature utilization) - - CPU peak usage snapshot - - Disk space change over time snapshots - - - HEALTH CHECKS - - Comes with appmetrics: +SYSOPS METRICS / HEALTH CHECKS + + + + +Right now as of May 7th 2018 here are the remaining outstanding issues for metrics: + +TODO OUTSTANDING ISSUES + +1) Need to make my own dashboard for non endpoint stats for Graphana. Actually a dashboard that covers all AyaNova would be good +https://www.influxdata.com/blog/how-to-use-grafana-with-influxdb-to-monitor-time-series-data/ +2) Save the dashboard as JSON text for the manual +3) See about making my own Grafana / INfluxdb container and include it in compose.yml for AyaNova server so can deploy it easily (with my own panels pre-built) +4) DOCUMENT +5) Skim below and see if I have covered it all. + + +Need to revise my metrics to bring in mvccore instead of mvc?: + - https://github.com/AppMetrics/AppMetrics/issues/261#issuecomment-404051808 + +Might be time to order all this to the best effectiveness if it isn't already. + + + +OLD OLD OLD OLD +This is old stuff I was using during research and initial implementation some of it may still be relevant later +=-=-=-=-=-=-=-=-=- + +APRIL 26 2018 - DID SOME RESEARCH, THIS IS ACTUALLY A VERY COMPLEX TOPIC AND BEST HANDLED WITH A 3RD PARTY TOOL +- There is an open source metrics tool and an open source db it can work with the is a time series data store (influxdb, elasticsearch) designed for exactly this scenario +- Influxdb has a docker container available +- Shitty thing is I would need some of this information for support purposes built in, not requiring some fancy 3rd party tools which are very cool for a large setup, +but a small one man show doesn't require that. +- Perhaps RAVEN can have a big corporate edition that is all intended to be containerized and comes with influxdb and preconfigured with metrics on. +- It handles both metrics and "HEALTH CHECK" issues in one package + +- I'm not sure if this is a v1.0 feature, though it would help in development to see what's what route writes +- If it can be an optional thing that can be turned on then that would be ideal +- https://al-hardy.blog/2017/04/28/asp-net-core-monitoring-with-influxdb-grafana/ +- https://www.app-metrics.io/ + + + +Ops Metrics + + - CASE 3502 Add metrics + - CASE 3502 Metric: record count in each table or at least major ones as a snapshot metric so can compare month to month. + - CASE 3497 ACTIVE user count - Log user login, last login and login per X period + - CASE 3499 "Slow" I want to know if anything is slow, not what the user says but what the code determines + + + + + - some kind of internal metrics to track changes over time in operations with thresholds to trigger logs maybe? + - Has to be super fast, maybe an internal counter / cache in memory and a periodic job that writes it out to DB, i.e. don't write to db metrics on every get operation etc + - Average response time? + - Busyness / unique logins or tokens in use? A way to see how many distinct users are connecting over a period of time so we know how utilized it is? + - Utilization? + - Areas / routes used in AyaNova and how often / frequently they are used (we could use this for feature utilization) + - CPU peak usage snapshot + - Disk space change over time snapshots + + + HEALTH CHECKS + - Comes with appmetrics: - https://al-hardy.blog/2017/04/17/asp-net-core-health-checking/ \ No newline at end of file diff --git a/devdocs/specs/core-ops-support-info-log.txt b/devdocs/old-devdocs/specs/core-ops-support-info-log.txt similarity index 97% rename from devdocs/specs/core-ops-support-info-log.txt rename to devdocs/old-devdocs/specs/core-ops-support-info-log.txt index a8623190..d2ce1b51 100644 --- a/devdocs/specs/core-ops-support-info-log.txt +++ b/devdocs/old-devdocs/specs/core-ops-support-info-log.txt @@ -1,85 +1,85 @@ -SYSOPS HEALTH CHECK / METRICS - -https://www.datadoghq.com/blog/monitoring-101-collecting-data/ - -OK, considered this and a log is a log and all logs are relevant to sysops people so I'm going to treat all logging the same regardless and make an effort to ensure each log entry -is tagged with the relevant class name - -CRITICAL ISSUES -- Check for critical issues in a health check periodic job which also logs and metrics -- Critical issues should be logged first then sent via notification for system operators if subscribed -- - -METRICS -- metrics should be gathered in DB and reported on via UI for ops users and potentially in other formats down the road - - - -TODO LIST OF THINGS CODED THAT NEED TO BE LOGGED -- Items in code tagged with this: - - //TODO: core-log-sysop -- Generator failures -- IJobBiz derived objects failures - -- configuration changes ??? -- Install and uninstall feature changes -- Warnings (low disk space, slowness monitoring, db issues) (during health check JOB??) - - -"HEALTH CHECK" JOB -- things that need to be metric a sized are commented with //OPSMETRIC -- Maybe a "health check" job or "checkup" job that periodically asseses things and reports findings -- works in conjunction with metrics gathered maybe? - - Metrics would be a system that for example could get free disk space then get it again a few days later and project ahead to getting low and warning or simple when down to 10% warn or etc -- Anything we'd like to see from a support point of view would be useful too -- Go over the research doc to see what was recommended -- Dig up that guys example project on his blog that he was going to add metrics to. -- Brainstorm a list of recent support issues and what could be a benefit in dealing with them -- "Slowness" comes up a lot. - - -Ops Metrics - CONFIRMED REQUIRED - - Gather in memory and flush to db on a schedule is best - - CASE 3562 If found, count of mismatch of attached files in database vs file system - - CASE 3523 Log major ops related configuration changes (before and after snapshot) - - CASE 3502 Log feature or route or endpoint usage count as a snapshot metric so can compare month to month. - - CASE 3502 Log record count in each table or at least major ones as a snapshot metric so can compare month to month. - - CASE 3497 ACTIVE user count - Log user login, last login and login per X period - - CASE 3499 "Slow" I want to know if anything is slow, not what the user says but what the code determines - - RESEARCH / IDEAS / EXAMPLES - - Metric types: - - https://www.app-metrics.io/getting-started/metric-types/ - - Code example that deals with this issue: - - https://github.com/AppMetrics/AppMetrics/tree/dev/src/App.Metrics.Core - - Need more than one window into the data, for example we need a last few minutes (5?) view so people can see at a glance what is happening NOW - - But also need to know what was it historically. So maybe we need a NOW algorithm but also a HISTORICAL algorithm. - - Maybe a sliding scale of recency, so a 5 minute view, a THIS WEEK view and then a month to month view beyond that?? - - LIBRARIES - - Health check Health Checks give you the ability to monitor the health of your application by writing a small tests which returns either a healthy, degraded or unhealthy result. - - https://www.app-metrics.io/health-checks/ - - APP METRICS - - https://github.com/AppMetrics/AppMetrics - - Different types of metrics are Gauges, Counters, Meters, Histograms and Timers and Application Performance Indexes - - METRICS of a system: - - Network. Network metrics are related to network bandwidth usage. - - System. System metrics are related to processor, memory, disk I/O, and network I/O. - - Platform. Platform metrics are related to ASP.NET, and the .NET common language runtime (CLR). - - Application. Application metrics include custom performance counters "Application Instrumentation". - - Service level. Service level metrics are related to your application, such as orders per second and searches per second. - - USEFUL INFO HERE FOR SYSTEM METRICS LIKE MEMORY ETC: This document from Microsoft gives generally accepted limits for things like CPU threshold, memory etc in actual percentages - - Section "System Resources" here https://msdn.microsoft.com/en-us/library/ff647791.aspx#scalenetchapt15_topic5 - - - USEFUL EXAMPLE dashboard for web applications: - - https://sandbox.stackify.com/Stacks/WebApps - - - - some kind of internal metrics to track changes over time in operations with thresholds to trigger logs maybe? - - Has to be super fast, maybe an internal counter / cache in memory and a periodic job that writes it out to DB, i.e. don't write to db metrics on every get operation etc - - Average response time? - - Busyness / unique logins or tokens in use? A way to see how many distinct users are connecting over a period of time so we know how utilized it is? - - Utilization? - - Areas / routes used in AyaNova and how often / frequently they are used (we could use this for feature utilization) - - CPU peak usage snapshot +SYSOPS HEALTH CHECK / METRICS + +https://www.datadoghq.com/blog/monitoring-101-collecting-data/ + +OK, considered this and a log is a log and all logs are relevant to sysops people so I'm going to treat all logging the same regardless and make an effort to ensure each log entry +is tagged with the relevant class name + +CRITICAL ISSUES +- Check for critical issues in a health check periodic job which also logs and metrics +- Critical issues should be logged first then sent via notification for system operators if subscribed +- + +METRICS +- metrics should be gathered in DB and reported on via UI for ops users and potentially in other formats down the road + + + +TODO LIST OF THINGS CODED THAT NEED TO BE LOGGED +- Items in code tagged with this: + - //TODO: core-log-sysop +- Generator failures +- IJobBiz derived objects failures + +- configuration changes ??? +- Install and uninstall feature changes +- Warnings (low disk space, slowness monitoring, db issues) (during health check JOB??) + + +"HEALTH CHECK" JOB +- things that need to be metric a sized are commented with //OPSMETRIC +- Maybe a "health check" job or "checkup" job that periodically asseses things and reports findings +- works in conjunction with metrics gathered maybe? + - Metrics would be a system that for example could get free disk space then get it again a few days later and project ahead to getting low and warning or simple when down to 10% warn or etc +- Anything we'd like to see from a support point of view would be useful too +- Go over the research doc to see what was recommended +- Dig up that guys example project on his blog that he was going to add metrics to. +- Brainstorm a list of recent support issues and what could be a benefit in dealing with them +- "Slowness" comes up a lot. + + +Ops Metrics + CONFIRMED REQUIRED + - Gather in memory and flush to db on a schedule is best + - CASE 3562 If found, count of mismatch of attached files in database vs file system + - CASE 3523 Log major ops related configuration changes (before and after snapshot) + - CASE 3502 Log feature or route or endpoint usage count as a snapshot metric so can compare month to month. + - CASE 3502 Log record count in each table or at least major ones as a snapshot metric so can compare month to month. + - CASE 3497 ACTIVE user count - Log user login, last login and login per X period + - CASE 3499 "Slow" I want to know if anything is slow, not what the user says but what the code determines + + RESEARCH / IDEAS / EXAMPLES + - Metric types: + - https://www.app-metrics.io/getting-started/metric-types/ + - Code example that deals with this issue: + - https://github.com/AppMetrics/AppMetrics/tree/dev/src/App.Metrics.Core + - Need more than one window into the data, for example we need a last few minutes (5?) view so people can see at a glance what is happening NOW + - But also need to know what was it historically. So maybe we need a NOW algorithm but also a HISTORICAL algorithm. + - Maybe a sliding scale of recency, so a 5 minute view, a THIS WEEK view and then a month to month view beyond that?? + - LIBRARIES + - Health check Health Checks give you the ability to monitor the health of your application by writing a small tests which returns either a healthy, degraded or unhealthy result. + - https://www.app-metrics.io/health-checks/ + - APP METRICS + - https://github.com/AppMetrics/AppMetrics + - Different types of metrics are Gauges, Counters, Meters, Histograms and Timers and Application Performance Indexes + - METRICS of a system: + - Network. Network metrics are related to network bandwidth usage. + - System. System metrics are related to processor, memory, disk I/O, and network I/O. + - Platform. Platform metrics are related to ASP.NET, and the .NET common language runtime (CLR). + - Application. Application metrics include custom performance counters "Application Instrumentation". + - Service level. Service level metrics are related to your application, such as orders per second and searches per second. + - USEFUL INFO HERE FOR SYSTEM METRICS LIKE MEMORY ETC: This document from Microsoft gives generally accepted limits for things like CPU threshold, memory etc in actual percentages + - Section "System Resources" here https://msdn.microsoft.com/en-us/library/ff647791.aspx#scalenetchapt15_topic5 + + - USEFUL EXAMPLE dashboard for web applications: + - https://sandbox.stackify.com/Stacks/WebApps + + + - some kind of internal metrics to track changes over time in operations with thresholds to trigger logs maybe? + - Has to be super fast, maybe an internal counter / cache in memory and a periodic job that writes it out to DB, i.e. don't write to db metrics on every get operation etc + - Average response time? + - Busyness / unique logins or tokens in use? A way to see how many distinct users are connecting over a period of time so we know how utilized it is? + - Utilization? + - Areas / routes used in AyaNova and how often / frequently they are used (we could use this for feature utilization) + - CPU peak usage snapshot - Disk space change over time snapshots \ No newline at end of file diff --git a/devdocs/specs/core-performance.txt b/devdocs/old-devdocs/specs/core-performance.txt similarity index 97% rename from devdocs/specs/core-performance.txt rename to devdocs/old-devdocs/specs/core-performance.txt index b89afcc9..bf3bf6f2 100644 --- a/devdocs/specs/core-performance.txt +++ b/devdocs/old-devdocs/specs/core-performance.txt @@ -1,156 +1,156 @@ -PERFORMANCE SPECS AND USEFUL INFO - -//this is handy: -http://okigiveup.net/what-postgresql-tells-you-about-its-performance/ - - - -Useful queries to indicate how indexes are being used in postgresql -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - -2020-05-21 THIS SUPERSEDES BELOW -HOW TO FIND SHITTY INDEXES: https://gist.github.com/jberkus/6b1bcaf7724dfc2a54f3 - -==-=-=- -OK: this is the best query to use to find non used indexes -Run it and look for any indexes that are *not* primary keys (name ends in pkey, want ones that end in idx which are mine) -that have zero in idx_scan, that means they are completely unused (if a lot of full test runs that excercise all routes and features have happened prior to checking) - -SELECT * FROM pg_stat_user_indexes order by idx_scan asc - -Following queries might be useful but for different purposes... - -This is a test query I used with widget and name fetching performance analysis: -explain analyze SELECT m.name -FROM awidget AS m -WHERE m.id = 12989 -LIMIT 1 - -//All index data collected by postgresql - -select * from pg_stat_user_indexes - - -Reveals Unused indices -=-=-=-=-=-=-=-=-=-=-=- - -SELECT * FROM pg_stat_user_indexes order by idx_scan asc - - The basic technique is to look at pg_stat_user_indexes and look for ones where idx_scan, - the count of how many times that index has been used to answer queries, is zero, or at least very low. - - - -Detecting missing indexes -=-=-=-=-=-=-=-=-=-=-=-=-= -SELECT relname, seq_scan, seq_tup_read, - idx_scan, idx_tup_fetch, - seq_tup_read / seq_scan - FROM pg_stat_user_tables - WHERE seq_scan > 0 - ORDER BY seq_tup_read DESC; - - -Shows info on all indices -=-=-=-=-=-=-=-=-=-=-=-=-=- -SELECT - t.tablename, - indexname, - c.reltuples AS num_rows, - pg_size_pretty(pg_relation_size(quote_ident(t.tablename)::text)) AS table_size, - pg_size_pretty(pg_relation_size(quote_ident(indexrelname)::text)) AS index_size, - CASE WHEN indisunique THEN 'Y' - ELSE 'N' - END AS UNIQUE, - idx_scan AS number_of_scans, - idx_tup_read AS tuples_read, - idx_tup_fetch AS tuples_fetched -FROM pg_tables t -LEFT OUTER JOIN pg_class c ON t.tablename=c.relname -LEFT OUTER JOIN - ( SELECT c.relname AS ctablename, ipg.relname AS indexname, x.indnatts AS number_of_columns, idx_scan, idx_tup_read, idx_tup_fetch, indexrelname, indisunique FROM pg_index x - JOIN pg_class c ON c.oid = x.indrelid - JOIN pg_class ipg ON ipg.oid = x.indexrelid - JOIN pg_stat_all_indexes psai ON x.indexrelid = psai.indexrelid ) - AS foo - ON t.tablename = foo.ctablename -WHERE t.schemaname='public' -ORDER BY 7,1,2; - - -Show performance of indices that are being used -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -SELECT indexrelname,cast(idx_tup_read AS numeric) / idx_scan AS avg_tuples,idx_scan,idx_tup_read FROM pg_stat_user_indexes WHERE idx_scan > 0; - - - - -WORK IN PROGRESS: - -=-=-=-=-=-=- -Search result list NAME FETCHER in : - -//Before attempt to optimize name fetcher (unknown number of results) -//22548, 21187, 20462, 22336, 20094 - AVG = 21325 - -14244 results with index scan: 24141, 29549, 23366, 24085, 23335 AVG: 24895 = 1.7ms per result - -Removed index but kept data: -14244 results without index scan: 23391, 22623, 21428, 22607, 23106 ANOMALOUS, disregarding - -### 14244 results without index scan (after a restart of server): 24124, 21157, 21178, 21187, 21932 AVG: 21915 = 1.53 per result ##### - -14244 results without index scan (after a restart of server and using a fresh aycontext for each query): 32336, 31794...clearly much slower, abandoning this avenue -14244 results without index scan (after a restart of server and using asnotracking for each query): 24625, 21387, 21905, 22190 ... not a dramatic difference, keeping the notracking code in as it makes sense but need to look elsewhere -14244 results without index scan (after a restart of server and bypassing EF entirely with a direct query INITIAL NAIVE ATTEMPT): 13955, 13365, 13421, 13445, 13271 - - -### 14244 results without index scan (after a restart of server and bypassing EF entirely with a direct query OPTIMIZED TO REUSE CONNECTION): 12707, 12341, 12733, 12487, 12452 AVG: 12,544 = .88ms per result #### - -Now I'm going to try it with the index put back in and data regenerated -### 14244 results with index in place (after a restart of server and bypassing EF entirely with a direct query OPTIMIZED TO REUSE CONNECTION): 11229, 15480, 13763, 13051, 13178 AVG: 13,340 = .936 per result - -Now fresh test but without index being crated -### 14244 results with index in place (after a restart of server, and bypassing EF entirely with a direct query OPTIMIZED TO REUSE CONNECTION): 14270 results - 13176, 12688, 13179, 12994, 12272 AVG: 12,861 = .90 per result - -index put back in and data regenerated -### 14255 results with index in place (after a restart of server and bypassing EF entirely with a direct query OPTIMIZED TO REUSE CONNECTION): 12461, 12040, 11171, 11141, 11214 AVG: 11605 = .81 per result -OK, this tells me that it's faster with the index in place and intuitively that just makes sense. -Also verified it's actually using the index scan instead of table scan. -I'm going to enact a policy to index id,name in all objects that have many columns, if they only have a name and id and not much else then there seems little benefit - -### results ("final" id,name indexes on user table and widget table, freshly generated data), 14202 RESULTS: 13295, 14502, 11774, 12521, 12101, 13169 AVG: 12,893 = 1.15 - -Ok, it just makes logical sense to keep the indexes even if slightly slower, I can revisit this later, the difference is miniscule. I suspect with a bigger database there would definitely be better peformance. - -=-=-=-=-=-=-=-=-=-=-=-=- -LOCALE ITEM -b4 running multiple subset fetches - -256287 256301 "public" "alocaleitem" "alocaleitem_localeid_key_idx" "2350" "13667" "5172" -256287 256302 "public" "alocaleitem" "alocaleitem_localeid_key_display_idx" "2618" "2618" "2618" -256287 256294 "public" "alocaleitem" "alocaleitem_pkey" "7085" "7090" "7085" - -"alocaleitem" "24" "133010" "12053" "14875" "5542" - -after I run a bunch of fetch subset test over and over: -256287 256301 "public" "alocaleitem" "alocaleitem_localeid_key_idx" "2398" "13715" "5220" -256287 256302 "public" "alocaleitem" "alocaleitem_localeid_key_display_idx" "2618" "2618" "2618" -256287 256294 "public" "alocaleitem" "alocaleitem_pkey" "7085" "7090" "7085" - - seq_tup_read -"alocaleitem" "24" "133010" "12073" "14895" "5542" - -more - -"alocaleitem" "24" "133010" "12141" "14963" "5542" - -256287 256301 "public" "alocaleitem" "alocaleitem_localeid_key_idx" "2438" "13755" "5260" -256287 256302 "public" "alocaleitem" "alocaleitem_localeid_key_display_idx" "2618" "2618" "2618" -256287 256294 "public" "alocaleitem" "alocaleitem_pkey" "7085" "7090" "7085" - -Fresh regen, removed alocaleitem_localeid_key_idx kept alocaleitem_localeid_key_display_idx -Before any test runs fetching subsets: -256514 256521 "public" "alocaleitem" "alocaleitem_pkey" "0" "0" "0" -256514 256528 "public" "alocaleitem" "alocaleitem_localeid_key_display_idx" "1667" "1667" "1667" - +PERFORMANCE SPECS AND USEFUL INFO + +//this is handy: +http://okigiveup.net/what-postgresql-tells-you-about-its-performance/ + + + +Useful queries to indicate how indexes are being used in postgresql +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +2020-05-21 THIS SUPERSEDES BELOW +HOW TO FIND SHITTY INDEXES: https://gist.github.com/jberkus/6b1bcaf7724dfc2a54f3 + +==-=-=- +OK: this is the best query to use to find non used indexes +Run it and look for any indexes that are *not* primary keys (name ends in pkey, want ones that end in idx which are mine) +that have zero in idx_scan, that means they are completely unused (if a lot of full test runs that excercise all routes and features have happened prior to checking) + +SELECT * FROM pg_stat_user_indexes order by idx_scan asc + +Following queries might be useful but for different purposes... + +This is a test query I used with widget and name fetching performance analysis: +explain analyze SELECT m.name +FROM awidget AS m +WHERE m.id = 12989 +LIMIT 1 + +//All index data collected by postgresql + +select * from pg_stat_user_indexes + + +Reveals Unused indices +=-=-=-=-=-=-=-=-=-=-=- + +SELECT * FROM pg_stat_user_indexes order by idx_scan asc + + The basic technique is to look at pg_stat_user_indexes and look for ones where idx_scan, + the count of how many times that index has been used to answer queries, is zero, or at least very low. + + + +Detecting missing indexes +=-=-=-=-=-=-=-=-=-=-=-=-= +SELECT relname, seq_scan, seq_tup_read, + idx_scan, idx_tup_fetch, + seq_tup_read / seq_scan + FROM pg_stat_user_tables + WHERE seq_scan > 0 + ORDER BY seq_tup_read DESC; + + +Shows info on all indices +=-=-=-=-=-=-=-=-=-=-=-=-=- +SELECT + t.tablename, + indexname, + c.reltuples AS num_rows, + pg_size_pretty(pg_relation_size(quote_ident(t.tablename)::text)) AS table_size, + pg_size_pretty(pg_relation_size(quote_ident(indexrelname)::text)) AS index_size, + CASE WHEN indisunique THEN 'Y' + ELSE 'N' + END AS UNIQUE, + idx_scan AS number_of_scans, + idx_tup_read AS tuples_read, + idx_tup_fetch AS tuples_fetched +FROM pg_tables t +LEFT OUTER JOIN pg_class c ON t.tablename=c.relname +LEFT OUTER JOIN + ( SELECT c.relname AS ctablename, ipg.relname AS indexname, x.indnatts AS number_of_columns, idx_scan, idx_tup_read, idx_tup_fetch, indexrelname, indisunique FROM pg_index x + JOIN pg_class c ON c.oid = x.indrelid + JOIN pg_class ipg ON ipg.oid = x.indexrelid + JOIN pg_stat_all_indexes psai ON x.indexrelid = psai.indexrelid ) + AS foo + ON t.tablename = foo.ctablename +WHERE t.schemaname='public' +ORDER BY 7,1,2; + + +Show performance of indices that are being used +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +SELECT indexrelname,cast(idx_tup_read AS numeric) / idx_scan AS avg_tuples,idx_scan,idx_tup_read FROM pg_stat_user_indexes WHERE idx_scan > 0; + + + + +WORK IN PROGRESS: + +=-=-=-=-=-=- +Search result list NAME FETCHER in : + +//Before attempt to optimize name fetcher (unknown number of results) +//22548, 21187, 20462, 22336, 20094 - AVG = 21325 + +14244 results with index scan: 24141, 29549, 23366, 24085, 23335 AVG: 24895 = 1.7ms per result + +Removed index but kept data: +14244 results without index scan: 23391, 22623, 21428, 22607, 23106 ANOMALOUS, disregarding + +### 14244 results without index scan (after a restart of server): 24124, 21157, 21178, 21187, 21932 AVG: 21915 = 1.53 per result ##### + +14244 results without index scan (after a restart of server and using a fresh aycontext for each query): 32336, 31794...clearly much slower, abandoning this avenue +14244 results without index scan (after a restart of server and using asnotracking for each query): 24625, 21387, 21905, 22190 ... not a dramatic difference, keeping the notracking code in as it makes sense but need to look elsewhere +14244 results without index scan (after a restart of server and bypassing EF entirely with a direct query INITIAL NAIVE ATTEMPT): 13955, 13365, 13421, 13445, 13271 + + +### 14244 results without index scan (after a restart of server and bypassing EF entirely with a direct query OPTIMIZED TO REUSE CONNECTION): 12707, 12341, 12733, 12487, 12452 AVG: 12,544 = .88ms per result #### + +Now I'm going to try it with the index put back in and data regenerated +### 14244 results with index in place (after a restart of server and bypassing EF entirely with a direct query OPTIMIZED TO REUSE CONNECTION): 11229, 15480, 13763, 13051, 13178 AVG: 13,340 = .936 per result + +Now fresh test but without index being crated +### 14244 results with index in place (after a restart of server, and bypassing EF entirely with a direct query OPTIMIZED TO REUSE CONNECTION): 14270 results - 13176, 12688, 13179, 12994, 12272 AVG: 12,861 = .90 per result + +index put back in and data regenerated +### 14255 results with index in place (after a restart of server and bypassing EF entirely with a direct query OPTIMIZED TO REUSE CONNECTION): 12461, 12040, 11171, 11141, 11214 AVG: 11605 = .81 per result +OK, this tells me that it's faster with the index in place and intuitively that just makes sense. +Also verified it's actually using the index scan instead of table scan. +I'm going to enact a policy to index id,name in all objects that have many columns, if they only have a name and id and not much else then there seems little benefit + +### results ("final" id,name indexes on user table and widget table, freshly generated data), 14202 RESULTS: 13295, 14502, 11774, 12521, 12101, 13169 AVG: 12,893 = 1.15 + +Ok, it just makes logical sense to keep the indexes even if slightly slower, I can revisit this later, the difference is miniscule. I suspect with a bigger database there would definitely be better peformance. + +=-=-=-=-=-=-=-=-=-=-=-=- +LOCALE ITEM +b4 running multiple subset fetches + +256287 256301 "public" "alocaleitem" "alocaleitem_localeid_key_idx" "2350" "13667" "5172" +256287 256302 "public" "alocaleitem" "alocaleitem_localeid_key_display_idx" "2618" "2618" "2618" +256287 256294 "public" "alocaleitem" "alocaleitem_pkey" "7085" "7090" "7085" + +"alocaleitem" "24" "133010" "12053" "14875" "5542" + +after I run a bunch of fetch subset test over and over: +256287 256301 "public" "alocaleitem" "alocaleitem_localeid_key_idx" "2398" "13715" "5220" +256287 256302 "public" "alocaleitem" "alocaleitem_localeid_key_display_idx" "2618" "2618" "2618" +256287 256294 "public" "alocaleitem" "alocaleitem_pkey" "7085" "7090" "7085" + + seq_tup_read +"alocaleitem" "24" "133010" "12073" "14895" "5542" + +more + +"alocaleitem" "24" "133010" "12141" "14963" "5542" + +256287 256301 "public" "alocaleitem" "alocaleitem_localeid_key_idx" "2438" "13755" "5260" +256287 256302 "public" "alocaleitem" "alocaleitem_localeid_key_display_idx" "2618" "2618" "2618" +256287 256294 "public" "alocaleitem" "alocaleitem_pkey" "7085" "7090" "7085" + +Fresh regen, removed alocaleitem_localeid_key_idx kept alocaleitem_localeid_key_display_idx +Before any test runs fetching subsets: +256514 256521 "public" "alocaleitem" "alocaleitem_pkey" "0" "0" "0" +256514 256528 "public" "alocaleitem" "alocaleitem_localeid_key_display_idx" "1667" "1667" "1667" + diff --git a/devdocs/specs/core-picklist-autocomplete-template-system.txt b/devdocs/old-devdocs/specs/core-picklist-autocomplete-template-system.txt similarity index 97% rename from devdocs/specs/core-picklist-autocomplete-template-system.txt rename to devdocs/old-devdocs/specs/core-picklist-autocomplete-template-system.txt index 7978ac79..a02d100f 100644 --- a/devdocs/specs/core-picklist-autocomplete-template-system.txt +++ b/devdocs/old-devdocs/specs/core-picklist-autocomplete-template-system.txt @@ -1,130 +1,130 @@ -AUTOCOMPLETE PICKLIST TEMPLATE SYSTEM SPECS - - -PICKLISTS: - -AUTOCOMPLETE - TODO FROM PLANS: - CLIENT UI - - WHERE USED - - Only used for *selection* on forms - - Not used in any main grids or in reports (unless people hit the PickList route in code behind the report) - - CONTROL: - - Use tagpicker as basis, already implements most of this - - Uses route at server that is dedicated to all picklists, accepts a type and search phrase returns results - - Must be a custom control even if it's just a wrapper around a regular autocomplete for future proofing - - Accepts a AyaType and handles all the rest automatically by knowing how to query the server? - - TEMPLATE templateable selects and display format for each major object type - - similar to datalistview editor but without filtering ability - - only one template per picklist type with option to default back to default - - Sane default with enough stuff to make it likely they won't bother to change it unless they need to - - SERVER - - route that accepts type and search phrase, returns results - - Uses template to determine which fields to query and include in return results - - Returns simple name / id pairs list easily bound to control - - Caches the templates and updates on change the cache - - AyaPickList is DataList equivalent - - Only need one object to contain default templates for all datalists since there is a finite amount - - make an sub area just like datalist for picklists to contain that stuff - - PickListView is the name of the template objects - - Similar to DataListView but static, one for each type of object only - - has default view if not overriden that is generally good enough for anyone - - PickList Controller ROUTES - - GET PickList/List(AyaType, query) - - Does NOT use cached view. - - after some research caches should only be used if: - - The data is very expensive in time to generate - - small, not likely to take up much memory - - There is a *lot* of fuckery involved with caches, basically it should not be used for anything I'm doing so far - - Based on saved template view constructs a query with relevant columns only and containing search query in each column - - Also handles tags properly - - PUT PickList/Template (body AyaType, body viewJson) - - Update a view to use a new default - - updates cache when it updates db as well - - DELETE PickList/Template (AyaType) - - for ui, resets the view back to it's default - - GET PickList/Template (AyaType) - - for ui picklistvieweditor to populate ui with current template (or default if not edited) - - GET PickList/TemplateList - - for ui picklistview editor to switch lists - - - autocomplete / search involves all displayed template columns - - support Search *IN* over all joined tables in list - - - - TAGS support - - Brainwave: include tags as an optional column they can include in template, so if it's far to the right won't intrude on view but can still search for tags right in the text you type!! - - this is a simple solution to tags issue - - - - - -currently in v7: - - All picklists in v7 windows are autocomplete based on the START of the phrase typed only - - i.e. if you type in a Project box "pr" you will get "Project A", "Project B" but not a project called "ABC Project" as it doesn't search *in* the values - - This is simple and easy to intuit, maybe we don't need to get too far ahead of ourselves here. - - I do like the option of using tags in search and also a template that can be ordered like part display format for all this - -IDEAS: - - AUTOCOMPLETE / SEARCH - - SEARCH *IN* - - Search in v7 was only start of string so search IN will be very helpful to people and a step up - - For example in v7 if a item was templated like Unit display format with manufacturer first, then search will start with manufacturer - so you couldn't search for the model number first or something, you had to start exactly at the start with the manufacturer - - - DISPLAY TEMPLATE - - COMBINED WITH DATALISTVIEW or it's own thing? - - Potential differences between dlv and PickListView - - Only one default per object type, can't make many, so fixed collection of them - - No filtering combined with it - - Server has code that looks for datalist views generically to display a list of them or fetch them in a factory - - Client sends the template to the server to get the dlv, but a picklist is fixed though customizable for all users so client doesn't need to send it except when editing - - PLV need to be cached at server as they will be hit hard on nearly any form being opened - - Similarities between dlv and PickListView - - consumes a list of available fields pre-defined on a collection - - order and visible are settable by end user - - - NAMING: - - "PickListView" - - In v7 display formats are used for the following: - - All picklists of that type - - In all main grid lists where that type is a JOINED display value not the main one: - - e.g. for UserNameDisplayFormat template: UserList just shows fields like name as they are, but Project list shows the project overseer (User) with the templated setting - - PROBLEM with v7 in filtering that combined column it actually only operated on the primary column name like "name" - - e.g. setting a filter on the workroderitempart list Part column of "eye" would not bring in part named "Thompson eyephones" becuase underlying it was searching only the part number field - - NOT IN GRIDS - - I think I can do away with the v7 feature of using the display format in joined tables of the main grids - - It didn't filter properly - - All JOINED table fields can be provided separately anyway for reporting and viewing and they would actually work with filtering - - NOT IN REPORTS - - Joined tables can be provided and combined in any way user wants on report so not a MUST have as it's fulfilled anyway - - - Fixed, i.e. user can't insert their own characters in the display format but has a fixed method of separating fields - - - Was thinking the DataListview stuff would be enough for picklist templates but actually there is very little real overlap here - - Maybe a kind of similar feature but focused on picklists instead? - - Selection templates for each object by TYPE? - - One central one, not unique to each user because..chaos. - - LINKED OBJECTS / TEMPLATES - - When you think about it there are few things that need to be linked for a template to display/search - - For example in v7 to make any display template for a Unit it needs Vendor name, Model name, Model number, Unit Serial number, Description - -that's 5 items of text info from at most 3 tables, it could just always query those three tables or fixup the query on the fly to minimize table joins - - So you could give the user the options of several text fields pre-defined, they set the order in the template and it searches and displays based on that - - - - - TAGS - - How important are tags for initial release really? - - People want keyboard focused not a lot of clicking, so searching by tags is a bit of an issue: - - Maybe tags can be supported by a special typing sequence like enclose in special characters to search by tag like: - "{orange,red,yellow} Proj" - - OR, MAYBE have parallel selects beside (or above) each other, from left to right, top down or whatever, TAGS is first in row, then actual drop down of names - - if don't select a tag or clear it then only names are taken into account - - Most important first but they go as pairs in the same component - - TAG part displays very minimally at first unless it's been activated or selected (maybe an icon on the outside of the regular select which switches to tag mode?) - - -OLD RESEARCH AND NOTES - - This article is spot on and I need to implement it like this: http://jeremymikkola.com/posts/2019_03_19_rules_for_autocomplete.html +AUTOCOMPLETE PICKLIST TEMPLATE SYSTEM SPECS + + +PICKLISTS: + +AUTOCOMPLETE + TODO FROM PLANS: + CLIENT UI + - WHERE USED + - Only used for *selection* on forms + - Not used in any main grids or in reports (unless people hit the PickList route in code behind the report) + - CONTROL: + - Use tagpicker as basis, already implements most of this + - Uses route at server that is dedicated to all picklists, accepts a type and search phrase returns results + - Must be a custom control even if it's just a wrapper around a regular autocomplete for future proofing + - Accepts a AyaType and handles all the rest automatically by knowing how to query the server? + - TEMPLATE templateable selects and display format for each major object type + - similar to datalistview editor but without filtering ability + - only one template per picklist type with option to default back to default + - Sane default with enough stuff to make it likely they won't bother to change it unless they need to + - SERVER + - route that accepts type and search phrase, returns results + - Uses template to determine which fields to query and include in return results + - Returns simple name / id pairs list easily bound to control + - Caches the templates and updates on change the cache + - AyaPickList is DataList equivalent + - Only need one object to contain default templates for all datalists since there is a finite amount + - make an sub area just like datalist for picklists to contain that stuff + - PickListView is the name of the template objects + - Similar to DataListView but static, one for each type of object only + - has default view if not overriden that is generally good enough for anyone + - PickList Controller ROUTES + - GET PickList/List(AyaType, query) + - Does NOT use cached view. + - after some research caches should only be used if: + - The data is very expensive in time to generate + - small, not likely to take up much memory + - There is a *lot* of fuckery involved with caches, basically it should not be used for anything I'm doing so far + - Based on saved template view constructs a query with relevant columns only and containing search query in each column + - Also handles tags properly + - PUT PickList/Template (body AyaType, body viewJson) + - Update a view to use a new default + - updates cache when it updates db as well + - DELETE PickList/Template (AyaType) + - for ui, resets the view back to it's default + - GET PickList/Template (AyaType) + - for ui picklistvieweditor to populate ui with current template (or default if not edited) + - GET PickList/TemplateList + - for ui picklistview editor to switch lists + + - autocomplete / search involves all displayed template columns + - support Search *IN* over all joined tables in list + + + - TAGS support + - Brainwave: include tags as an optional column they can include in template, so if it's far to the right won't intrude on view but can still search for tags right in the text you type!! + - this is a simple solution to tags issue + + + + + +currently in v7: + - All picklists in v7 windows are autocomplete based on the START of the phrase typed only + - i.e. if you type in a Project box "pr" you will get "Project A", "Project B" but not a project called "ABC Project" as it doesn't search *in* the values + - This is simple and easy to intuit, maybe we don't need to get too far ahead of ourselves here. + - I do like the option of using tags in search and also a template that can be ordered like part display format for all this + +IDEAS: + - AUTOCOMPLETE / SEARCH + - SEARCH *IN* + - Search in v7 was only start of string so search IN will be very helpful to people and a step up + - For example in v7 if a item was templated like Unit display format with manufacturer first, then search will start with manufacturer + so you couldn't search for the model number first or something, you had to start exactly at the start with the manufacturer + + - DISPLAY TEMPLATE + - COMBINED WITH DATALISTVIEW or it's own thing? + - Potential differences between dlv and PickListView + - Only one default per object type, can't make many, so fixed collection of them + - No filtering combined with it + - Server has code that looks for datalist views generically to display a list of them or fetch them in a factory + - Client sends the template to the server to get the dlv, but a picklist is fixed though customizable for all users so client doesn't need to send it except when editing + - PLV need to be cached at server as they will be hit hard on nearly any form being opened + - Similarities between dlv and PickListView + - consumes a list of available fields pre-defined on a collection + - order and visible are settable by end user + + - NAMING: + - "PickListView" + - In v7 display formats are used for the following: + - All picklists of that type + - In all main grid lists where that type is a JOINED display value not the main one: + - e.g. for UserNameDisplayFormat template: UserList just shows fields like name as they are, but Project list shows the project overseer (User) with the templated setting + - PROBLEM with v7 in filtering that combined column it actually only operated on the primary column name like "name" + - e.g. setting a filter on the workroderitempart list Part column of "eye" would not bring in part named "Thompson eyephones" becuase underlying it was searching only the part number field + - NOT IN GRIDS + - I think I can do away with the v7 feature of using the display format in joined tables of the main grids + - It didn't filter properly + - All JOINED table fields can be provided separately anyway for reporting and viewing and they would actually work with filtering + - NOT IN REPORTS + - Joined tables can be provided and combined in any way user wants on report so not a MUST have as it's fulfilled anyway + + - Fixed, i.e. user can't insert their own characters in the display format but has a fixed method of separating fields + + - Was thinking the DataListview stuff would be enough for picklist templates but actually there is very little real overlap here + - Maybe a kind of similar feature but focused on picklists instead? + - Selection templates for each object by TYPE? + - One central one, not unique to each user because..chaos. + - LINKED OBJECTS / TEMPLATES + - When you think about it there are few things that need to be linked for a template to display/search + - For example in v7 to make any display template for a Unit it needs Vendor name, Model name, Model number, Unit Serial number, Description + -that's 5 items of text info from at most 3 tables, it could just always query those three tables or fixup the query on the fly to minimize table joins + - So you could give the user the options of several text fields pre-defined, they set the order in the template and it searches and displays based on that + + + + - TAGS + - How important are tags for initial release really? + - People want keyboard focused not a lot of clicking, so searching by tags is a bit of an issue: + - Maybe tags can be supported by a special typing sequence like enclose in special characters to search by tag like: + "{orange,red,yellow} Proj" + - OR, MAYBE have parallel selects beside (or above) each other, from left to right, top down or whatever, TAGS is first in row, then actual drop down of names + - if don't select a tag or clear it then only names are taken into account + - Most important first but they go as pairs in the same component + - TAG part displays very minimally at first unless it's been activated or selected (maybe an icon on the outside of the regular select which switches to tag mode?) + + +OLD RESEARCH AND NOTES + - This article is spot on and I need to implement it like this: http://jeremymikkola.com/posts/2019_03_19_rules_for_autocomplete.html - Check article responses and comments here for tweaks: https://news.ycombinator.com/item?id=19438826 \ No newline at end of file diff --git a/devdocs/specs/core-regions.txt b/devdocs/old-devdocs/specs/core-regions.txt similarity index 92% rename from devdocs/specs/core-regions.txt rename to devdocs/old-devdocs/specs/core-regions.txt index 990bc804..0e6fdb57 100644 --- a/devdocs/specs/core-regions.txt +++ b/devdocs/old-devdocs/specs/core-regions.txt @@ -1,27 +1,27 @@ -REGION SPECS - - - -CASES - -REGIONS:CLIENT:NOTIFICATION:GENERAL: - REGION feature changes case -https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/3454 - -REGIONS:GENERAL: - denormalize region id in each regionalized object -https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/3476 - -QUOTE:NOTIFICATION:CR: - Notifications for quote creation should be regionalized (or tags?) -https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/3564 - - - - -REQUIREMENTS - - -Definitive decision on regions: -Regions will be deprecated as a feature entirely, no region feature will be in RAVEN / v8. -Old data will import regions as tags, first the region will be imported as a tag then anything that is imported of that region will be tagged with that region. -Notifications will work via tags instead, users will be able to filter a notification to anything tagged with that tag. -Essentially being able to filter out a user from seeing data outside their region is not going to be a feature going forward. +REGION SPECS + + + +CASES + +REGIONS:CLIENT:NOTIFICATION:GENERAL: - REGION feature changes case +https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/3454 + +REGIONS:GENERAL: - denormalize region id in each regionalized object +https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/3476 + +QUOTE:NOTIFICATION:CR: - Notifications for quote creation should be regionalized (or tags?) +https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/3564 + + + + +REQUIREMENTS + + +Definitive decision on regions: +Regions will be deprecated as a feature entirely, no region feature will be in RAVEN / v8. +Old data will import regions as tags, first the region will be imported as a tag then anything that is imported of that region will be tagged with that region. +Notifications will work via tags instead, users will be able to filter a notification to anything tagged with that tag. +Essentially being able to filter out a user from seeing data outside their region is not going to be a feature going forward. Roles will be the primary way to restrict what users see and various filters by tag for certain ops like notification etc. \ No newline at end of file diff --git a/devdocs/specs/core-reporting.txt b/devdocs/old-devdocs/specs/core-reporting.txt similarity index 98% rename from devdocs/specs/core-reporting.txt rename to devdocs/old-devdocs/specs/core-reporting.txt index dfa38f6e..e5d4ba2f 100644 --- a/devdocs/specs/core-reporting.txt +++ b/devdocs/old-devdocs/specs/core-reporting.txt @@ -1,379 +1,379 @@ -REPORTING SPECS - -2021-06-24 V7 Stock report list: - -ClientList Sample Client Banked Service Balance -ClientListDetailed Sample AVERY 5260 Client Postal Mailing Labels -ClientServiceRequestList Sample Customer Service Requests Report -ContactTitle.Label.List Contact titles list -ContractList Sample Summary Report of Contracts -HeadOfficeList Sample Head Office Contract Expiry -HeadOfficeListDetailed Sample AVERY 5261 Head Office Mailing Labels -LoanItemList Sample Loan Items & Present Status -MemoList Sample Memo list -NotifyDeliveryLogList Sample Notifications Deliveries Report -NotifySubscriptionList Sample Notification Subscription List -PartInventoryAdjustmentDetailed Sample Part Inventory Adjustments Detailed Report -PartInventoryAdjustmentList Sample Part Adjustments Summary List -PartList Sample Parts By Category Report -PartWarehouseInventoryList Sample Inventory Reconciliation Form Report -PartWarehouseInventoryList Sample ReOrder List -PartWarehouseInventoryList Sample Retail and Cost Inventory Values -PurchaseOrderDetailed Sample Purchase Order Detailed Report -PurchaseOrderList Sample Purchase Orders Summary Report -PurchaseOrderReceiptDetailed Sample Purchase Order Receipts Detailed Report -PurchaseOrderReceiptList Sample Purchase Order Receipts Summary Report -PurchaseOrderReceiptListDetailed Received Items Labels AVERY 12295 -Rates Sample Rates List Report -ReportList Report Templates List Report -SearchResultList Sample Search Result List -ServiceBank Banked Service Showing Currency Balance Based on Grid Sorted Effective Date Using Script -ServiceBank Banked Service Showing Hours Balance Based on Grid Sorted Effective Date Using Script -ServiceBank Banked Service Using Grids Currency Balance -ServiceBank Banked Service Using Grids Hour Balance -TaxCodes Sample Tax Codes List report -UnitList Sample Total Number of Units Per Client -UnitList Sample Unit List -UnitList Sample Units Avery 5260 labels report -UnitMeterReadingList Sample Meter Reading List Displaying Difference Between -UnitModelList Sample Unit Model List report -UserList Sample User report List report -VendorList Vendor Contact List -WorkOrderItemPartRequestList Parts Requests From Service Workorders Report -WorkorderPMDetailed PM Showing Client and Unit Report -WorkorderPMList Next Service Date Of PM's Report -WorkorderPMPartList Parts Needed For Upcoming PMs Report -WorkorderQuoteDetailed Sample Detailed Quote -WorkorderQuoteDetailed Sample Detailed Quote with Costs and with No Discount compared against Discount Price -WorkorderQuoteDetailed Sample Detailed Quote with Tasks -WorkorderQuoteDetailed Sample Detailed Quote without Scheduled Users Showing Report -WorkorderQuoteLaborList Sample Quotes Labor By Scheduleable User Report -WorkorderQuoteLaborList Sample Quotes Labor Summary Report -WorkorderQuoteList Quotes Summary Report -WorkorderQuotePartList Sample Quote Parts Summary Report -WorkorderServiceCustomList Sample Custom Fields Report -WorkorderServiceDetailed Sample Banked Detailed Service Workorder with Grand Total Repeats Report -WorkorderServiceDetailed Sample Billable Grouped By Client with Details and Total Report -WorkorderServiceDetailed Sample Call Back Report -WorkorderServiceDetailed Sample Client Claim Receipt -WorkorderServiceDetailed Sample Detailed Service Workorder with Grand Total Head Office Billed Report -WorkorderServiceDetailed Sample Detailed Service Workorder with Grand Total Report -WorkorderServiceDetailed Sample Detailed Service Workorder with Grand Total and Signature -WorkorderServiceDetailed Sample Dispatching Report -WorkorderServiceDetailed Sample Dispatching Report - each wo item starts on a new page -WorkorderServiceDetailed Sample Grand Total of All Listed Workorders Billable Items -WorkorderServiceDetailed Sample Labor Hours in Service Workorders Report -WorkorderServiceDetailed Sample Labor from Request Date Average Response Time -WorkorderServiceDetailed Sample Service Workorder with No Charge Amounts -WorkorderServiceDetailed Sample Total Billable Grouped By Client Report -WorkorderServiceDetailed Sample Total Billable Grouped By Project Includes No Charge Hours Report -WorkorderServiceDetailed Sample Unit History Billable Detailed Report -WorkorderServiceDetailed Sample Unit History Report -WorkorderServiceExpenseList Misc Expenses In Workorders Report -WorkorderServiceItemList Sample Outside Service Summary Report -WorkorderServiceItemList Sample Unit History Report Summary -WorkorderServiceItemList Sample Workorder Item Status -WorkorderServiceLaborList Sample Actual Total Hours Based on Entered Start and Stop Times Report with Grand Total -WorkorderServiceLaborList Sample Client Billing Hours Report with Grand Total -WorkorderServiceLaborList Sample Labor Hours By Client Report -WorkorderServiceLaborList Sample Scheduleable User Billing Hours Report with Grand Total Report -WorkorderServiceLaborList Sample User Billing Hours Report with Grand Total and Commission Report -WorkorderServiceList Sample Service Workorders Invoiced -WorkorderServiceLoanList Sample Loans Summary Report -WorkorderServicePartList Part Profit Loss -WorkorderServicePartList Parts Requested Via Quotes Report -WorkorderServicePartList Parts by Project Report -WorkorderServicePartList Sample Parts In Service Workorders Report -WorkorderServiceScheduledUserList Sample Scheduled Users Summary Report -WorkorderServiceTravelList Sample Scheduleable User Travel Summary Report -WorkorderServiceTravelList Sample Scheduleable User Travel Summary with Grand Total Report - - -################################################################################################################################################################ - - - - - - -################################## -2020-09-25 OUTSTANDING REPORTING STUFF -This is stuff that may or may not be relevant in future, keeping here from my notes -REPORTING STUFF THAT IS FUTURE OR ON HOLD -MOVE THIS TO A v.next case or into reporting SPEC doc for future reference if not a coding issue now - - -todo: bizrule for report scale value at server - and maybe other shit as well - -todo: Need a setting that warns people about printing too much data, i.e. "That's a lot of data, are you sure you want to render that, it will be slow" or something to that effect - - -todo: REPORT BACKEND - report delete throws server exception about db context re-use or something to that effect - No exact steps top repro, but happens for Joyce with win64 release build if go in and edit same template a few times from widget list then attempt to delete it - try to repro on debug build figure it out, could be a big issue if it's not specifically a report issue but wider biz object issue - COULD NOT REPRO HERE - -todo: (On hold pending testing) pdf options UI and passthrough - OUTSTANDING - Docs - DOCS reference pages - https://stackoverflow.com/questions/49943479/puppeteer-header-and-footertemplate-doesnt-work#49996999 - https://pptr.dev/#?product=Puppeteer&version=v5.3.0&show=api-pagepdfoptions - todo: document about the troubleshooting section items here if applicable: - https://jsreport.net/learn/chrome-pdf - which may or may not apply in our case - Testing - - DONE - basically need to be able to select every option and send it through - options: - http://www.puppeteersharp.com/api/PuppeteerSharp.PdfOptions.html - http://www.puppeteersharp.com/api/PuppeteerSharp.Page.html#PuppeteerSharp_Page_PdfAsync_System_String_PuppeteerSharp_PdfOptions_ - https://pptr.dev/#?product=Puppeteer&version=v5.3.0&show=api-pagepdfoptions - page numbers control - Test this, it might do what we need as it has a template for pdf footer and page number is part of it - http://www.puppeteersharp.com/api/PuppeteerSharp.PdfOptions.html - look at jsreport what do they include in their pdf post processing parameters and capabilities - need to add pdfkit or whatever it's called at the front. - -todo: I have console logging capture code now in backend, but it's doing nothing really, just logs if exception thrown - it might be handy if it returned the log value and any other diagnostic info with render return data when user is in designer - i.e. have a further property Diagnostic bool and if set then returns diagnostic data - and return property with pdf name would be in an object with additional properties for diagnosis etc - But only if it proves helpful or necessary - mainly this would allow a console log or error or trace to flow back to the user from the script being run at the server - -//before getting into timeouts and shit make sure it's running as well as can be in docker -todo: look at guidance for running puppeteer (js) on alpine docker here: https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md#running-on-alpine - how jsreport is launching headless chrome, i.e. which settings and flags etc - https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#puppeteerlaunchoptions - https://jsreport.net/learn/chrome-pdf - https://github.com/jsreport/jsreport-chrome-pdf/blob/master/lib/conversion.js - (after looking at it, it's still a bit unclear, maybe not relevant as they seem to do a lot differently for that) - - -todo: look over this: https://github.com/puppeteer/puppeteer/issues/1834 - -todo: REPORT BACKEND - more timeouts for report rendering, hard kill after 30 seconds tops but adjustable interval maybe? - each process takes time in part, need to see which is taking which time the most and killable - i.e. run a huge report and see which exact step takes which time for each - we have the pre-render timing out maybe need more for each step where it's vulnerable to crashing / timing out - - Devops droplet is overwhelmed by 10k records of widgets using the customfields example report - symptom is super high cpu usage (100%) pegged and probably virtual memory usage as well - timeout is kind of a hard core way to work around this issue, maybe instead it should be looking at excessive cpu and memory usage? - The metrics don't catch it because it happens too quickly for the metrics lifecycle - - I want it to be able to handle it gracefully without crashing - Looks like jsreports has this issue too and they hard kill the process I think if necessary, but they actually re-use the same instance for reporting I think. - If it's not an issue then no need to resolve at the moment - - UPDATE: No way to timeout the pdf generation built into puppeteer sharp so far, maybe some workarounds - I think the nuclear option would be to start timer once we know the process id of the chormium instance and that time automatically kills that process ID if still found around XX seconds later - (or in the form of a clean up job maybe like the temp file deleter job) - -todo: reporting load test - test locally with 20k widgets, make it crash then determine what limits to set on it and properly return error when it's exceeded - right now it just says something about puppeteer and "crash" - NOT ABLE TO REPRO HERE - - - -todo: MEMORY / PERFORMANCE / CRASHING - BOTTOM LINE: - It *sometimes* can't render at 5k records lots of pages on devops but mainly it does around 2.5 to 3 minutes avg, same on dev ws takes 1.5 m avg but no crash - uses a lot of ram, also cpu does get pegged by chrome process at 95% so it's a bit of both I guess - If users have issue with server during reporting they should check ram and cpu - a minimal droplet appears fine for normal workload, it's the big report rendering that's the most inefficient - - look at proper settings for rendering in docker on linux and try to make it resilient to crashing even if set too low or too little resources - IDEAS: - check guidelines for running in docker from link below - check command line params for best fit - see about re-using same or whatever - check cpu, memory usage upon render request, reject immediately if the system is overburdened - check for running chromium processes or some way to determine if in the middle of the last render for someone - - Try a method to zap all chromium processes as a test to see if they *can* be killed whil stuck this way - To test use the "custom date time format helpers" with 5k records, that reliably freezes everything even when others all seem to run ok - (this in itself is curious but whatever) - - What I'm seeing is on a long render it returns a 504 gateway timeout to the client but it's still churning away in the background - 5k records and "custom date time format helpers" report will take about 3 minutes to render, maybe less and it will crash out for the client return 504 but then it will complete at some point - Confirmed it *does* complete because I was able to download the 4.12mb 2144 page pdf manually from the server temp folder via filezilla once I saw the cpu go down again - and chrome process stop - 90% memory is the max used in do graph panel, probably docker is not letting it take all or something isn't - maybe swapping out is what's happening, peak memory usage seems to be half a gig or so but c - 97% cpu usage is max - - I'm thinking it's a memory issue more than a cpu issue because the cpu is hardly pegged at all while it's rendering right up until it appears to run out of memory - then it starts swapping and all hell breaks loose and the cpu pegs on the swap daemon - Need to test by moving up to 2gb of memory witha resize but keep the single vcpu and see what's what - also increase the timeout in nginx for the reverse proxy to wait - A temporary rendering caused memory shortage should not cause the system to come to a standstill - - -todo: memory usage and timeout is directly related to the amount of space taken up physically on the page - it's NOT related to the helpers as just putting static text on the page causes the same issue - it's memory taken to render to pdf probably and a byte is a byte even if it's blank white page - =-=-=-=-=- - - - - - - - -########## ORIGINAL SPECS ################### -CASES -1734 - REPORTS:GRIDS: - grid filter name and summary of filter criteria available as fields to print on report - - -REQUIREMENTS - -- All v7 reports ported to RAVEN - - ALL Fields even the ones that don't show on the report but are available for adding to a report in the editor need to be available - - - REPORTS - - Report object has following properties: - - DataList name it's based off of - - Required fields from DataList - - Report template itself with it's own code and template requirements TBD - - Report columns returned: When user selects to show a report, client will fixup any missing columns from the datalistview currently in use - - For example they are viewing a table based on a TestWidgetDataList DataListview with only 3 columns in it - - They drop down the reports list which shows all reports based off TestWidgetDataList view - - They select a report to print. - - Report code looks at report's required fields from DatalistView and sees report uses 6 fields listed - - Code compares report fields to in use DataListview fields and appends any report required fields missing from current view to the right of the collection in the current DataListview - - When report is run it will have all fields this way returned but will still be sorted and filtered by table view - - As part of editing process user can select an existing datalistview to prime their report editing view - - A report can be selected from any client table that is based on the same view - - -//======================= - - -USEFUL REPORTING RELATED LINKS - - https://github.com/jsreport/jsreport-core - https://github.com/jsreport/jsreport-core/blob/master/lib/render/engineScript.js - - //actual render here - https://github.com/jsreport/jsreport-chrome-pdf/blob/d3fe318aac3628d8cb62f86f8f71314f21745798/lib/conversion.js - - //PDF utils - https://github.com/jsreport/jsreport-pdf-utils - - They use a Mozilla library called pdfjs and their utils are basically just wrappers around using it - https://github.com/mozilla/pdf.js - - hub to docs here: - https://mozilla.github.io/pdf.js/ - - This is the jsreport designer libs used for reference: https://github.com/jsreport/jsreport-studio/blob/master/package.json -https://jsreport.net/learn/api - -Report templates pre-designed and open source: https://github.com/wildbit/postmark-templates - -HTML -> PDF - JSREPORT has a comparison table of various html to pdf tools here: - https://jsreport.net/learn/pdf-recipes - - - Headless Chrome - https://github.com/jsreport/jsreport-chrome-pdf - FAST SPEED (according to jsreport docs) - jsreport uses headless chrome by default which has built in pdf from html ability. - they use a NODE library Puppeteer for it, but there is a c# wrapper for .net core linux windows mac: https://github.com/hardkoded/puppeteer-sharp - some kind of example that may be relevant: https://github.com/kblok/netconfar-puppeteer-sharp-demo/blob/master/hacking-the-browser-api/Controllers/MediumController.cs#L13 - Maybe not the only one for c# core, need to dig around - Issues: - Issue with header / footer not being settable apparently which is a big breaking issue for many biz reports usage - someone said that another pdf tool can be used to set those post processing but fuckery abounds - other solutions below apparently don't have this issue. - Even jsreport has listed workarounds and tools to resolve this - Update: apparently there are ways: - https://stackoverflow.com/questions/44575628/alter-the-default-header-footer-when-printing-to-pdf?noredirect=1&lq=1 - see last comment seems relevant, also other linked cases all mention various things. Finally, could use a pdf writer tool to post process maybe. - - There seem to be many potential issues with missing libraries, rights and sandbox and etc etc etc on linux - These things kind of turned me off this a bit, it's not plug and play and simple - - - LINKS: - https://github.com/hardkoded/puppeteer-sharp - https://github.com/puppeteer/puppeteer - https://stackoverflow.com/search?q=puppeteer-sharp - https://stackoverflow.com/questions/62042078/puppeteer-sharp-for-server-side-html-to-pdf-conversions - https://www.singlestoneconsulting.com/blog/how-to-generate-server-side-pdf-reports-puppeteer-d3-handlebars/ - https://github.com/hardkoded/puppeteer-sharp/issues/1510 - shows being used by someone other than jsreport which buries all the details in endless libs - https://github.com/hardkoded/puppeteer-sharp/issues/1514 - - WeasyPrint - https://github.com/jsreport/jsreport-weasyprint-pdf - SLOWEST SPEED - https://github.com/Kozea/WeasyPrint based on python, does it's own rendering doesn't rely on a web browser engine like the rest - free, recommended by wkhtmltopdf author as an alternative - May be slow, slower than the other options likely, has some Installation procedure that are a bit convoluted but ironically only for windows as it's included in package managers - Very good support for modern css3 PAGE properties apparently - WRAPPER - https://github.com/balbarak/WeasyPrint-netcore/blob/master/src/Balbarak.WeasyPrint/WeasyPrintClient.cs - - - wkhtmltopdf - https://github.com/jsreport/jsreport-wkhtmltopdf - MEDIUM SPEED - https://wkhtmltopdf.org/downloads.html - Well used, old based on older webkit so doesn't support css3 but likely enough for our purposes - has an easy installer for all platforms - free - Has warnings about how unsanitized html can take down a server or own it somehow - WRAPPERS - https://github.com/carloscds/HtmlToPDFCore/tree/master/HtmlToPDFCore This one looks cool, all platforms supported includes binary possibly? - https://blog.elmah.io/generate-a-pdf-from-asp-net-core-for-free/ - - -HTML -> DOCX - This is a possiblity that needs to be researched, instead of pdf go docx which is in theory multi platform and openable on other devices? Not sure - https://github.com/jsreport/jsreport-docx - https://github.com/EricWhiteDev/Open-Xml-PowerTools - -HTML -> XLSX - https://github.com/jsreport/jsreport-xlsx - -HTML -> TEXT - https://github.com/jsreport/jsreport-html-to-text - https://github.com/jsreport/jsreport-text - - -TEMPLATE ENGINE - https://github.com/jsreport/jsreport-handlebars - Handlebars by default for jsreport which is easy peasy to work with - -PDF META DATA EDITING - https://github.com/jsreport/jsreport-pdf-meta - -Render outputs - JSReport renders to different outputs, they call it recipes https://jsreport.net/learn/recipes - HTML - just outputs as html for viewing in the browser / printing from browser - PDF: https://jsreport.net/learn/pdf-recipes - Outputs 5 different pdf converters because they all support different feature sets which is ominous - - - -BAR CODE STUFF - Bar codes: https://github.com/metafloor/bwip-js - https://stackoverflow.com/questions/19017512/use-canvas-inside-a-handlebars-template - https://github.com/metafloor/bwip-js#browser-usage - https://www.scandit.com/blog/types-barcodes-choosing-right-barcode/ - https://github.com/metafloor/bwip-js/wiki/BWIPP-Barcode-Types - - let opt = { - bcid: "code128", // Barcode type - text: "0123456789", // Text to encode - scale: 3, // 3x scaling factor - height: 10, // Bar height, in millimeters - includetext: true, // Show human-readable text - textxalign: "center" // Always good to set this - }; +REPORTING SPECS + +2021-06-24 V7 Stock report list: + +ClientList Sample Client Banked Service Balance +ClientListDetailed Sample AVERY 5260 Client Postal Mailing Labels +ClientServiceRequestList Sample Customer Service Requests Report +ContactTitle.Label.List Contact titles list +ContractList Sample Summary Report of Contracts +HeadOfficeList Sample Head Office Contract Expiry +HeadOfficeListDetailed Sample AVERY 5261 Head Office Mailing Labels +LoanItemList Sample Loan Items & Present Status +MemoList Sample Memo list +NotifyDeliveryLogList Sample Notifications Deliveries Report +NotifySubscriptionList Sample Notification Subscription List +PartInventoryAdjustmentDetailed Sample Part Inventory Adjustments Detailed Report +PartInventoryAdjustmentList Sample Part Adjustments Summary List +PartList Sample Parts By Category Report +PartWarehouseInventoryList Sample Inventory Reconciliation Form Report +PartWarehouseInventoryList Sample ReOrder List +PartWarehouseInventoryList Sample Retail and Cost Inventory Values +PurchaseOrderDetailed Sample Purchase Order Detailed Report +PurchaseOrderList Sample Purchase Orders Summary Report +PurchaseOrderReceiptDetailed Sample Purchase Order Receipts Detailed Report +PurchaseOrderReceiptList Sample Purchase Order Receipts Summary Report +PurchaseOrderReceiptListDetailed Received Items Labels AVERY 12295 +Rates Sample Rates List Report +ReportList Report Templates List Report +SearchResultList Sample Search Result List +ServiceBank Banked Service Showing Currency Balance Based on Grid Sorted Effective Date Using Script +ServiceBank Banked Service Showing Hours Balance Based on Grid Sorted Effective Date Using Script +ServiceBank Banked Service Using Grids Currency Balance +ServiceBank Banked Service Using Grids Hour Balance +TaxCodes Sample Tax Codes List report +UnitList Sample Total Number of Units Per Client +UnitList Sample Unit List +UnitList Sample Units Avery 5260 labels report +UnitMeterReadingList Sample Meter Reading List Displaying Difference Between +UnitModelList Sample Unit Model List report +UserList Sample User report List report +VendorList Vendor Contact List +WorkOrderItemPartRequestList Parts Requests From Service Workorders Report +WorkorderPMDetailed PM Showing Client and Unit Report +WorkorderPMList Next Service Date Of PM's Report +WorkorderPMPartList Parts Needed For Upcoming PMs Report +WorkorderQuoteDetailed Sample Detailed Quote +WorkorderQuoteDetailed Sample Detailed Quote with Costs and with No Discount compared against Discount Price +WorkorderQuoteDetailed Sample Detailed Quote with Tasks +WorkorderQuoteDetailed Sample Detailed Quote without Scheduled Users Showing Report +WorkorderQuoteLaborList Sample Quotes Labor By Scheduleable User Report +WorkorderQuoteLaborList Sample Quotes Labor Summary Report +WorkorderQuoteList Quotes Summary Report +WorkorderQuotePartList Sample Quote Parts Summary Report +WorkorderServiceCustomList Sample Custom Fields Report +WorkorderServiceDetailed Sample Banked Detailed Service Workorder with Grand Total Repeats Report +WorkorderServiceDetailed Sample Billable Grouped By Client with Details and Total Report +WorkorderServiceDetailed Sample Call Back Report +WorkorderServiceDetailed Sample Client Claim Receipt +WorkorderServiceDetailed Sample Detailed Service Workorder with Grand Total Head Office Billed Report +WorkorderServiceDetailed Sample Detailed Service Workorder with Grand Total Report +WorkorderServiceDetailed Sample Detailed Service Workorder with Grand Total and Signature +WorkorderServiceDetailed Sample Dispatching Report +WorkorderServiceDetailed Sample Dispatching Report - each wo item starts on a new page +WorkorderServiceDetailed Sample Grand Total of All Listed Workorders Billable Items +WorkorderServiceDetailed Sample Labor Hours in Service Workorders Report +WorkorderServiceDetailed Sample Labor from Request Date Average Response Time +WorkorderServiceDetailed Sample Service Workorder with No Charge Amounts +WorkorderServiceDetailed Sample Total Billable Grouped By Client Report +WorkorderServiceDetailed Sample Total Billable Grouped By Project Includes No Charge Hours Report +WorkorderServiceDetailed Sample Unit History Billable Detailed Report +WorkorderServiceDetailed Sample Unit History Report +WorkorderServiceExpenseList Misc Expenses In Workorders Report +WorkorderServiceItemList Sample Outside Service Summary Report +WorkorderServiceItemList Sample Unit History Report Summary +WorkorderServiceItemList Sample Workorder Item Status +WorkorderServiceLaborList Sample Actual Total Hours Based on Entered Start and Stop Times Report with Grand Total +WorkorderServiceLaborList Sample Client Billing Hours Report with Grand Total +WorkorderServiceLaborList Sample Labor Hours By Client Report +WorkorderServiceLaborList Sample Scheduleable User Billing Hours Report with Grand Total Report +WorkorderServiceLaborList Sample User Billing Hours Report with Grand Total and Commission Report +WorkorderServiceList Sample Service Workorders Invoiced +WorkorderServiceLoanList Sample Loans Summary Report +WorkorderServicePartList Part Profit Loss +WorkorderServicePartList Parts Requested Via Quotes Report +WorkorderServicePartList Parts by Project Report +WorkorderServicePartList Sample Parts In Service Workorders Report +WorkorderServiceScheduledUserList Sample Scheduled Users Summary Report +WorkorderServiceTravelList Sample Scheduleable User Travel Summary Report +WorkorderServiceTravelList Sample Scheduleable User Travel Summary with Grand Total Report + + +################################################################################################################################################################ + + + + + + +################################## +2020-09-25 OUTSTANDING REPORTING STUFF +This is stuff that may or may not be relevant in future, keeping here from my notes +REPORTING STUFF THAT IS FUTURE OR ON HOLD +MOVE THIS TO A v.next case or into reporting SPEC doc for future reference if not a coding issue now + + +todo: bizrule for report scale value at server + and maybe other shit as well + +todo: Need a setting that warns people about printing too much data, i.e. "That's a lot of data, are you sure you want to render that, it will be slow" or something to that effect + + +todo: REPORT BACKEND - report delete throws server exception about db context re-use or something to that effect + No exact steps top repro, but happens for Joyce with win64 release build if go in and edit same template a few times from widget list then attempt to delete it + try to repro on debug build figure it out, could be a big issue if it's not specifically a report issue but wider biz object issue + COULD NOT REPRO HERE + +todo: (On hold pending testing) pdf options UI and passthrough + OUTSTANDING + Docs + DOCS reference pages + https://stackoverflow.com/questions/49943479/puppeteer-header-and-footertemplate-doesnt-work#49996999 + https://pptr.dev/#?product=Puppeteer&version=v5.3.0&show=api-pagepdfoptions + todo: document about the troubleshooting section items here if applicable: + https://jsreport.net/learn/chrome-pdf + which may or may not apply in our case + Testing + + DONE + basically need to be able to select every option and send it through + options: + http://www.puppeteersharp.com/api/PuppeteerSharp.PdfOptions.html + http://www.puppeteersharp.com/api/PuppeteerSharp.Page.html#PuppeteerSharp_Page_PdfAsync_System_String_PuppeteerSharp_PdfOptions_ + https://pptr.dev/#?product=Puppeteer&version=v5.3.0&show=api-pagepdfoptions + page numbers control + Test this, it might do what we need as it has a template for pdf footer and page number is part of it + http://www.puppeteersharp.com/api/PuppeteerSharp.PdfOptions.html + look at jsreport what do they include in their pdf post processing parameters and capabilities + need to add pdfkit or whatever it's called at the front. + +todo: I have console logging capture code now in backend, but it's doing nothing really, just logs if exception thrown + it might be handy if it returned the log value and any other diagnostic info with render return data when user is in designer + i.e. have a further property Diagnostic bool and if set then returns diagnostic data + and return property with pdf name would be in an object with additional properties for diagnosis etc + But only if it proves helpful or necessary + mainly this would allow a console log or error or trace to flow back to the user from the script being run at the server + +//before getting into timeouts and shit make sure it's running as well as can be in docker +todo: look at guidance for running puppeteer (js) on alpine docker here: https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md#running-on-alpine + how jsreport is launching headless chrome, i.e. which settings and flags etc + https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#puppeteerlaunchoptions + https://jsreport.net/learn/chrome-pdf + https://github.com/jsreport/jsreport-chrome-pdf/blob/master/lib/conversion.js + (after looking at it, it's still a bit unclear, maybe not relevant as they seem to do a lot differently for that) + + +todo: look over this: https://github.com/puppeteer/puppeteer/issues/1834 + +todo: REPORT BACKEND - more timeouts for report rendering, hard kill after 30 seconds tops but adjustable interval maybe? + each process takes time in part, need to see which is taking which time the most and killable + i.e. run a huge report and see which exact step takes which time for each + we have the pre-render timing out maybe need more for each step where it's vulnerable to crashing / timing out + + Devops droplet is overwhelmed by 10k records of widgets using the customfields example report + symptom is super high cpu usage (100%) pegged and probably virtual memory usage as well + timeout is kind of a hard core way to work around this issue, maybe instead it should be looking at excessive cpu and memory usage? + The metrics don't catch it because it happens too quickly for the metrics lifecycle + + I want it to be able to handle it gracefully without crashing + Looks like jsreports has this issue too and they hard kill the process I think if necessary, but they actually re-use the same instance for reporting I think. + If it's not an issue then no need to resolve at the moment + + UPDATE: No way to timeout the pdf generation built into puppeteer sharp so far, maybe some workarounds + I think the nuclear option would be to start timer once we know the process id of the chormium instance and that time automatically kills that process ID if still found around XX seconds later + (or in the form of a clean up job maybe like the temp file deleter job) + +todo: reporting load test + test locally with 20k widgets, make it crash then determine what limits to set on it and properly return error when it's exceeded + right now it just says something about puppeteer and "crash" + NOT ABLE TO REPRO HERE + + + +todo: MEMORY / PERFORMANCE / CRASHING + BOTTOM LINE: + It *sometimes* can't render at 5k records lots of pages on devops but mainly it does around 2.5 to 3 minutes avg, same on dev ws takes 1.5 m avg but no crash + uses a lot of ram, also cpu does get pegged by chrome process at 95% so it's a bit of both I guess + If users have issue with server during reporting they should check ram and cpu + a minimal droplet appears fine for normal workload, it's the big report rendering that's the most inefficient + + look at proper settings for rendering in docker on linux and try to make it resilient to crashing even if set too low or too little resources + IDEAS: + check guidelines for running in docker from link below + check command line params for best fit + see about re-using same or whatever + check cpu, memory usage upon render request, reject immediately if the system is overburdened + check for running chromium processes or some way to determine if in the middle of the last render for someone + + Try a method to zap all chromium processes as a test to see if they *can* be killed whil stuck this way + To test use the "custom date time format helpers" with 5k records, that reliably freezes everything even when others all seem to run ok + (this in itself is curious but whatever) + + What I'm seeing is on a long render it returns a 504 gateway timeout to the client but it's still churning away in the background + 5k records and "custom date time format helpers" report will take about 3 minutes to render, maybe less and it will crash out for the client return 504 but then it will complete at some point + Confirmed it *does* complete because I was able to download the 4.12mb 2144 page pdf manually from the server temp folder via filezilla once I saw the cpu go down again + and chrome process stop + 90% memory is the max used in do graph panel, probably docker is not letting it take all or something isn't + maybe swapping out is what's happening, peak memory usage seems to be half a gig or so but c + 97% cpu usage is max + + I'm thinking it's a memory issue more than a cpu issue because the cpu is hardly pegged at all while it's rendering right up until it appears to run out of memory + then it starts swapping and all hell breaks loose and the cpu pegs on the swap daemon + Need to test by moving up to 2gb of memory witha resize but keep the single vcpu and see what's what + also increase the timeout in nginx for the reverse proxy to wait + A temporary rendering caused memory shortage should not cause the system to come to a standstill + + +todo: memory usage and timeout is directly related to the amount of space taken up physically on the page + it's NOT related to the helpers as just putting static text on the page causes the same issue + it's memory taken to render to pdf probably and a byte is a byte even if it's blank white page + =-=-=-=-=- + + + + + + + +########## ORIGINAL SPECS ################### +CASES +1734 - REPORTS:GRIDS: - grid filter name and summary of filter criteria available as fields to print on report + + +REQUIREMENTS + +- All v7 reports ported to RAVEN + - ALL Fields even the ones that don't show on the report but are available for adding to a report in the editor need to be available + + - REPORTS + - Report object has following properties: + - DataList name it's based off of + - Required fields from DataList + - Report template itself with it's own code and template requirements TBD + - Report columns returned: When user selects to show a report, client will fixup any missing columns from the datalistview currently in use + - For example they are viewing a table based on a TestWidgetDataList DataListview with only 3 columns in it + - They drop down the reports list which shows all reports based off TestWidgetDataList view + - They select a report to print. + - Report code looks at report's required fields from DatalistView and sees report uses 6 fields listed + - Code compares report fields to in use DataListview fields and appends any report required fields missing from current view to the right of the collection in the current DataListview + - When report is run it will have all fields this way returned but will still be sorted and filtered by table view + - As part of editing process user can select an existing datalistview to prime their report editing view + - A report can be selected from any client table that is based on the same view + + +//======================= + + +USEFUL REPORTING RELATED LINKS + + https://github.com/jsreport/jsreport-core + https://github.com/jsreport/jsreport-core/blob/master/lib/render/engineScript.js + + //actual render here + https://github.com/jsreport/jsreport-chrome-pdf/blob/d3fe318aac3628d8cb62f86f8f71314f21745798/lib/conversion.js + + //PDF utils + https://github.com/jsreport/jsreport-pdf-utils + + They use a Mozilla library called pdfjs and their utils are basically just wrappers around using it + https://github.com/mozilla/pdf.js + + hub to docs here: + https://mozilla.github.io/pdf.js/ + + This is the jsreport designer libs used for reference: https://github.com/jsreport/jsreport-studio/blob/master/package.json +https://jsreport.net/learn/api + +Report templates pre-designed and open source: https://github.com/wildbit/postmark-templates + +HTML -> PDF + JSREPORT has a comparison table of various html to pdf tools here: + https://jsreport.net/learn/pdf-recipes + + + Headless Chrome + https://github.com/jsreport/jsreport-chrome-pdf + FAST SPEED (according to jsreport docs) + jsreport uses headless chrome by default which has built in pdf from html ability. + they use a NODE library Puppeteer for it, but there is a c# wrapper for .net core linux windows mac: https://github.com/hardkoded/puppeteer-sharp + some kind of example that may be relevant: https://github.com/kblok/netconfar-puppeteer-sharp-demo/blob/master/hacking-the-browser-api/Controllers/MediumController.cs#L13 + Maybe not the only one for c# core, need to dig around + Issues: + Issue with header / footer not being settable apparently which is a big breaking issue for many biz reports usage + someone said that another pdf tool can be used to set those post processing but fuckery abounds + other solutions below apparently don't have this issue. + Even jsreport has listed workarounds and tools to resolve this + Update: apparently there are ways: + https://stackoverflow.com/questions/44575628/alter-the-default-header-footer-when-printing-to-pdf?noredirect=1&lq=1 + see last comment seems relevant, also other linked cases all mention various things. Finally, could use a pdf writer tool to post process maybe. + + There seem to be many potential issues with missing libraries, rights and sandbox and etc etc etc on linux + These things kind of turned me off this a bit, it's not plug and play and simple + + + LINKS: + https://github.com/hardkoded/puppeteer-sharp + https://github.com/puppeteer/puppeteer + https://stackoverflow.com/search?q=puppeteer-sharp + https://stackoverflow.com/questions/62042078/puppeteer-sharp-for-server-side-html-to-pdf-conversions + https://www.singlestoneconsulting.com/blog/how-to-generate-server-side-pdf-reports-puppeteer-d3-handlebars/ + https://github.com/hardkoded/puppeteer-sharp/issues/1510 - shows being used by someone other than jsreport which buries all the details in endless libs + https://github.com/hardkoded/puppeteer-sharp/issues/1514 + + WeasyPrint + https://github.com/jsreport/jsreport-weasyprint-pdf + SLOWEST SPEED + https://github.com/Kozea/WeasyPrint based on python, does it's own rendering doesn't rely on a web browser engine like the rest + free, recommended by wkhtmltopdf author as an alternative + May be slow, slower than the other options likely, has some Installation procedure that are a bit convoluted but ironically only for windows as it's included in package managers + Very good support for modern css3 PAGE properties apparently + WRAPPER + https://github.com/balbarak/WeasyPrint-netcore/blob/master/src/Balbarak.WeasyPrint/WeasyPrintClient.cs + + + wkhtmltopdf + https://github.com/jsreport/jsreport-wkhtmltopdf + MEDIUM SPEED + https://wkhtmltopdf.org/downloads.html + Well used, old based on older webkit so doesn't support css3 but likely enough for our purposes + has an easy installer for all platforms + free + Has warnings about how unsanitized html can take down a server or own it somehow + WRAPPERS + https://github.com/carloscds/HtmlToPDFCore/tree/master/HtmlToPDFCore This one looks cool, all platforms supported includes binary possibly? + https://blog.elmah.io/generate-a-pdf-from-asp-net-core-for-free/ + + +HTML -> DOCX + This is a possiblity that needs to be researched, instead of pdf go docx which is in theory multi platform and openable on other devices? Not sure + https://github.com/jsreport/jsreport-docx + https://github.com/EricWhiteDev/Open-Xml-PowerTools + +HTML -> XLSX + https://github.com/jsreport/jsreport-xlsx + +HTML -> TEXT + https://github.com/jsreport/jsreport-html-to-text + https://github.com/jsreport/jsreport-text + + +TEMPLATE ENGINE + https://github.com/jsreport/jsreport-handlebars + Handlebars by default for jsreport which is easy peasy to work with + +PDF META DATA EDITING + https://github.com/jsreport/jsreport-pdf-meta + +Render outputs + JSReport renders to different outputs, they call it recipes https://jsreport.net/learn/recipes + HTML - just outputs as html for viewing in the browser / printing from browser + PDF: https://jsreport.net/learn/pdf-recipes + Outputs 5 different pdf converters because they all support different feature sets which is ominous + + + +BAR CODE STUFF + Bar codes: https://github.com/metafloor/bwip-js + https://stackoverflow.com/questions/19017512/use-canvas-inside-a-handlebars-template + https://github.com/metafloor/bwip-js#browser-usage + https://www.scandit.com/blog/types-barcodes-choosing-right-barcode/ + https://github.com/metafloor/bwip-js/wiki/BWIPP-Barcode-Types + + let opt = { + bcid: "code128", // Barcode type + text: "0123456789", // Text to encode + scale: 3, // 3x scaling factor + height: 10, // Bar height, in millimeters + includetext: true, // Show human-readable text + textxalign: "center" // Always good to set this + }; diff --git a/devdocs/specs/core-reviews.txt b/devdocs/old-devdocs/specs/core-reviews.txt similarity index 97% rename from devdocs/specs/core-reviews.txt rename to devdocs/old-devdocs/specs/core-reviews.txt index c3c1b6be..59b76d90 100644 --- a/devdocs/specs/core-reviews.txt +++ b/devdocs/old-devdocs/specs/core-reviews.txt @@ -1,306 +1,306 @@ -# Reviews (was follow-ups, follow ups, followups, schedulemarkers) - -JOYCE SPEC DOC NOTES: - -Follow Ups - -SEE CASE 3511 for this. - -Overdue Follow Ups -Home area – user based Follow Ups -Home area - role based Follow Ups -List area - Follow Ups -Follow Ups View list -Changing Active state of record to inactive that has Follow Up(s) Linked To: -Changing Active state of User record to inactive that has Follow Up(s) Assigned To: -Follow Ups historical -Role rights -Follow Up form and fields -⦁ Special note: Toggle to allow Assigned to edit or not -Records that have associated Follow Ups: - - - -Overdue Follow Ups: -⦁ Form display: -⦁ In the form, shows OVERDUE whether it be a stamp or whatever – its not something that is set by a user, but AyaNova displays when sees that there is no completed date and Due By Date is older than now. -⦁ List display: -⦁ Each listed item that is overdue displays with an OVERDUE stamp too -⦁ So is very noticeable - - - -Home area – user based Follow Ups -⦁ Follow Ups -⦁ (each logged in user has their own Follow Ups area that displays the two types of relevant Follow Ups panel with badge) -⦁ -⦁ Overdue Follow Ups #xx -⦁ Follow Ups that are Active, that are Assigned To this user logged in, that have empty Completed Date, that Due By Date is prior to todays date & time. -⦁ Follow Ups Due over next 7 days #xx -⦁ Follow Ups that are Active, that are Assigned To this user logged in, that have empty Completed Date, that Due By Date is between todays date & time and 7 days from now. -⦁ - -Home area - role based Follow Ups -⦁ Panel shown for following role(s): -⦁ Dispatcher -⦁ -⦁ Overdue Follow Ups #xx -⦁ Follow Ups that are Active, that are Assigned To any user, that have empty Completed Date, that Due By Date is prior to todays date & time. -⦁ Follow Ups Due over next 7 days #xx -⦁ Follow Ups that are Active, that are Assigned To any user, that have empty Completed Date, that Due By Date is between todays date & time and 7 days from now. -⦁ List Actions when viewing the actual list: -⦁ Set to inactive selected -⦁ Delete selected -⦁ Reassign selected -⦁ Reschedule selected - - -List area - Follow Ups -⦁ Where all Follow Ups for all records could be viewed -⦁ regardless of who Assigned To, Active state, Linked To, Due By Date, Completed Date -⦁ List available to be viewed and edited and actions performed on by specific roles only: -⦁ Dispatcher-full -⦁ Setup-full -⦁ List Actions when viewing list: -⦁ Change Active state of selected -⦁ Delete selected -⦁ Reassign selected -⦁ Reschedule selected -⦁ List filter/sort options -⦁ Active (Active/Inactive – true/false isn't what shows, so we should NOT list the filter as such. Filter should actually be what this is) -⦁ Due By Date (empty, equal to specific date, greater than, less than) -⦁ Completed Date (empty, equal to specific date, greater than, less than) -⦁ Assigned to -⦁ Tag(s) -⦁ Provide ability to filter to show all records that have this tag OR this tag ? -⦁ Provide ability to filter to show all records that have this tag AND this tag? -⦁ Provide ability to filter to show all records that have this tag AND/OR this tag - - - -Follow Ups View list: -⦁ Each main record has a Follow Ups view that lists: -⦁ By default shows: -⦁ Overdue: Active Follow Ups for THIS record that are Active, that do not have a Completed Date, whose Due By Date is past are shown with OVERDUE -⦁ By default sorted by: -⦁ Due By Date -⦁ Filtering options: -⦁ Preset selections of: -⦁ Not Yet Completed (nor overdue) -⦁ Overdue -⦁ Completed -⦁ Active (Active/Inactive – true/false isn't what shows, so we should NOT list the filter as such. Filter should actually be what this is) -⦁ Due By Date (empty, equal to specific date, greater than, less than) -⦁ Completed Date (empty, equal to specific date, greater than, less than) -⦁ Assigned to -⦁ This list does NOT list Follow Ups for the record's “children” -⦁ i.e. a client's Follow Ups View does NOT include listing follow ups for its units, for its workorders. -⦁ (I mean yes, it would be awesome if the list included Follow Ups of items linked to this same project so that a user could see at a glance all related Follow ups – i.e. follow ups for workorders where this Project has been selected) but at this time I am not sure is a necessity, so we will leave as is -⦁ List Actions: -⦁ Mass change who assigned to -⦁ be able to select one or more multiple followups in the list and “Mass change who assigned to” (so can assign to someone else) -⦁ action NOT available for Tech-limited, Subcontractor-full, Subcontractor-limited as Follows Ups able to view are only those assigned to themselves -⦁ Mass Edit the Due Date -⦁ be able to select one or more multiple followups in the list and “Mass Edit the Due Date” such as Move existing Due Date xx yyy ahead where xx equals a number, and yyy equals the amount of change. -⦁ Same feature here will be used “inside” the Follow Up form to set the Due By Date -⦁ i.e. gives options for quick selection (i.e. 1 day from now, 1 week from now, 1 month from now, As well as ability to manually select specific date/time -⦁ See for example: Wrike.com -⦁ Actions available for read only list of tasks include ability to reschedule – changing the existing of all selected ahead either days, weeks or months. ( I would like to also include hours) -⦁ Which is a superb QUICK way to quickly reschedule a number of items at the same time, putting all forward the same amount (i.e. push forward all selected by an hour, three hours, a day, a week, etc) - - - - - - - - - - -Changing Active state of a record to inactive that has a FollowUp Linked To: - -Active/Inactive: -⦁ Only the follow roles can edit the Active state of a record – because doing so affects other records: -⦁ Setup-full -⦁ Dispatcher-full -Circumstances that Follow Up may be unchecked Active automatically -⦁ When the Linked To of the Follow Up is set to inactive, AyaNova8 automatically sets Follow Up(s) linked to that record also to inactive. -⦁ i.e. set a unit to inactive, all of its Follow Ups that are not yet completed automatically set to inactive -⦁ i.e. set a client to inactive, all of its Follow Ups not yet completed are set to inactive, all of its PM's Follow Ups set to inactive, all of its PMs set to inactive, all of its Unit's Follow Ups set to inactive, all of its Units set to inactive, etc -What about going from inactive to active, does it then re-activate those items? -[ED: no this isn't a good idea, people may want the Review to be active but not the main record and it's a can of worms to reactivate etc] - -Changing Active state of User record to inactive that has Follow Up(s) Assigned To: -⦁ Exception related to Assigned To -⦁ The user Assigned To can not be unchecked Active if this user has ANY follow ups that do not have a Completed Date. -⦁ Whether inactive or Active. -⦁ Idea behind this aspect is so that there are not inactive follow ups floating around that are not needed. -⦁ And internally for us, so that setting a user to inactive does make the enduser keep their AyaNova clean. -⦁ This way end user doesn't set all Follow Ups to inactive whether are outstanding or not. -[ED: no, again these should not be affected because a supervisor may set a user inactive then see their followups in their master grid and batch reassign them keeping them in play] - - - - -Follow Ups historical: -⦁ AyaNova will not automatically prune records created by a user -⦁ i.e. AyaNova will auto prune the access log, and notifications logs, but NOT actual records such as Follow Ups, Workorders, Pos, etc. -⦁ Completed Follow Ups are not pruned -⦁ Provide ability to mass delete from the list being viewed by specific roles only -⦁ i.e. tech and subcontractor roles can not delete a Follow Up -⦁ i.e. Dispatcher can view Follow Ups for a tech, and mass delete those completed. -⦁ - -Role rights: -⦁ Each user regardless of role, can view Follow Ups that they are the Assigned To -⦁ Each user regardless of role, can view Follow ups that they are who is the type (user) Linked To -⦁ Each user regardless of role, can set a Follow Up to Completed IF they are the Assigned To. -⦁ . -⦁ Specific roles can NOT create a new Follow Up -⦁ Tech-limited, Sub-contractor-limited can NOT create -⦁ The user creating can set whether the Assigned can edit the Due Date or not -⦁ This than allows for scenarios where want to give the assigned ability to edit the due date or not. -⦁ Otherwise only specific roles can edit the Due By Date -⦁ . -⦁ Specific roles restricted in what can be edited in the Follow Up assigned to them -⦁ -⦁ Is user Assigned To:? -⦁ Yes -⦁ -⦁ No -⦁ Can view if setup-full and dispatcher-full -⦁ Can edit if setup-full and dispatcher-full -⦁ . -⦁ Only specific roles can assign someone other than themselves to a Follow Up -⦁ Only specific role(s) can manually edit the Completed Date -⦁ Only specific role(s) can set a Follow Up to inactive -⦁ Only specific role(s) can delete a Follow Up -⦁ Setup-full -⦁ Dispatcher-full - - -Follow Up form and fields: -⦁ Active/Inactive -⦁ Assigned to -⦁ Due By Date -⦁ Summary -⦁ Details -⦁ Completed Date -⦁ Completed Details -⦁ Shows but not editable by enduser regardless of role -⦁ Record History -⦁ Created/Created By Last Modified/Last Modified By -⦁ Record Type -⦁ type of record -⦁ Linked To -⦁ name of record - -Actions on single Follow Up -⦁ Delete -⦁ Only available to Setup-full -⦁ Save -⦁ Cancel out of (disgards changes not yet saved) - -Actions on multiple Follow Ups (in a list for the source, in a list for a record) -⦁ Set selected to Inactive -⦁ Delete selected -⦁ Only available to Setup-full -⦁ Note that not all fields editable by user creating, user editing: -⦁ Type of record for -⦁ Not a selectable field, is set internally based on the record Assigned To -⦁ To facilitate filtering by type of record linked to -⦁ i.e. Unit is a Type, Client is a Type, etc -⦁ Record Activity -⦁ Same ole as AyaNova7 -⦁ Created By, Created Date -⦁ Last Modified By, Last Modified Date -⦁ Active/Inactive -⦁ Only following role(s) can change Active state -⦁ Dispatcher-full -⦁ Setup-full -⦁ For any other role, ONLY shows stamp of Inactive if set to inactive, otherwise nothing shows when is Active -⦁ Completed Date: -⦁ Only specific role(s) have access to edit the actual Completed Date -⦁ Dispatcher-full -⦁ Setup-full -⦁ Rest of the roles have access only to select Set to Completed, which auto fills in Completed Date -⦁ Linked To: -⦁ This is the record the Follow Up is for – any main record in AyaNova (client, wo, pm, unit, unit model, project, user) -⦁ Automatically populated as a Follow Up is only ever created “from” the record itself -⦁ Not editable by any user. -⦁ Additional: -⦁ Note: a Follow Up Linked To a user can be viewed by that same user but CAN NOT be edited as NOT the same as Assigned To: -⦁ This way a user can see follow ups to do with themselves (i.e. mgmt set Follow Up to go over time spent on breaks with Bob. Bob can see this follow up, but can not edit it). NOT SURE I AGREE WITH THIS AS IT IS PRIVATE INFO IN THE SCENARIO OUTLINED -⦁ Hmmmm do client's by default get to see Follow Ups linked to themselves? -⦁ ?? is there a need to be able to create a Follow Up elsewhere and need to select the record Linked To?? -⦁ NO - A user can only create a follow up for a record they have access to, so no is my answer -⦁ Too db intensive to bring back every possible type of record this user has access to -⦁ Assigned To: -⦁ Can not be blank – required field -⦁ This is who is to perform the Follow Up -⦁ If don't know who to assign to, then suggestion is to assign to yourself, the person creating. -⦁ By default, the user creating the Follow Up is pre-selected. -⦁ Additional: -⦁ Selection list depends on the role of the user creating: -⦁ Dispatcher-full, Setup-full: -⦁ list of all active users. -⦁ All other roles, their own name is default selected and is the only available selection. -⦁ Due By Date: -⦁ Can not be blank – required field -⦁ Creator by default can always edit the Due By Date when creating and when editing -⦁ Provide quick selection in the form in addition to Date/Time field -⦁ i.e. Hour from now, Day from now, Week from now, Month from now. -⦁ . -⦁ Summary -⦁ Single line -⦁ Creator by default can -⦁ Follow Up Details -⦁ Multi-line – meant for entering details about what need to do -⦁ Completed Details -⦁ Multi-line – where source user can enter details about what they did -⦁ Tags -⦁ A way for grouping and filtering -⦁ i.e. so if search for all records with a specific tag, returns all that have, each sorted by type of record returned as in all Follow Ups returned and listed together, all Clients that have this tag returned and listed together. -⦁ See tags doc -⦁ Assigned can edit : -⦁ If user created the followup, can edit all fields. -⦁ -⦁ If user is NOT who Created the followup (only certain roles can create selecting for another user – Dispatcher-full, Setup-full), source user can only edit : -⦁ Completed Date -⦁ Completed Details -⦁ Certain roles can edit all fields including Active/Inactive of existing Follow Ups that have anotherr user assigned (Dispatcher-full and Setup-full) - - - - - - -Records that have associated Follow Ups: -[ED: All CoreBizObject types meaning pretty much everything except Reviews of course] -⦁ Any record that has”views” -⦁ Client -⦁ HeadOffice -⦁ Project -⦁ Unit -⦁ Unit Model -⦁ WO -⦁ PM -⦁ PO -⦁ Vendor -⦁ User -⦁ -⦁ Not sure of, as not sure if would have views -⦁ Contract -⦁ - - - - - - - - - - - - +# Reviews (was follow-ups, follow ups, followups, schedulemarkers) + +JOYCE SPEC DOC NOTES: + +Follow Ups + +SEE CASE 3511 for this. + +Overdue Follow Ups +Home area – user based Follow Ups +Home area - role based Follow Ups +List area - Follow Ups +Follow Ups View list +Changing Active state of record to inactive that has Follow Up(s) Linked To: +Changing Active state of User record to inactive that has Follow Up(s) Assigned To: +Follow Ups historical +Role rights +Follow Up form and fields +⦁ Special note: Toggle to allow Assigned to edit or not +Records that have associated Follow Ups: + + + +Overdue Follow Ups: +⦁ Form display: +⦁ In the form, shows OVERDUE whether it be a stamp or whatever – its not something that is set by a user, but AyaNova displays when sees that there is no completed date and Due By Date is older than now. +⦁ List display: +⦁ Each listed item that is overdue displays with an OVERDUE stamp too +⦁ So is very noticeable + + + +Home area – user based Follow Ups +⦁ Follow Ups +⦁ (each logged in user has their own Follow Ups area that displays the two types of relevant Follow Ups panel with badge) +⦁ +⦁ Overdue Follow Ups #xx +⦁ Follow Ups that are Active, that are Assigned To this user logged in, that have empty Completed Date, that Due By Date is prior to todays date & time. +⦁ Follow Ups Due over next 7 days #xx +⦁ Follow Ups that are Active, that are Assigned To this user logged in, that have empty Completed Date, that Due By Date is between todays date & time and 7 days from now. +⦁ + +Home area - role based Follow Ups +⦁ Panel shown for following role(s): +⦁ Dispatcher +⦁ +⦁ Overdue Follow Ups #xx +⦁ Follow Ups that are Active, that are Assigned To any user, that have empty Completed Date, that Due By Date is prior to todays date & time. +⦁ Follow Ups Due over next 7 days #xx +⦁ Follow Ups that are Active, that are Assigned To any user, that have empty Completed Date, that Due By Date is between todays date & time and 7 days from now. +⦁ List Actions when viewing the actual list: +⦁ Set to inactive selected +⦁ Delete selected +⦁ Reassign selected +⦁ Reschedule selected + + +List area - Follow Ups +⦁ Where all Follow Ups for all records could be viewed +⦁ regardless of who Assigned To, Active state, Linked To, Due By Date, Completed Date +⦁ List available to be viewed and edited and actions performed on by specific roles only: +⦁ Dispatcher-full +⦁ Setup-full +⦁ List Actions when viewing list: +⦁ Change Active state of selected +⦁ Delete selected +⦁ Reassign selected +⦁ Reschedule selected +⦁ List filter/sort options +⦁ Active (Active/Inactive – true/false isn't what shows, so we should NOT list the filter as such. Filter should actually be what this is) +⦁ Due By Date (empty, equal to specific date, greater than, less than) +⦁ Completed Date (empty, equal to specific date, greater than, less than) +⦁ Assigned to +⦁ Tag(s) +⦁ Provide ability to filter to show all records that have this tag OR this tag ? +⦁ Provide ability to filter to show all records that have this tag AND this tag? +⦁ Provide ability to filter to show all records that have this tag AND/OR this tag + + + +Follow Ups View list: +⦁ Each main record has a Follow Ups view that lists: +⦁ By default shows: +⦁ Overdue: Active Follow Ups for THIS record that are Active, that do not have a Completed Date, whose Due By Date is past are shown with OVERDUE +⦁ By default sorted by: +⦁ Due By Date +⦁ Filtering options: +⦁ Preset selections of: +⦁ Not Yet Completed (nor overdue) +⦁ Overdue +⦁ Completed +⦁ Active (Active/Inactive – true/false isn't what shows, so we should NOT list the filter as such. Filter should actually be what this is) +⦁ Due By Date (empty, equal to specific date, greater than, less than) +⦁ Completed Date (empty, equal to specific date, greater than, less than) +⦁ Assigned to +⦁ This list does NOT list Follow Ups for the record's “children” +⦁ i.e. a client's Follow Ups View does NOT include listing follow ups for its units, for its workorders. +⦁ (I mean yes, it would be awesome if the list included Follow Ups of items linked to this same project so that a user could see at a glance all related Follow ups – i.e. follow ups for workorders where this Project has been selected) but at this time I am not sure is a necessity, so we will leave as is +⦁ List Actions: +⦁ Mass change who assigned to +⦁ be able to select one or more multiple followups in the list and “Mass change who assigned to” (so can assign to someone else) +⦁ action NOT available for Tech-limited, Subcontractor-full, Subcontractor-limited as Follows Ups able to view are only those assigned to themselves +⦁ Mass Edit the Due Date +⦁ be able to select one or more multiple followups in the list and “Mass Edit the Due Date” such as Move existing Due Date xx yyy ahead where xx equals a number, and yyy equals the amount of change. +⦁ Same feature here will be used “inside” the Follow Up form to set the Due By Date +⦁ i.e. gives options for quick selection (i.e. 1 day from now, 1 week from now, 1 month from now, As well as ability to manually select specific date/time +⦁ See for example: Wrike.com +⦁ Actions available for read only list of tasks include ability to reschedule – changing the existing of all selected ahead either days, weeks or months. ( I would like to also include hours) +⦁ Which is a superb QUICK way to quickly reschedule a number of items at the same time, putting all forward the same amount (i.e. push forward all selected by an hour, three hours, a day, a week, etc) + + + + + + + + + + +Changing Active state of a record to inactive that has a FollowUp Linked To: + +Active/Inactive: +⦁ Only the follow roles can edit the Active state of a record – because doing so affects other records: +⦁ Setup-full +⦁ Dispatcher-full +Circumstances that Follow Up may be unchecked Active automatically +⦁ When the Linked To of the Follow Up is set to inactive, AyaNova8 automatically sets Follow Up(s) linked to that record also to inactive. +⦁ i.e. set a unit to inactive, all of its Follow Ups that are not yet completed automatically set to inactive +⦁ i.e. set a client to inactive, all of its Follow Ups not yet completed are set to inactive, all of its PM's Follow Ups set to inactive, all of its PMs set to inactive, all of its Unit's Follow Ups set to inactive, all of its Units set to inactive, etc +What about going from inactive to active, does it then re-activate those items? +[ED: no this isn't a good idea, people may want the Review to be active but not the main record and it's a can of worms to reactivate etc] + +Changing Active state of User record to inactive that has Follow Up(s) Assigned To: +⦁ Exception related to Assigned To +⦁ The user Assigned To can not be unchecked Active if this user has ANY follow ups that do not have a Completed Date. +⦁ Whether inactive or Active. +⦁ Idea behind this aspect is so that there are not inactive follow ups floating around that are not needed. +⦁ And internally for us, so that setting a user to inactive does make the enduser keep their AyaNova clean. +⦁ This way end user doesn't set all Follow Ups to inactive whether are outstanding or not. +[ED: no, again these should not be affected because a supervisor may set a user inactive then see their followups in their master grid and batch reassign them keeping them in play] + + + + +Follow Ups historical: +⦁ AyaNova will not automatically prune records created by a user +⦁ i.e. AyaNova will auto prune the access log, and notifications logs, but NOT actual records such as Follow Ups, Workorders, Pos, etc. +⦁ Completed Follow Ups are not pruned +⦁ Provide ability to mass delete from the list being viewed by specific roles only +⦁ i.e. tech and subcontractor roles can not delete a Follow Up +⦁ i.e. Dispatcher can view Follow Ups for a tech, and mass delete those completed. +⦁ + +Role rights: +⦁ Each user regardless of role, can view Follow Ups that they are the Assigned To +⦁ Each user regardless of role, can view Follow ups that they are who is the type (user) Linked To +⦁ Each user regardless of role, can set a Follow Up to Completed IF they are the Assigned To. +⦁ . +⦁ Specific roles can NOT create a new Follow Up +⦁ Tech-limited, Sub-contractor-limited can NOT create +⦁ The user creating can set whether the Assigned can edit the Due Date or not +⦁ This than allows for scenarios where want to give the assigned ability to edit the due date or not. +⦁ Otherwise only specific roles can edit the Due By Date +⦁ . +⦁ Specific roles restricted in what can be edited in the Follow Up assigned to them +⦁ +⦁ Is user Assigned To:? +⦁ Yes +⦁ +⦁ No +⦁ Can view if setup-full and dispatcher-full +⦁ Can edit if setup-full and dispatcher-full +⦁ . +⦁ Only specific roles can assign someone other than themselves to a Follow Up +⦁ Only specific role(s) can manually edit the Completed Date +⦁ Only specific role(s) can set a Follow Up to inactive +⦁ Only specific role(s) can delete a Follow Up +⦁ Setup-full +⦁ Dispatcher-full + + +Follow Up form and fields: +⦁ Active/Inactive +⦁ Assigned to +⦁ Due By Date +⦁ Summary +⦁ Details +⦁ Completed Date +⦁ Completed Details +⦁ Shows but not editable by enduser regardless of role +⦁ Record History +⦁ Created/Created By Last Modified/Last Modified By +⦁ Record Type +⦁ type of record +⦁ Linked To +⦁ name of record + +Actions on single Follow Up +⦁ Delete +⦁ Only available to Setup-full +⦁ Save +⦁ Cancel out of (disgards changes not yet saved) + +Actions on multiple Follow Ups (in a list for the source, in a list for a record) +⦁ Set selected to Inactive +⦁ Delete selected +⦁ Only available to Setup-full +⦁ Note that not all fields editable by user creating, user editing: +⦁ Type of record for +⦁ Not a selectable field, is set internally based on the record Assigned To +⦁ To facilitate filtering by type of record linked to +⦁ i.e. Unit is a Type, Client is a Type, etc +⦁ Record Activity +⦁ Same ole as AyaNova7 +⦁ Created By, Created Date +⦁ Last Modified By, Last Modified Date +⦁ Active/Inactive +⦁ Only following role(s) can change Active state +⦁ Dispatcher-full +⦁ Setup-full +⦁ For any other role, ONLY shows stamp of Inactive if set to inactive, otherwise nothing shows when is Active +⦁ Completed Date: +⦁ Only specific role(s) have access to edit the actual Completed Date +⦁ Dispatcher-full +⦁ Setup-full +⦁ Rest of the roles have access only to select Set to Completed, which auto fills in Completed Date +⦁ Linked To: +⦁ This is the record the Follow Up is for – any main record in AyaNova (client, wo, pm, unit, unit model, project, user) +⦁ Automatically populated as a Follow Up is only ever created “from” the record itself +⦁ Not editable by any user. +⦁ Additional: +⦁ Note: a Follow Up Linked To a user can be viewed by that same user but CAN NOT be edited as NOT the same as Assigned To: +⦁ This way a user can see follow ups to do with themselves (i.e. mgmt set Follow Up to go over time spent on breaks with Bob. Bob can see this follow up, but can not edit it). NOT SURE I AGREE WITH THIS AS IT IS PRIVATE INFO IN THE SCENARIO OUTLINED +⦁ Hmmmm do client's by default get to see Follow Ups linked to themselves? +⦁ ?? is there a need to be able to create a Follow Up elsewhere and need to select the record Linked To?? +⦁ NO - A user can only create a follow up for a record they have access to, so no is my answer +⦁ Too db intensive to bring back every possible type of record this user has access to +⦁ Assigned To: +⦁ Can not be blank – required field +⦁ This is who is to perform the Follow Up +⦁ If don't know who to assign to, then suggestion is to assign to yourself, the person creating. +⦁ By default, the user creating the Follow Up is pre-selected. +⦁ Additional: +⦁ Selection list depends on the role of the user creating: +⦁ Dispatcher-full, Setup-full: +⦁ list of all active users. +⦁ All other roles, their own name is default selected and is the only available selection. +⦁ Due By Date: +⦁ Can not be blank – required field +⦁ Creator by default can always edit the Due By Date when creating and when editing +⦁ Provide quick selection in the form in addition to Date/Time field +⦁ i.e. Hour from now, Day from now, Week from now, Month from now. +⦁ . +⦁ Summary +⦁ Single line +⦁ Creator by default can +⦁ Follow Up Details +⦁ Multi-line – meant for entering details about what need to do +⦁ Completed Details +⦁ Multi-line – where source user can enter details about what they did +⦁ Tags +⦁ A way for grouping and filtering +⦁ i.e. so if search for all records with a specific tag, returns all that have, each sorted by type of record returned as in all Follow Ups returned and listed together, all Clients that have this tag returned and listed together. +⦁ See tags doc +⦁ Assigned can edit : +⦁ If user created the followup, can edit all fields. +⦁ +⦁ If user is NOT who Created the followup (only certain roles can create selecting for another user – Dispatcher-full, Setup-full), source user can only edit : +⦁ Completed Date +⦁ Completed Details +⦁ Certain roles can edit all fields including Active/Inactive of existing Follow Ups that have anotherr user assigned (Dispatcher-full and Setup-full) + + + + + + +Records that have associated Follow Ups: +[ED: All CoreBizObject types meaning pretty much everything except Reviews of course] +⦁ Any record that has”views” +⦁ Client +⦁ HeadOffice +⦁ Project +⦁ Unit +⦁ Unit Model +⦁ WO +⦁ PM +⦁ PO +⦁ Vendor +⦁ User +⦁ +⦁ Not sure of, as not sure if would have views +⦁ Contract +⦁ + + + + + + + + + + + + diff --git a/devdocs/specs/core-roles.txt b/devdocs/old-devdocs/specs/core-roles.txt similarity index 97% rename from devdocs/specs/core-roles.txt rename to devdocs/old-devdocs/specs/core-roles.txt index 9b4826e5..e93bee71 100644 --- a/devdocs/specs/core-roles.txt +++ b/devdocs/old-devdocs/specs/core-roles.txt @@ -1,325 +1,325 @@ -# Roles specifications - -From case https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/1809 - -RAVEN will replace security rights system of v7 with a role based system instead -I'm using an int flags enum which means a maximum of 32 possible roles unless I bump it up to a long but don't really want to as this number will be thrown around the api a lot - -ROLES set general accessibility to change or delete or read objects, however Business rules may further restrict on top of that. - -**DELETE RIGHTS*** -If you can modify an object you can delete an object unless business rules say otherwise - -**SEE NAME / PICKLISTS *** - - Not sure if correct but for now assuming anyone can read the name of any object and that the UI will exclude them by biz rule if they aren't supposed to see something - - this does mean a subcontractor could use the api to fetch a list of customers outside of the client though...hmmm.. - - -**LIMITED ROLES / BUSINESS RULES LIMITATIONS ** -(formerly self owned) -In some cases business rules may further restrict what a user can do. -For example a SubContractorLimited has the change right to a workorder, but in fact the workorder itself has business rules that limit that drastically down to almost nothing but a single area entry in labor - -=-=-=-=- HOW TO HANDLE EDIT OWN PLANNING =-=-=-=-=- -- EditOwn IS DEPRECATED FROM ORIGINAL PLAN is really not about editown it's about supporting a user who is not supposed to see any data other than the bare minimum in order to fill out workorders - - Make it a business rule(s) instead in the areas of workorders and anything specific - - Get rid of edit own rights code entirely - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - -** LIMITED ROLES ACCESS RIGHTS PLANNING ** -As of jan 2020 just trying to determine what the limited roles do as they are the least clear, here is some thinking on that: - - Do I need all the limited roles or are some redundant - - My thinking currently is it could be too complex for people to understand unless it's very clear what the dividing line is and in many cases people probably won't care about the limited roles / overthinking it - - some people want to set every last little thing but are we selling to those people or to people who just want to get shit done - - Many people just want the ability to not show private info and I have pretty good handle on that like hiding costs, client lists etc - - How many of oru customers will have a junior dispatcher or junior inventory person? - - Even if this isn't perfect I need to start with something and can build on it later, so keep in mind TTM and simpler is better up to a point - - No need to figure everythign otu at this point, it's easier to work with actual features down the road and restrict more then - - Issues is mainly to do with what the limited roles are all about and where the dividing line for features will be - - MAYBE the way to think of this is that the limited roles are all basically READ ONLY versions of the full roles - - This satisfies the need for office people to be able to look shit up but not break it by changing it - - CURRENT RESOLUTION TO THIS: just go ahead and code it now - - I have a pretty clear understanding of the full roles - - Work out the Limited roles later when I have actual features to limit and can see it in action - - Code it so that this is kept in mind so it's not a bitch to go back in limit later -================================================== - -LISTS UNDER LIMITED ROLES -If a user *can* potentially view or edit an object type then that object's list will display, if certain fields should be restricted then they will be via business rules when the record is opened. -So in theory lists should not show stuff that a user has no rights to see, so some columns need to be restricted for those users when the list is delivered by the server -Case by case issue. - -********** -Theoretical company entitities concerned with AyaNova: - -Upper Management - - KPI - - View schedule - - View read only workorders full view though - -Service manager - - Create users set roles - - Access everything except OPS (and possibly some accounting functionality restriction?) - -I.T. - - OPS, setup, backup etc - - No access to biz data at all - -Accounting - - Invoicing - - Clients - - View any biz related data - - No ability to modify workorders unless accounting related like invoice number or something - -HR - - Create users - - Disable users - -Sales - - Quotes - - View clients / ho - - Create clients? - -Service - - Workorders - - view quotes - - Turn wo into quotes - - CSR - - Create modify clients headoffices - -Shipping receiving - - Receive PO - - Outside service receiving - -Inventory - - Create parts - - Create warehouses - - all inventory related like make po's, receive them - -Customers - - View their shit - -************************************************************************************************************************************************************ - -## ROLES - -### None -No rights, not settable, just for internal usage in code - -### BizAdminLimited -Intended for a business administrator / supervisor who wants to monitor the business, kpi, reporting etc, but doesn't actually get to change anything. -Suitable for the "big boss" who isn't trusted to make actual day to day decisions but can review anything. -NOT FULLY FLESHED OUT THIS CAN ALL CHANGE -**RIGHTS** -- Read only access to everything (except OPS stuff) -- Full access to management reporting, KPI etc, but can't change them substantially, just sort, filter etc. - - -### BizAdminFull - -Basically the v7 manager account stuff with full rights to everything other than OpsAdmin stuff. - -**RIGHTS** -- Full access to all AyaNova objects with the sole exception of OPS related stuff -- ONLY role that can make a user or change a user's roles -- Grants roles to other users -- Licensing -- Business related configuration settings - - Form customization - - Localized text customization -- All management and KPI stuff -- NO Operations rights at all so no setup, or troubleshooting logs or technical details - -### DispatchLimited -see roles.odt for more info -NOT FULLY FLESHED OUT THIS CAN ALL CHANGE -- Intended as the junior dispatcher account, where they can help with day to day but not change anything big or see any private data -- Can create workorder -- Can add users to workorder / schedule -- view other dispatch full objects as readonly like clients, vendors, headoffices etc -- No areas of workorder that are not directly related to scheduling - -### DispatchFull -see roles.odt for more info -- Intended as the role for the person managing a group of techs and scheduling, pre-filling in workorders etc -- Create workorder -- Create clients -- Create vendors -- Can see anything related to scheduling and conveying service -- Not necessarily the service manager who would have multiple roles like InventoryFull and DispatchFull -- Schedule anyone -- View and edit any area of any workorder with possible exception of profit and loss stuff or any strictly BIZ functionality -- Does not have inventory rights to make inventory changes like creating parts - - -### InventoryLimited -see roles.odt for more info -NOT FULLY FLESHED OUT THIS CAN ALL CHANGE -NO PO functionality except maybe able to receive?? To be determined -View inventory, adjust inventory -creat parts, assign vendors etc (dispatcher comes to them for new parts to be created) -NO dangerous or biz affecting rights -REad only rights to all other objects that InventoryFull can edit - -### InventoryFull -see roles.odt for more info -Same as inventory limited but with all the PO related stuff -Also can fully change and create warehouses -Create vendors - - -### Accounting -see roles.odt for more info -- Create vendors -- Create / edit clients (ho) -- Integrate with QB external accounting software etc -- No access to inventory, if that's needed they can give the user inventory role as well - -### TechFull -see roles.odt for more info -- consumes a license -- Can create their own workorders and schedule themselves on them but can't schedule others, that's dispatch job -- Some areas of workorder are still not availble if they are related to other roles such as accounting etc -- Not able to see part costs or % markup or any data not absolutely essential to doing their job -- Can create unit -- Can create client - - - -### TechLimited -see roles.odt for more info -- CONSUMES A LICENSE -NOT FULLY FLESHED OUT THIS CAN ALL CHANGE -- Isnt this basically a subcontractor though? -- More rights than a subcontrator but less than a full tech, cannot see sensitive data -- Can't schedule themselves only add labor -- Can make entries into existing workorders, add rows to existing areas in the workorder but can't add a new area or create a new workorder -- Can only see their own workorders, no one elses -- No access to any costs or business data of any kind -- Can't make clients or vendors or units - - -### SubContractorLimited -NOTE 2020-04-14 13:19:17: There is a case for this that I haven't read to update this block of text yet -https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/1465 - -For filling out labor on workorders but not seeing any details of the workorder -Like a tech limited but more limited. -NOT FULLY FLESHED OUT THIS CAN ALL CHANGE -** Essentially the only purpose of this is to allow them to enter labor on a pre-existing workorder but really see almost nothing on the workorder except the bare minimum to enter labor -They can see only where they are scheduled in the schedule form, no client name, nothing of any detail at all, just work and enter it. -see roles.odt for more info -can only add themselves as a labor entry, not much else unless it proves necessary. -For a tech/subcontractor that is not trusted with company information including even client name – i.e. just given the work to perform and enter details about that work, but doesn't need access to anything else -Can't select new parts only uses existing ones -ONLY ACCESS TO DASHBOARD TO SEE *THEIR* SHIT, SERVICE NAV ITEMS NOT VISIBLE - -### SubContractorFull -See case 1465 mentioned above -Same as limited except can also see the client name and address and can select parts and other things to add to workorder but not see any details about those things outside the wo view -see roles.odt for more info - -### ClientLimited - -### ClientFull - -### OpsAdminLimited -Like ops full but for read only and simle maintenance or watching / observing when issues -A role you'd give an office person with no tech background but who is tasked with backup or looking at logs when things go wrong -backup but can't restore -view logs, call ops full (I.T.) when issue arises - -### OpsAdminFull -Any major db change like restore, importing etc. -backup, troubleshoot, dashboard of throughput, db administration, all the stuff needed to keep RAVEN up and running and monitor any issues in operations of it, -nothing to do with business stuff or actual business data - -### SALESFULL -Makes QUOTES -View and create clients? -Turn quote into workorder? (that implies scheduling rights, sb dispatcher job) -Maybe they approve the quote for service then a service manager does the actual booking! - -### SALESLIMITED -(basically a read only sales full) -Views quotes, can't change them? -View customers can't change them - -************************************************************************************************************************************************************ - - -BizAdminLimited | BizAdminFull | DispatchLimited | DispatchFull | InventoryLimited | - InventoryFull | AccountingFull | TechLimited | TechFull | SubContractorLimited | - SubContractorFull | ClientLimited | ClientFull | OpsAdminLimited | OpsAdminFull | SalesFull | SalesLimited - -# CLIENT UI AREAS AND ROLES THAT CAN SEE THEM -(there are other restrictions individually but this is just that they are visible to those users in the main UI) - -## HOME - - [ALL ROLES EXCEPT CLIENT ONES, RESTRICTIONS BY BIZ RULES AND EXCEPTIONS ONLY] - - Dashboard - - Search - - Schedule - - Memos - - Reminders - - Translation settings for User - - Set login and password - - Notification subscriptions - -## CUSTOMERS - [FULL - BAF, DF, ACC, TF ] - [READ ONLY - BAL, DL, TL ] - - Customers - - Head offices - -## SERVICE - - Schedule (all) - - [FULL - BAF, DF, DL ] - - [READ ONLY - BAL ] - - - Workorders - - [FULL - ACC, DF, DL ] - - [READ ONLY - TF, BAL ] - - [SPECIAL - TF can see all and create their own wo and put themselves on it but no other techs can be selected by them] - - Quotes - - [FULL - SF, SL] - - Preventive Maintenance - - Customer Units - - Unit Models - - Loan Items - - Contracts - - Customer Service Requests - -## INVENTORY - - Parts - - Part inventory - - Part Requests - - Purchase orders - - Purchase Order Receipts - - Adjustments - -## VENDORS - - -## ACCOUNTING - - Accounting - -## ADMINISTRATION - - Global settings - - license - - Users - - Localized Text Design - - Report Templates - - Attached Files - - History (change log for all objects) - - Statistics (KPI SHIT) - -## SERVER OPERATIONS - - Backup - - Job Queue - - Server log - - Server metrics - - Notifciation Settings - -## TEST WIDGETS +# Roles specifications + +From case https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/1809 + +RAVEN will replace security rights system of v7 with a role based system instead +I'm using an int flags enum which means a maximum of 32 possible roles unless I bump it up to a long but don't really want to as this number will be thrown around the api a lot + +ROLES set general accessibility to change or delete or read objects, however Business rules may further restrict on top of that. + +**DELETE RIGHTS*** +If you can modify an object you can delete an object unless business rules say otherwise + +**SEE NAME / PICKLISTS *** + - Not sure if correct but for now assuming anyone can read the name of any object and that the UI will exclude them by biz rule if they aren't supposed to see something + - this does mean a subcontractor could use the api to fetch a list of customers outside of the client though...hmmm.. + + +**LIMITED ROLES / BUSINESS RULES LIMITATIONS ** +(formerly self owned) +In some cases business rules may further restrict what a user can do. +For example a SubContractorLimited has the change right to a workorder, but in fact the workorder itself has business rules that limit that drastically down to almost nothing but a single area entry in labor + +=-=-=-=- HOW TO HANDLE EDIT OWN PLANNING =-=-=-=-=- +- EditOwn IS DEPRECATED FROM ORIGINAL PLAN is really not about editown it's about supporting a user who is not supposed to see any data other than the bare minimum in order to fill out workorders + - Make it a business rule(s) instead in the areas of workorders and anything specific + - Get rid of edit own rights code entirely + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + +** LIMITED ROLES ACCESS RIGHTS PLANNING ** +As of jan 2020 just trying to determine what the limited roles do as they are the least clear, here is some thinking on that: + - Do I need all the limited roles or are some redundant + - My thinking currently is it could be too complex for people to understand unless it's very clear what the dividing line is and in many cases people probably won't care about the limited roles / overthinking it + - some people want to set every last little thing but are we selling to those people or to people who just want to get shit done + - Many people just want the ability to not show private info and I have pretty good handle on that like hiding costs, client lists etc + - How many of oru customers will have a junior dispatcher or junior inventory person? + - Even if this isn't perfect I need to start with something and can build on it later, so keep in mind TTM and simpler is better up to a point + - No need to figure everythign otu at this point, it's easier to work with actual features down the road and restrict more then + - Issues is mainly to do with what the limited roles are all about and where the dividing line for features will be + - MAYBE the way to think of this is that the limited roles are all basically READ ONLY versions of the full roles + - This satisfies the need for office people to be able to look shit up but not break it by changing it + - CURRENT RESOLUTION TO THIS: just go ahead and code it now + - I have a pretty clear understanding of the full roles + - Work out the Limited roles later when I have actual features to limit and can see it in action + - Code it so that this is kept in mind so it's not a bitch to go back in limit later +================================================== + +LISTS UNDER LIMITED ROLES +If a user *can* potentially view or edit an object type then that object's list will display, if certain fields should be restricted then they will be via business rules when the record is opened. +So in theory lists should not show stuff that a user has no rights to see, so some columns need to be restricted for those users when the list is delivered by the server +Case by case issue. + +********** +Theoretical company entitities concerned with AyaNova: + +Upper Management + - KPI + - View schedule + - View read only workorders full view though + +Service manager + - Create users set roles + - Access everything except OPS (and possibly some accounting functionality restriction?) + +I.T. + - OPS, setup, backup etc + - No access to biz data at all + +Accounting + - Invoicing + - Clients + - View any biz related data + - No ability to modify workorders unless accounting related like invoice number or something + +HR + - Create users + - Disable users + +Sales + - Quotes + - View clients / ho + - Create clients? + +Service + - Workorders + - view quotes + - Turn wo into quotes + - CSR + - Create modify clients headoffices + +Shipping receiving + - Receive PO + - Outside service receiving + +Inventory + - Create parts + - Create warehouses + - all inventory related like make po's, receive them + +Customers + - View their shit + +************************************************************************************************************************************************************ + +## ROLES + +### None +No rights, not settable, just for internal usage in code + +### BizAdminLimited +Intended for a business administrator / supervisor who wants to monitor the business, kpi, reporting etc, but doesn't actually get to change anything. +Suitable for the "big boss" who isn't trusted to make actual day to day decisions but can review anything. +NOT FULLY FLESHED OUT THIS CAN ALL CHANGE +**RIGHTS** +- Read only access to everything (except OPS stuff) +- Full access to management reporting, KPI etc, but can't change them substantially, just sort, filter etc. + + +### BizAdminFull + +Basically the v7 manager account stuff with full rights to everything other than OpsAdmin stuff. + +**RIGHTS** +- Full access to all AyaNova objects with the sole exception of OPS related stuff +- ONLY role that can make a user or change a user's roles +- Grants roles to other users +- Licensing +- Business related configuration settings + - Form customization + - Localized text customization +- All management and KPI stuff +- NO Operations rights at all so no setup, or troubleshooting logs or technical details + +### DispatchLimited +see roles.odt for more info +NOT FULLY FLESHED OUT THIS CAN ALL CHANGE +- Intended as the junior dispatcher account, where they can help with day to day but not change anything big or see any private data +- Can create workorder +- Can add users to workorder / schedule +- view other dispatch full objects as readonly like clients, vendors, headoffices etc +- No areas of workorder that are not directly related to scheduling + +### DispatchFull +see roles.odt for more info +- Intended as the role for the person managing a group of techs and scheduling, pre-filling in workorders etc +- Create workorder +- Create clients +- Create vendors +- Can see anything related to scheduling and conveying service +- Not necessarily the service manager who would have multiple roles like InventoryFull and DispatchFull +- Schedule anyone +- View and edit any area of any workorder with possible exception of profit and loss stuff or any strictly BIZ functionality +- Does not have inventory rights to make inventory changes like creating parts + + +### InventoryLimited +see roles.odt for more info +NOT FULLY FLESHED OUT THIS CAN ALL CHANGE +NO PO functionality except maybe able to receive?? To be determined +View inventory, adjust inventory +creat parts, assign vendors etc (dispatcher comes to them for new parts to be created) +NO dangerous or biz affecting rights +REad only rights to all other objects that InventoryFull can edit + +### InventoryFull +see roles.odt for more info +Same as inventory limited but with all the PO related stuff +Also can fully change and create warehouses +Create vendors + + +### Accounting +see roles.odt for more info +- Create vendors +- Create / edit clients (ho) +- Integrate with QB external accounting software etc +- No access to inventory, if that's needed they can give the user inventory role as well + +### TechFull +see roles.odt for more info +- consumes a license +- Can create their own workorders and schedule themselves on them but can't schedule others, that's dispatch job +- Some areas of workorder are still not availble if they are related to other roles such as accounting etc +- Not able to see part costs or % markup or any data not absolutely essential to doing their job +- Can create unit +- Can create client + + + +### TechLimited +see roles.odt for more info +- CONSUMES A LICENSE +NOT FULLY FLESHED OUT THIS CAN ALL CHANGE +- Isnt this basically a subcontractor though? +- More rights than a subcontrator but less than a full tech, cannot see sensitive data +- Can't schedule themselves only add labor +- Can make entries into existing workorders, add rows to existing areas in the workorder but can't add a new area or create a new workorder +- Can only see their own workorders, no one elses +- No access to any costs or business data of any kind +- Can't make clients or vendors or units + + +### SubContractorLimited +NOTE 2020-04-14 13:19:17: There is a case for this that I haven't read to update this block of text yet +https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/1465 + +For filling out labor on workorders but not seeing any details of the workorder +Like a tech limited but more limited. +NOT FULLY FLESHED OUT THIS CAN ALL CHANGE +** Essentially the only purpose of this is to allow them to enter labor on a pre-existing workorder but really see almost nothing on the workorder except the bare minimum to enter labor +They can see only where they are scheduled in the schedule form, no client name, nothing of any detail at all, just work and enter it. +see roles.odt for more info +can only add themselves as a labor entry, not much else unless it proves necessary. +For a tech/subcontractor that is not trusted with company information including even client name – i.e. just given the work to perform and enter details about that work, but doesn't need access to anything else +Can't select new parts only uses existing ones +ONLY ACCESS TO DASHBOARD TO SEE *THEIR* SHIT, SERVICE NAV ITEMS NOT VISIBLE + +### SubContractorFull +See case 1465 mentioned above +Same as limited except can also see the client name and address and can select parts and other things to add to workorder but not see any details about those things outside the wo view +see roles.odt for more info + +### ClientLimited + +### ClientFull + +### OpsAdminLimited +Like ops full but for read only and simle maintenance or watching / observing when issues +A role you'd give an office person with no tech background but who is tasked with backup or looking at logs when things go wrong +backup but can't restore +view logs, call ops full (I.T.) when issue arises + +### OpsAdminFull +Any major db change like restore, importing etc. +backup, troubleshoot, dashboard of throughput, db administration, all the stuff needed to keep RAVEN up and running and monitor any issues in operations of it, +nothing to do with business stuff or actual business data + +### SALESFULL +Makes QUOTES +View and create clients? +Turn quote into workorder? (that implies scheduling rights, sb dispatcher job) +Maybe they approve the quote for service then a service manager does the actual booking! + +### SALESLIMITED +(basically a read only sales full) +Views quotes, can't change them? +View customers can't change them + +************************************************************************************************************************************************************ + + +BizAdminLimited | BizAdminFull | DispatchLimited | DispatchFull | InventoryLimited | + InventoryFull | AccountingFull | TechLimited | TechFull | SubContractorLimited | + SubContractorFull | ClientLimited | ClientFull | OpsAdminLimited | OpsAdminFull | SalesFull | SalesLimited + +# CLIENT UI AREAS AND ROLES THAT CAN SEE THEM +(there are other restrictions individually but this is just that they are visible to those users in the main UI) + +## HOME + - [ALL ROLES EXCEPT CLIENT ONES, RESTRICTIONS BY BIZ RULES AND EXCEPTIONS ONLY] + - Dashboard + - Search + - Schedule + - Memos + - Reminders + - Translation settings for User + - Set login and password + - Notification subscriptions + +## CUSTOMERS + [FULL - BAF, DF, ACC, TF ] + [READ ONLY - BAL, DL, TL ] + - Customers + - Head offices + +## SERVICE + - Schedule (all) + - [FULL - BAF, DF, DL ] + - [READ ONLY - BAL ] + + - Workorders + - [FULL - ACC, DF, DL ] + - [READ ONLY - TF, BAL ] + - [SPECIAL - TF can see all and create their own wo and put themselves on it but no other techs can be selected by them] + - Quotes + - [FULL - SF, SL] + - Preventive Maintenance + - Customer Units + - Unit Models + - Loan Items + - Contracts + - Customer Service Requests + +## INVENTORY + - Parts + - Part inventory + - Part Requests + - Purchase orders + - Purchase Order Receipts + - Adjustments + +## VENDORS + + +## ACCOUNTING + - Accounting + +## ADMINISTRATION + - Global settings + - license + - Users + - Localized Text Design + - Report Templates + - Attached Files + - History (change log for all objects) + - Statistics (KPI SHIT) + +## SERVER OPERATIONS + - Backup + - Job Queue + - Server log + - Server metrics + - Notifciation Settings + +## TEST WIDGETS diff --git a/devdocs/specs/core-search.txt b/devdocs/old-devdocs/specs/core-search.txt similarity index 98% rename from devdocs/specs/core-search.txt rename to devdocs/old-devdocs/specs/core-search.txt index cb4992eb..4ae4a6ed 100644 --- a/devdocs/specs/core-search.txt +++ b/devdocs/old-devdocs/specs/core-search.txt @@ -1,107 +1,107 @@ -SEARCH SPECS - - - -CASES - -SEARCH:NEW: - Search dictionary: Auto remove orphaned words -https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/1878 - -WORKORDER:PARTS:SEARCH:CR:DUPLICATE 3358: - Parts Search on Parts Grid -https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/3310 - -WORKORDER:PARTS:SEARCH:CR:DUPLICATE 3310: - Ability to ‘search’ for a part while in a WO or PM -https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/3358 - -UI:WORKORDER:CR: - Have a search box for clients instead of having to use the slider to find a client -https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/3376 - -SEARCH:UI:GENERAL: - Be able to search from anywhere in any screen -https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/3459 - -SEARCH:WORKORDER:PO:QUOTE:PM: - Workorder and other numbered items need to be searchable by their number -https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/3506 - - - -REQUIREMENTS - -- USE-CASE: Central text search for any match. Can include tags. Can specify a type of object result desired. - -- MINIMUM 2 character words only are searchable -- MAXIMUM 255 character words only are indexed (cut off at 255 if longer) - -- ? USE-CASE: In-object text search for the typeandid that user is in, e.g. when in Client info form can search on that client. - - This is problematic because it seems to require searching for related objects but that's deprecated to priority 2 - - Maybe more ideally is a search that can be something like "search all workorders FOR THIS CLIENT" or search all units "FOR THIS CLIENT" - - UPDATE: For the above this is really a feature specific to this object, not a general search issue so not part of search at all - -- USE-CASE: Picklist / chooser Search for text of a specific type of object, e.g. find all Clients that contain "squirrel" to drive picklists everywhere -- USE-CASE: No snippet (excerpts) just name and type. I think for the initial release I'm *not* going to include snippets with result for several reasons: - - Performance: better to get an immediate result than to wait a while to get excerpts that - - Bandwidth: will trigger a lot of probably unneeded Bandwidth and chew up cycles on the db and server - - Can be added later based on feedback (i.e. a lot of bitching) - - For performance it would be something that runs *after* the search results are returned, either on demand (user clicks on excert button, or slowly fills in the list async) - -- NAME: in search index include a bool indicating the word is actually part of the name or equivalent of the object, this will make name searches WAAAAYYY easier!!! - - in non named objects it's whatever the primary identifier is, i.e. workorder number for a workorder, partb number for a part - - Maybe all objects should have a "name" column in db be it a workorder number or part number just for consistency - - RIGHTS: if a search is performed that is not NAME ONLY then the user role must have rights to read the full object even if the results are found in the name as this simplifies things greatly -- TAGS: Any search, anywhere, can include tags (internally it will post filter on tags after initial text search or if no text then will just search tags) - -- ROLES: Needs to internally be able to filter by CANREAD property of role user is in (e.g. if no rights to read client no clients returned) -- INDEX VISIBLE ID NUMBERS MUST be searchable so ensure they get put into text search with the regular text. -- OBJECT TYPE criteria support (AyaType must be included in search index) - -- CLIENT_NOT_SERVER_REQUIREMENT: PARENT / OPENABLE OBJECT: Objects that are searchable but not openable directly will be handled by the client - - Maybe this is a client concern, not a backend concern as pre-finding all the parents at the backend for the results is slower than - dynamically pulling it for one being opened from the client - - This is in the object, not in the searchkey as it would be inefficient - - Maybe need parent AyaType as an ENUM ATTRIBUTE in the AyaType table for easy traversal? - -- CLEANUP: Generator able to cleanup index with no matching word (if possible), index with no matching typeandid -- CJK INDEX support: same as v7 but tied to Locale, not globally -- GROUP BY: group by objectype then objectid (then created date?) -- Coding: break this into separate discrete classes, the old v7 code is very monolithic and in-elegant - -//TODO: -- INDEXES: play with it and see what works best - - - -PROPOSED SCHEMA -asearchdictionary - - id (long) - - word (nvarchar 255) (indexed?) - -asearchkey - - id (long) - - wordid (fk on asearchdictionary.id) - - objectid (long id of source object) - - aType (AyaType as int of source object) - - - - - -REFERENCE INFO - -V7 Code: -- Word breaker: AyaBizUtils -> Break starting at line 1976 -- Insert into db: DBUtil.cs -> ProcessKeywords starting at line 423 -- Usage: Client.cs line 2104 -- SearchResultList.cs (whole class, also there is an "ri" version for some reason I forget) -- V7 DB Schema: - -CREATE TABLE [dbo].[ASEARCHDICTIONARY]( - [AID] [uniqueidentifier] NOT NULL, - [AWORD] [nvarchar](255) NOT NULL -) ON [PRIMARY] - - -CREATE TABLE [dbo].[ASEARCHKEY]( - [AWORDID] [uniqueidentifier] NOT NULL, - [ASOURCEOBJECTID] [uniqueidentifier] NOT NULL, - [ASOURCEOBJECTTYPE] [smallint] NOT NULL -) ON [PRIMARY] - +SEARCH SPECS + + + +CASES + +SEARCH:NEW: - Search dictionary: Auto remove orphaned words +https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/1878 + +WORKORDER:PARTS:SEARCH:CR:DUPLICATE 3358: - Parts Search on Parts Grid +https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/3310 + +WORKORDER:PARTS:SEARCH:CR:DUPLICATE 3310: - Ability to ‘search’ for a part while in a WO or PM +https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/3358 + +UI:WORKORDER:CR: - Have a search box for clients instead of having to use the slider to find a client +https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/3376 + +SEARCH:UI:GENERAL: - Be able to search from anywhere in any screen +https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/3459 + +SEARCH:WORKORDER:PO:QUOTE:PM: - Workorder and other numbered items need to be searchable by their number +https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/3506 + + + +REQUIREMENTS + +- USE-CASE: Central text search for any match. Can include tags. Can specify a type of object result desired. + +- MINIMUM 2 character words only are searchable +- MAXIMUM 255 character words only are indexed (cut off at 255 if longer) + +- ? USE-CASE: In-object text search for the typeandid that user is in, e.g. when in Client info form can search on that client. + - This is problematic because it seems to require searching for related objects but that's deprecated to priority 2 + - Maybe more ideally is a search that can be something like "search all workorders FOR THIS CLIENT" or search all units "FOR THIS CLIENT" + - UPDATE: For the above this is really a feature specific to this object, not a general search issue so not part of search at all + +- USE-CASE: Picklist / chooser Search for text of a specific type of object, e.g. find all Clients that contain "squirrel" to drive picklists everywhere +- USE-CASE: No snippet (excerpts) just name and type. I think for the initial release I'm *not* going to include snippets with result for several reasons: + - Performance: better to get an immediate result than to wait a while to get excerpts that + - Bandwidth: will trigger a lot of probably unneeded Bandwidth and chew up cycles on the db and server + - Can be added later based on feedback (i.e. a lot of bitching) + - For performance it would be something that runs *after* the search results are returned, either on demand (user clicks on excert button, or slowly fills in the list async) + +- NAME: in search index include a bool indicating the word is actually part of the name or equivalent of the object, this will make name searches WAAAAYYY easier!!! + - in non named objects it's whatever the primary identifier is, i.e. workorder number for a workorder, partb number for a part + - Maybe all objects should have a "name" column in db be it a workorder number or part number just for consistency + - RIGHTS: if a search is performed that is not NAME ONLY then the user role must have rights to read the full object even if the results are found in the name as this simplifies things greatly +- TAGS: Any search, anywhere, can include tags (internally it will post filter on tags after initial text search or if no text then will just search tags) + +- ROLES: Needs to internally be able to filter by CANREAD property of role user is in (e.g. if no rights to read client no clients returned) +- INDEX VISIBLE ID NUMBERS MUST be searchable so ensure they get put into text search with the regular text. +- OBJECT TYPE criteria support (AyaType must be included in search index) + +- CLIENT_NOT_SERVER_REQUIREMENT: PARENT / OPENABLE OBJECT: Objects that are searchable but not openable directly will be handled by the client + - Maybe this is a client concern, not a backend concern as pre-finding all the parents at the backend for the results is slower than + dynamically pulling it for one being opened from the client + - This is in the object, not in the searchkey as it would be inefficient + - Maybe need parent AyaType as an ENUM ATTRIBUTE in the AyaType table for easy traversal? + +- CLEANUP: Generator able to cleanup index with no matching word (if possible), index with no matching typeandid +- CJK INDEX support: same as v7 but tied to Locale, not globally +- GROUP BY: group by objectype then objectid (then created date?) +- Coding: break this into separate discrete classes, the old v7 code is very monolithic and in-elegant + +//TODO: +- INDEXES: play with it and see what works best + + + +PROPOSED SCHEMA +asearchdictionary + - id (long) + - word (nvarchar 255) (indexed?) + +asearchkey + - id (long) + - wordid (fk on asearchdictionary.id) + - objectid (long id of source object) + - aType (AyaType as int of source object) + + + + + +REFERENCE INFO + +V7 Code: +- Word breaker: AyaBizUtils -> Break starting at line 1976 +- Insert into db: DBUtil.cs -> ProcessKeywords starting at line 423 +- Usage: Client.cs line 2104 +- SearchResultList.cs (whole class, also there is an "ri" version for some reason I forget) +- V7 DB Schema: + +CREATE TABLE [dbo].[ASEARCHDICTIONARY]( + [AID] [uniqueidentifier] NOT NULL, + [AWORD] [nvarchar](255) NOT NULL +) ON [PRIMARY] + + +CREATE TABLE [dbo].[ASEARCHKEY]( + [AWORDID] [uniqueidentifier] NOT NULL, + [ASOURCEOBJECTID] [uniqueidentifier] NOT NULL, + [ASOURCEOBJECTTYPE] [smallint] NOT NULL +) ON [PRIMARY] + diff --git a/devdocs/specs/core-seeds.txt b/devdocs/old-devdocs/specs/core-seeds.txt similarity index 91% rename from devdocs/specs/core-seeds.txt rename to devdocs/old-devdocs/specs/core-seeds.txt index b35486b5..767636fc 100644 --- a/devdocs/specs/core-seeds.txt +++ b/devdocs/old-devdocs/specs/core-seeds.txt @@ -1,6 +1,6 @@ -SEEDS -EXPORT READY (DATA DUMP CODED) - -REQUIREMENTS -See case 3544 - +SEEDS +EXPORT READY (DATA DUMP CODED) + +REQUIREMENTS +See case 3544 + diff --git a/devdocs/specs/core-server-state.txt b/devdocs/old-devdocs/specs/core-server-state.txt similarity index 97% rename from devdocs/specs/core-server-state.txt rename to devdocs/old-devdocs/specs/core-server-state.txt index 15fc592e..2cc7e7be 100644 --- a/devdocs/specs/core-server-state.txt +++ b/devdocs/old-devdocs/specs/core-server-state.txt @@ -1,39 +1,39 @@ -SERVER STATE SPECS - -REQUIREMENTS - - -LATEST: - -2020-04-05 - Decided to allow all non biz object routes that are required for running client like formcustom etc to be open unless server is fully closed - ops forms may need all that stuff - will not allow to update things like formcustom though, only to get them - any biz objects not ops are fully locked down though, so no getting a widget if the server is closed or opsonly - however you can get a widgetlist because picklist is open when opsonly as there is a probability that some things might be needed for ops - -OLD STUFF: - - -Two parallel paths that can lead to serverstate affecting access to server: - -Closed or Open States - - If closed all routes are shut to all users with case by case exceptions: - - OPS type user exceptions: - - Login - - View long running jobs because server may be closed due to long running process they need to view for status updates - - they can fetch a license key or look at license current state (ONLY IF CLOSED DUE TO LICENSE ISSUE) - - View METRICS and log files - - -- SYSTEM_LOCK - - An independent setting outside of the regular server state that allows RAVEN to internally lock itself when License or lockout related issues like non-payment - - Acts as though the server was set to CLOSED so OPS can still go in but doesn't matter what state they set it to because the locked is a parallel in memory internal only setting - - All non-ops routes will need to see if closed and server state returns closed both if serverstate is closed or if SYSTEM_LOCK - - -Some scenarios at the server require general users to be LOCKED OUT COMPLETELY but still grant limited access for operations administration, such as: - - Biz changes that need all users out such as a re-org of client data or something else business related - - Ops changes that need all users out such as upgrades, backup, restore, any mass data change such as import or export - - Emergency security issues such as hacking attempt etc - +SERVER STATE SPECS + +REQUIREMENTS + + +LATEST: + +2020-04-05 - Decided to allow all non biz object routes that are required for running client like formcustom etc to be open unless server is fully closed + ops forms may need all that stuff + will not allow to update things like formcustom though, only to get them + any biz objects not ops are fully locked down though, so no getting a widget if the server is closed or opsonly + however you can get a widgetlist because picklist is open when opsonly as there is a probability that some things might be needed for ops + +OLD STUFF: + + +Two parallel paths that can lead to serverstate affecting access to server: + +Closed or Open States + - If closed all routes are shut to all users with case by case exceptions: + - OPS type user exceptions: + - Login + - View long running jobs because server may be closed due to long running process they need to view for status updates + - they can fetch a license key or look at license current state (ONLY IF CLOSED DUE TO LICENSE ISSUE) + - View METRICS and log files + + +- SYSTEM_LOCK + - An independent setting outside of the regular server state that allows RAVEN to internally lock itself when License or lockout related issues like non-payment + - Acts as though the server was set to CLOSED so OPS can still go in but doesn't matter what state they set it to because the locked is a parallel in memory internal only setting + - All non-ops routes will need to see if closed and server state returns closed both if serverstate is closed or if SYSTEM_LOCK + + +Some scenarios at the server require general users to be LOCKED OUT COMPLETELY but still grant limited access for operations administration, such as: + - Biz changes that need all users out such as a re-org of client data or something else business related + - Ops changes that need all users out such as upgrades, backup, restore, any mass data change such as import or export + - Emergency security issues such as hacking attempt etc + Need a method to inform users that server *WILL* be going down within a set time frame, like 15 minutes (no need to get fancy and make it configurable) \ No newline at end of file diff --git a/devdocs/specs/core-tags.txt b/devdocs/old-devdocs/specs/core-tags.txt similarity index 97% rename from devdocs/specs/core-tags.txt rename to devdocs/old-devdocs/specs/core-tags.txt index 04f937ee..6f4bebe4 100644 --- a/devdocs/specs/core-tags.txt +++ b/devdocs/old-devdocs/specs/core-tags.txt @@ -1,92 +1,92 @@ -# TAGS specifications - -Main case is 3373 https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/3373 - - -RESEARCH: -https://www.databasesoup.com/2015/01/tag-all-things.html -https://www.npgsql.org/efcore/mapping/array.html -https://www.postgresql.org/docs/current/arrays.html - - -2018-12-05 Research showed that actually I'm doing tags all wrong and the multi table method is not correct performance wise or simplicity wise -The winning method in a test using postgres was a text array of tags with a "gin" index see databasesoup link above. - - - -FORMAT -=-=-=- -Copied from stack overflow -tags ... - - must be no longer than 255 characters (35 in Stack overflow, but why limit it?) - spaces are replaced by dashes, no spaces in a tag - always converts to lower invariant culture - - (probably not this, utf-8 ok: must use the ascii character set a-z 0-9 + # - .) - -SCHEMA - -USE-CASES -Add a tag to an object type and id, start typing and a selection list fills in to select from - - Don't allow the same tag more than once - - Create a tag if not present (rights?) -Show tags on an object -Find any type or specific type items by a set of tags (and/or tag groups) to include and a set of tags to exclude (i.e. has "red, yellow" but not "green") -Search for text must allow specifying tags (and/or tag groups) to refine -Reporting will require filtering sources of report data by tags (and/or tag groups) - -METHODS REQUIRED IN TAG CONTROLLER - -- GET tag text by id -- GET tag id by tag text -- CREATE tag for tagging something -- REMOVE tag (and all tagmap entities) - - -- GET TAGMAPS LIST (get all object/id entities with this tag) -- CREATE TAGMAP Apply tag to an object / id -- REMOVE TAGMAP remove tag from object/id -- GET TAGS for object (name id list, main display route) - - -ROLES / RIGHTS -- Limited roles can tag stuff and remove tags as per their rights to the object type in question but can't make new tags or change existing tags -- Full roles can make new tags and can edit or delete existing tags - - -RETRIEVAL - -Will need to query tags as follows: - -AType and Id list of tags (most common) -Objects with one or more tags -Objects that have a set of tags but do not have another set of tags -Objects of a certain type but any id that have a certain tag - -V7IMPORT -See case 3373 for a list of things that will become tags - - -OLD DEPRECATED STUFF BELOW HERE -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - -TAG GROUP DEPRECATED 2018-12-05 - I'm deprecating this as it's surplus to requirements: users will be able to specify multiple tags in a filter and they can save filters so no need for bags of tags - - TAG-GROUP - bag of tags - Modify the below and coded and tests and tables to now have feature for tag groups - They will be in their own table with a dictionary table of tag ids and tag group id's to link - They are used for read purposes, you never tag an item with a tag group, only query by group. - If a group is deleted tags it contains are NOT deleted or changed - If a tag is deleted it must be removed from any tag groups and if there are no other items in that tag group then the tag group must be deleted as well?? - - Or maybe is just an empty group with a warning symbol in ui - Tag groups will become a major way to save filters for things because a lot of filtering will be by tags so this should be a solid feature. - - RETRIEVAL / LISTS: need to modify the tag list to optionally return TAGGROUP names as well as identify they are group so UI can feature differently - - FILTERING AND SORTING BY TAG-GROUP - - All code that filters and sorts by tag should accept a tag group as a separate type of input and dynamically build the tag filter list from the group and individual tags separately - rather than storing a list of tags at the moment a group is applied. - In this way the filters are always dynamically linked to the tags in the group and reflect the most recent changes to the group - tl/dr: don't store the tag id's from a group in the filter, store the group id separately and build the list on query - +# TAGS specifications + +Main case is 3373 https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/3373 + + +RESEARCH: +https://www.databasesoup.com/2015/01/tag-all-things.html +https://www.npgsql.org/efcore/mapping/array.html +https://www.postgresql.org/docs/current/arrays.html + + +2018-12-05 Research showed that actually I'm doing tags all wrong and the multi table method is not correct performance wise or simplicity wise +The winning method in a test using postgres was a text array of tags with a "gin" index see databasesoup link above. + + + +FORMAT +=-=-=- +Copied from stack overflow +tags ... + + must be no longer than 255 characters (35 in Stack overflow, but why limit it?) + spaces are replaced by dashes, no spaces in a tag + always converts to lower invariant culture + - (probably not this, utf-8 ok: must use the ascii character set a-z 0-9 + # - .) + +SCHEMA + +USE-CASES +Add a tag to an object type and id, start typing and a selection list fills in to select from + - Don't allow the same tag more than once + - Create a tag if not present (rights?) +Show tags on an object +Find any type or specific type items by a set of tags (and/or tag groups) to include and a set of tags to exclude (i.e. has "red, yellow" but not "green") +Search for text must allow specifying tags (and/or tag groups) to refine +Reporting will require filtering sources of report data by tags (and/or tag groups) + +METHODS REQUIRED IN TAG CONTROLLER + +- GET tag text by id +- GET tag id by tag text +- CREATE tag for tagging something +- REMOVE tag (and all tagmap entities) + + +- GET TAGMAPS LIST (get all object/id entities with this tag) +- CREATE TAGMAP Apply tag to an object / id +- REMOVE TAGMAP remove tag from object/id +- GET TAGS for object (name id list, main display route) + + +ROLES / RIGHTS +- Limited roles can tag stuff and remove tags as per their rights to the object type in question but can't make new tags or change existing tags +- Full roles can make new tags and can edit or delete existing tags + + +RETRIEVAL + +Will need to query tags as follows: + +AType and Id list of tags (most common) +Objects with one or more tags +Objects that have a set of tags but do not have another set of tags +Objects of a certain type but any id that have a certain tag + +V7IMPORT +See case 3373 for a list of things that will become tags + + +OLD DEPRECATED STUFF BELOW HERE +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + +TAG GROUP DEPRECATED 2018-12-05 + I'm deprecating this as it's surplus to requirements: users will be able to specify multiple tags in a filter and they can save filters so no need for bags of tags + + TAG-GROUP - bag of tags + Modify the below and coded and tests and tables to now have feature for tag groups + They will be in their own table with a dictionary table of tag ids and tag group id's to link + They are used for read purposes, you never tag an item with a tag group, only query by group. + If a group is deleted tags it contains are NOT deleted or changed + If a tag is deleted it must be removed from any tag groups and if there are no other items in that tag group then the tag group must be deleted as well?? + - Or maybe is just an empty group with a warning symbol in ui + Tag groups will become a major way to save filters for things because a lot of filtering will be by tags so this should be a solid feature. + - RETRIEVAL / LISTS: need to modify the tag list to optionally return TAGGROUP names as well as identify they are group so UI can feature differently + + FILTERING AND SORTING BY TAG-GROUP + - All code that filters and sorts by tag should accept a tag group as a separate type of input and dynamically build the tag filter list from the group and individual tags separately + rather than storing a list of tags at the moment a group is applied. + In this way the filters are always dynamically linked to the tags in the group and reflect the most recent changes to the group + tl/dr: don't store the tag id's from a group in the filter, store the group id separately and build the list on query + \ No newline at end of file diff --git a/devdocs/specs/core-testing.txt b/devdocs/old-devdocs/specs/core-testing.txt similarity index 100% rename from devdocs/specs/core-testing.txt rename to devdocs/old-devdocs/specs/core-testing.txt diff --git a/devdocs/specs/core-translation.txt b/devdocs/old-devdocs/specs/core-translation.txt similarity index 98% rename from devdocs/specs/core-translation.txt rename to devdocs/old-devdocs/specs/core-translation.txt index 307833fa..437f8174 100644 --- a/devdocs/specs/core-translation.txt +++ b/devdocs/old-devdocs/specs/core-translation.txt @@ -1,103 +1,103 @@ -# Translation specifications - - -REQUIREMENTS - - ROLE RIGHTS: BizAdminFull only can edit. BizAdminLimited can view but not change - - CENTRAL translation EDIT FORM - - End user customizes Translations from a central location with a kick ass search and change ability - - We will *not* support Translation changes form by form as in v7 but only from central location - - Faster to code TTM - - User doesn't think they are only changing it on one form only - - Some forms don't have all the related keys on them (i.e. a list will show "Widgets" even though the edit form never shows that string) - - Client handles *ALL* Translation presentation locally, only exception is the server ops logs - - This saves bandwidth and hassle and leaves presentation to the client where it belongs (was a source of trouble in v7) - - Keys are text, human readable and as short as possible - - Not numeric ID's for these, strictly textual - - values may have substitution tokens in them for certain things - - DataDump plugin will export and import any custom translations that did not come with AyaNova 7 - - Dump needs to check if the "stock" translation has been edited or not before exporting - - Only edited ones are exported - - For example if someone edited the Spanish translation then it would dump as "Spanish-Custom" (or whatever the word for custom is in that language) so as not to interfere with our stock Built in Spanish in Raven - - The documented renaming (below) will need to be automated during import of v7 stock translations to migrate to the new key values - - Two kinds of translations: Stock and Custom. - - Stock translations are stored in db and not user editable - - STock translation names are whatever the international name for that translation is like "esp" or "fr" etc - - Custom translations are stored in the database and are user customizable - - ROUTES - - GET ROUTE that provides a pick list of translations - - - GET ROUTE that returns all key value pairs when requested for a specific translation - - This one is for editing purposes or for export to disk - - - GET ROUTE that returns a list of specific key value pairs for a requested translation and specific list of translation keys provided - - This one is for day to day ops and will be called on any client opening a new area of UI they have not previously opened - - - PUT ROUTE that accepts a list of key value pairs and a specific translation and updates the current values in db from the provided list - - if translation name key provided is one of our stock ones then it errors out as you can't change the stock translations - - if translation doesn't exist in db errors out - - biz full rights only - - - POST ROUTE that creates a new translation duplicated from an existing translation and copies all the values from the existing translation - - Post object {sourcetranslation:"English", newtranslation:"Mytranslation"} - - Errors if already exists with that name - - Sets it to stock=false so it can be edited - - This is also how you rename a translation - - - DELETE ROUTE for deleting any non-stock translation - - Can't delete current DB default translation (specfic error) - - Users of that translation will be reset to current DB default translation - - - - -CHANGES MADE TO KEYS FROM v7 - - - Replaced all [.Label.] with [.] - - Replaced all ["O.] with ["] this needs to be a case sensitive change!!! -- Removed duplicate key [WorkorderService.CloseByDate] that resulted from last change of O. (the first one between workorderservice and workorderstatus) - - Replaced all [.ToolBar.] with [.] - - Replaced all [.Toolbar.] with [.] - - Replaced all [.Go.] with [.] - - Replaced all [.Command.] with [.] -- Removed duplicate key created by last operation: [UI.Search] (removed second longer one that refers to database) - - Replaced all [.Error.] with [.] - - Replaced all [.Object.] with [.] - - Replaced all ["UI.] with ["] (and removed exact dupe keys created as a result) - - Replaced all [.] with [] -- Removed dupe WorkOrderItemOutsideService (removed the one with the longest value) - - Replaced all ["AddressAddress"] with ["Address"] - - Replaced all ["ContactPhoneContactPhone"] with ["ContactPhone"] - - Replaced all ["ContactPhonePhone"] with ["ContactPhone"] - - Replaced all ["PurchaseOrderPurchaseOrder"] with ["PurchaseOrder"] - - Replaced all ["WorkOrderItemMiscExpenseExpense"] with ["WorkOrderItemMiscExpense"] - - Replaced all ["WorkOrderItemTravelTravel"] with ["WorkOrderItemTravel"] - -Note: still some dupes but...fuck it - - - - -- TODO: Some of the keys are new and not translated from English, when all is done and the keys that will be carried forward are determined, check for untranslated ones - - Use Google translate to get a rough approximation. - - A technique to get a good translation would be to try various synonyms out and try to zero in on the commonality in translation to ensure a word is not being completely misunderstood to get a better translation - - I.E. if different forms of the phrase result in similar words in the other language then it's probably Gucci - - -CLIENT - - Client fetches localized text on an as required basis form by form and caches it locally until cache is invalidated - - Cache invalidated by either a timeout or possibly receiving a message from the server. - - Open an edit form - - client checks local cache (do I have the values for the list of required keys??) - - YES: just use it - - NO: Send a list of keys to the server along with the user id that are required for this form and get back the LT, put it in the cache - - User id required because someone might edit their translation or the translation name and so it needs to check via the user account what the translation is - -This way there is no wasted space at the client caching stuff that will never be used - -CHANGES: - - If the text is changed at the server then a notification should occur for clients using that local to invalidate their cache - - Although, that would be a pretty rare event so...maybe not so much, a logout could clear the cache or a login I guess - - - +# Translation specifications + + +REQUIREMENTS + - ROLE RIGHTS: BizAdminFull only can edit. BizAdminLimited can view but not change + - CENTRAL translation EDIT FORM + - End user customizes Translations from a central location with a kick ass search and change ability + - We will *not* support Translation changes form by form as in v7 but only from central location + - Faster to code TTM + - User doesn't think they are only changing it on one form only + - Some forms don't have all the related keys on them (i.e. a list will show "Widgets" even though the edit form never shows that string) + - Client handles *ALL* Translation presentation locally, only exception is the server ops logs + - This saves bandwidth and hassle and leaves presentation to the client where it belongs (was a source of trouble in v7) + - Keys are text, human readable and as short as possible + - Not numeric ID's for these, strictly textual + - values may have substitution tokens in them for certain things + - DataDump plugin will export and import any custom translations that did not come with AyaNova 7 + - Dump needs to check if the "stock" translation has been edited or not before exporting + - Only edited ones are exported + - For example if someone edited the Spanish translation then it would dump as "Spanish-Custom" (or whatever the word for custom is in that language) so as not to interfere with our stock Built in Spanish in Raven + - The documented renaming (below) will need to be automated during import of v7 stock translations to migrate to the new key values + - Two kinds of translations: Stock and Custom. + - Stock translations are stored in db and not user editable + - STock translation names are whatever the international name for that translation is like "esp" or "fr" etc + - Custom translations are stored in the database and are user customizable + + ROUTES + - GET ROUTE that provides a pick list of translations + + - GET ROUTE that returns all key value pairs when requested for a specific translation + - This one is for editing purposes or for export to disk + + - GET ROUTE that returns a list of specific key value pairs for a requested translation and specific list of translation keys provided + - This one is for day to day ops and will be called on any client opening a new area of UI they have not previously opened + + - PUT ROUTE that accepts a list of key value pairs and a specific translation and updates the current values in db from the provided list + - if translation name key provided is one of our stock ones then it errors out as you can't change the stock translations + - if translation doesn't exist in db errors out + - biz full rights only + + - POST ROUTE that creates a new translation duplicated from an existing translation and copies all the values from the existing translation + - Post object {sourcetranslation:"English", newtranslation:"Mytranslation"} + - Errors if already exists with that name + - Sets it to stock=false so it can be edited + - This is also how you rename a translation + + - DELETE ROUTE for deleting any non-stock translation + - Can't delete current DB default translation (specfic error) + - Users of that translation will be reset to current DB default translation + + + + +CHANGES MADE TO KEYS FROM v7 + + - Replaced all [.Label.] with [.] + - Replaced all ["O.] with ["] this needs to be a case sensitive change!!! +- Removed duplicate key [WorkorderService.CloseByDate] that resulted from last change of O. (the first one between workorderservice and workorderstatus) + - Replaced all [.ToolBar.] with [.] + - Replaced all [.Toolbar.] with [.] + - Replaced all [.Go.] with [.] + - Replaced all [.Command.] with [.] +- Removed duplicate key created by last operation: [UI.Search] (removed second longer one that refers to database) + - Replaced all [.Error.] with [.] + - Replaced all [.Object.] with [.] + - Replaced all ["UI.] with ["] (and removed exact dupe keys created as a result) + - Replaced all [.] with [] +- Removed dupe WorkOrderItemOutsideService (removed the one with the longest value) + - Replaced all ["AddressAddress"] with ["Address"] + - Replaced all ["ContactPhoneContactPhone"] with ["ContactPhone"] + - Replaced all ["ContactPhonePhone"] with ["ContactPhone"] + - Replaced all ["PurchaseOrderPurchaseOrder"] with ["PurchaseOrder"] + - Replaced all ["WorkOrderItemMiscExpenseExpense"] with ["WorkOrderItemMiscExpense"] + - Replaced all ["WorkOrderItemTravelTravel"] with ["WorkOrderItemTravel"] + +Note: still some dupes but...fuck it + + + + +- TODO: Some of the keys are new and not translated from English, when all is done and the keys that will be carried forward are determined, check for untranslated ones + - Use Google translate to get a rough approximation. + - A technique to get a good translation would be to try various synonyms out and try to zero in on the commonality in translation to ensure a word is not being completely misunderstood to get a better translation + - I.E. if different forms of the phrase result in similar words in the other language then it's probably Gucci + + +CLIENT + - Client fetches localized text on an as required basis form by form and caches it locally until cache is invalidated + - Cache invalidated by either a timeout or possibly receiving a message from the server. + - Open an edit form + - client checks local cache (do I have the values for the list of required keys??) + - YES: just use it + - NO: Send a list of keys to the server along with the user id that are required for this form and get back the LT, put it in the cache + - User id required because someone might edit their translation or the translation name and so it needs to check via the user account what the translation is + +This way there is no wasted space at the client caching stuff that will never be used + +CHANGES: + - If the text is changed at the server then a notification should occur for clients using that local to invalidate their cache + - Although, that would be a pretty rare event so...maybe not so much, a logout could clear the cache or a login I guess + + + diff --git a/devdocs/specs/core-trial-evaluation-system.txt b/devdocs/old-devdocs/specs/core-trial-evaluation-system.txt similarity index 98% rename from devdocs/specs/core-trial-evaluation-system.txt rename to devdocs/old-devdocs/specs/core-trial-evaluation-system.txt index d2b1e6dd..96125867 100644 --- a/devdocs/specs/core-trial-evaluation-system.txt +++ b/devdocs/old-devdocs/specs/core-trial-evaluation-system.txt @@ -1,36 +1,36 @@ -Trial and acquire features - -Raven will no longer be a download and try anonymously application. -There are only two ways for a non customer to trial: immediately online or self host. Both methods require the user to register to trial and the key will be automatically fulfilled. -In no case will a user be able to install a trial key without the database being erased to prevent serial trial scamming. - -LICENSED CUSTOMER ADD-ON TRIAL -Users that are already licensed and just want to try out a feature will get a normal licensed key with the feature licensed as normal but with short expiry like 30 days. -Once the feature licensed expires it's not offered in the UI anymore (or it says "A license is required to use this feature") -This way we do not need to replace the key again with a non-licensed version of the trialed add-on. - -PROSPECT ONLINE FULL TRIAL -Anyone visiting our website who is a prospective customer will be able to trial AyaNova immediately by filling out a form after which a new AyaNova will be spun up with a fixed time limit with full license registered to them but as a trial. -Inside the trial they will be able to seed data for various scenarios at will -They can purchase at any time and we will activate it into the online version already set up so they can just start working -When the time limit expires plus let's say another month the database will be automatically erased and server spun down (container deleted from docker?) - - -PROSPECT SELF HOST FULL TRIAL - -When a prospect user wants to trial self host, they will be able to download and install and it will start in unlicensed mode where they can verify it's installed and ready but there is no license so it won't allow normal ops, -The only options will be to confirm it's working properly and to request a trial key which will be sent to Rockfish automatically, generate a key automatically and install automatically. -When a trial key is first installed the database is automatically erased thus preventing them from just endlesssly requestion trial keys to keep using it for free -user can during trial pick different seed data for various scenarios at will -They can install a fully registered key at any time by purchasing from within AyaNova (at first may need to be via current shareit system) - - -FEATURES REQUIRED TO SUPPORT THIS - -- We need a management console to view the load on our server and to alert us to slowdowns so we can expand the virtual server, also we need to be able to do it in more than one datacenter as we would want local endpoints for users ultimately -- RockFish or some other application needs to be able to spin up a new server and db combo that is unique (docker container?) automatically and prune or get rid of it completely after XX days after trial has expired and it is still unlicensed -- Rockfish automatic trial key fulfillment and delivery and installation -- RAVEN built in form to request trial key and automatic fulfillment and install including db is erased any time a trial key is installed when a user already has a trial or no key installed -- RAVEN built in purchase feature - - +Trial and acquire features + +Raven will no longer be a download and try anonymously application. +There are only two ways for a non customer to trial: immediately online or self host. Both methods require the user to register to trial and the key will be automatically fulfilled. +In no case will a user be able to install a trial key without the database being erased to prevent serial trial scamming. + +LICENSED CUSTOMER ADD-ON TRIAL +Users that are already licensed and just want to try out a feature will get a normal licensed key with the feature licensed as normal but with short expiry like 30 days. +Once the feature licensed expires it's not offered in the UI anymore (or it says "A license is required to use this feature") +This way we do not need to replace the key again with a non-licensed version of the trialed add-on. + +PROSPECT ONLINE FULL TRIAL +Anyone visiting our website who is a prospective customer will be able to trial AyaNova immediately by filling out a form after which a new AyaNova will be spun up with a fixed time limit with full license registered to them but as a trial. +Inside the trial they will be able to seed data for various scenarios at will +They can purchase at any time and we will activate it into the online version already set up so they can just start working +When the time limit expires plus let's say another month the database will be automatically erased and server spun down (container deleted from docker?) + + +PROSPECT SELF HOST FULL TRIAL + +When a prospect user wants to trial self host, they will be able to download and install and it will start in unlicensed mode where they can verify it's installed and ready but there is no license so it won't allow normal ops, +The only options will be to confirm it's working properly and to request a trial key which will be sent to Rockfish automatically, generate a key automatically and install automatically. +When a trial key is first installed the database is automatically erased thus preventing them from just endlesssly requestion trial keys to keep using it for free +user can during trial pick different seed data for various scenarios at will +They can install a fully registered key at any time by purchasing from within AyaNova (at first may need to be via current shareit system) + + +FEATURES REQUIRED TO SUPPORT THIS + +- We need a management console to view the load on our server and to alert us to slowdowns so we can expand the virtual server, also we need to be able to do it in more than one datacenter as we would want local endpoints for users ultimately +- RockFish or some other application needs to be able to spin up a new server and db combo that is unique (docker container?) automatically and prune or get rid of it completely after XX days after trial has expired and it is still unlicensed +- Rockfish automatic trial key fulfillment and delivery and installation +- RAVEN built in form to request trial key and automatic fulfillment and install including db is erased any time a trial key is installed when a user already has a trial or no key installed +- RAVEN built in purchase feature + + diff --git a/devdocs/specs/core-ui-design.txt b/devdocs/old-devdocs/specs/core-ui-design.txt similarity index 97% rename from devdocs/specs/core-ui-design.txt rename to devdocs/old-devdocs/specs/core-ui-design.txt index b6723964..02b1c9ce 100644 --- a/devdocs/specs/core-ui-design.txt +++ b/devdocs/old-devdocs/specs/core-ui-design.txt @@ -1,432 +1,432 @@ -UI DESIGN DOC - -Requirements - - Responsive but favoring larger screens primarily - - Smaller screens will be able to do everything but the layout is not the primary one - - Service techs have an ipad or notebook - - Anticipate a list of things each role needs immediately in front of them and try for that - - componentized UI elements so can re-use and mix and even support customizing with user defined layout - - So for example a customer list is a self contained subset of a list widget and can be plunked down anywhere required - - This will save me time so identify the "types" of ui elements (picklist, filterable data list, entry form etc) - - Then can build specific versions of the types identified like a client list is a specialized filterable data list etc. - - If a list then it also knows which element is selected or a list of selected elements so other widgets can operate on it - - A menu or command widget that can be inserted into another widget, i.e. a part picker for a workorder part list widget or elsewhere a part is required - - This way I'm only making a few UI objects, not a new one for every single element. - - Kind of making the pallet first of all required objects then I can "paint" with them on to the UI without getting bogged down in minute details every time I make a form - - UI elements should be responsive and generic enough to work for many different use cases - - they should be rights aware and mode aware (editable, read only) enough to handle all that without recoding again and again - - the page or shell or whatever that holds the widgets should be end user customizable from a widget pallet. - - The more self contained the widget the more useful - - - Most people seem to prefer WBI over RI and the reason always seems to be RI is too simple or requires too many clicks - - So plan on the bigger screen layout being the main UI and smaller screen secondary - - I want things to be simpler and cleaner than it seems many people do so beware of that tendency - - People don't want to have to open sub screens any more than absolutely necessary - - Make sure a screen contains as much as possible to complete it on one screen - - Clean interface with good negative space but not dumbed down too much - - Pro-marketing style, stuff that makes it easier to sell - - emphasize simple fonts with good contrast - - Blue is a good colour, no purple or pastels - - DAshboard / customizable UI - - Ideally people can see as much detail as they want or remove unused ui widget elements - - So, for example on the dashboard they can customize by plunking down a client list widget, adding a "My workorders" widget for a tech - - or for a Ops person they can plunk down on their dashboard a current server status widget or active jobs widget etc - - - - RAVEN PROPOSED NAV PANEL - - - "HOME" (Current user specific stuff only) - - "OVERVIEW" (old "dashboard" not sure of the LT name but it's the old dashboard) of service if a tech or has access to tech related shit like current dashboard - - A customer had thoughts on the dashboard: - - case 1974: shootnsharp@thesoileaus.com "In my opinion, the dashboard would be much more functional and valuable if I could determine how many work orders show on the screen and possibly even what statuses (or be able to sort by status, priority, etc.) The At a Glance stats of Service Rate Quantity is helpful but would be even more relevant if it showed what was approaching due date, overdue, waiting on parts, pending parts requests, items on loan stats, preventative maintenance work orders approaching and overdue. Having the capability to customize the Dashboard is key because each Service business has its own metrics that are most important to its business." - - SCHEDULE (User's own schedule only if applicable, all users can have a schedule so it goes here) - - MEMOS (for user) - - SCHEDULE MARKERS (list for user, convenience extra so don't need to hunt around on calendar) - - SETTINGS - - User translation settings - - Any other user specific settings that the User can control (and sb able to control more than in v7 if it doesn't affect anyone else) - - Change login? - - notification subscriptions - - Notifciation deliveries - - CUSTOMERS - - CUSTOMERS (customers) - - HEAD OFFICES - - SERVICE - - WORKORDERS (was "service" in v7, now all "service" workorders are just workorders) - - ALL LEVELS - - NOTE: Either all levels still in menu at left here or somehow at right in separate boxes maybe, I like the idea of the in menu better with single right pane for simplicity - - TEMPLATES - - QUOTES - - See "Workorders" above same layout - - PREVENTIVE MAINTENANCE - - See "Workorders" above same layout - - UNITS - - UNIT MODELS - - CONTRACTS - - CUSTOMER SERVICE REQUESTS - - LOANERS (not 100% certain about this location for this item) - - SCHEDULE (all users not just current one) - - INVENTORY - - PARTS (part list) - - INVENTORY - - PART REQUESTS - - PURCHASE ORDERS - - PO ITEMS (WEIRD) - - PO RECEIPTS - - PO RECEIPT ITEMS (ALSO WEIRD) - - ADJUSTMENTS - - WIDGETS (for testing purposes) - - VENDORS - - single level, no subitems - - ACCOUNTING - - Any new accounting funcationlity (theres' some new workorder stuff for accting) - - All old plugin accounting integration stuff - - ADMINISTRATION - - GLOBAL SETTINGS - - LICENSE RELATED - - USERS - - LOCALIZED TEXT DESIGN - - REPORT TEMPLATES - - FILES IN DATABASE - - SCHEDULE MARKERS (DEPRECATED) (This shows *all* sm for all users, kind of weird, not documented at all, leaving it out) - - HISTORY (event log) view, filter, sort etc the whole thing here to see what activity is happening in general - - KPI WIDGETS AND GRAPHS AND SHIT FOR BIZ ADMIN - - OPERATIONS CONSOLE - - SERVER CONTROL? (close/open server ops? Or does that happen automatically when doing other jobs?) - - "ARCHIVE" (BACKUP /RESTORE) - - JOBS (view status of, trigger some maybe) - - SERVER LOGS - - METRICS - - NOTIFICATION CONFIG AND CHECK DELIVERIES - - - - [HOLDER] - [HOLDER] - ACTION - ACTION - ACTION - ACTION - ACTION - [HOLDER] - ACTION - - So top level can be a holder or an action - if holder then we are in second level - SECOND LEVEL - Can be a holder or an action - if Holder then we are in third level - Can only be an action - action - action - -FOR REFERENCE HERE IS THE v7 NAV panel LAYOUT: -- V7 nav panel is like this: - - DASHBOARD - - SERVICE - - All levels of workorders of this type - - Templates for workorders of this type - - QUOTES - - All levels of workorders of this type - - Templates for workorders of this type - - PREVENTIVE MAINTENANCE - - All levels of workorders of this type - - Templates for workorders of this type - - SCHEDULE - - INVENTORY - - parts - - po's - - po items (weird) - - po receipts - - po receipt items (also weird) - - adjustments - - adjustment items (strange) - - part inventory - - part requests - - CLIENTS (CUSTOMERS) - - clients (customers) - - head offices - - contracts - - projects - - customer service requests - - UNITS - - units - - unit models - - loan items - - VENDORS - - vendors - - CURRENT USER - - memos - - notification subscriptions - - notification deliveries - - wiki page (personal, wtf?) - - SEARCH - - ADMINISTRATION - - global settings - - regions - - security groups - - users - - custom field design - - localized text design - - notification deliveries (last 7 days) - - report templates - - files in database - - schedule markers (wtf forgot about this what's it for again?) - - - -=-=-=-=-=-= -This is a worked example to determine what UI elements should be where using the Client as the example object type: - -CLIENT OPS -=-=-=-=-=- - - list - - Select individually - - mass operations - - Delete - - Tag - - Import / Export / Integrate - - Notifications - - - Report / Graph - - - Search / Find quickly by typing in part of the name or something - - Filter - - Sort - - Set display number per page (sticky) - - Expand to full screen to show all the columns possible? - - Or...shows as many columns as possible automatically based on screen size available width - - - Single - - CRUD - - TAGS - - Duplicate - - Report / Graph - - Notifications settings - - Service BANK - - CSR - - - Show all - - Units - - Workorders - - Quotes - - PM - - CSR - - Service history feature for quickly seeing totals and dates (see case for deets) - - Export / Integrate - - Attachments - - Wiki - - Follow up / schedule - - Record history (should just show in main UI I think) - - Notes (separate collection, but maybe should be part of main edit ui) - - - - Contracts - - Projects - - =-=-=-=-=-=-=-=- - - - - -Graphics and themes for AyaNova - - No bitmap graphics, vector only!! - - For the manual and docs will use material theme with MKDOCS generator. - -ICON FONT - Going with Font Awesome 5.x SOLID FREE icons -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -- I'll choose the replacement fonts as I need them from the FontAwesome5 collection and document them here. -- https://fontawesome.com/icons?d=gallery&s=regular,solid&m=free - -- v7: - - v7 icons, all orangey brown in color with bits of highlight in each one of other colors. 3d in general - - Service Workorder (wrench and screwdriver) - - Workorder items (single wrench alone no screwdriver) - - Scheduled users (torso in front of calendar) - - Parts (3d cube) - - Labor (hammer) - - Travel (truck looks like loomis courier truck) - - Loans (plug from electrical cord for no apparent reason) - - Expenses (riffle of US dollar bills) - - Service templates (looks like rubber stamp) - - Quote (pen and paper) - - all subitems same as for service workorder - - PM (alarm clock and paper) - - all subitems same as for service workorder - - Schedule (looks like the schedule calendar screen but tiny and a bit cluttered) - - Inventory (3 shapes, pyramid, ball, cube in 3d effect) - - Parts (cube) - - PO items and PO receipts (both are kind of just documents, PO receipt is same but with a corner to corner orangey stripe across it that is indechipherable) - - Part requests (document like a po with a wrnch and hammer Service icon in front of it weirdly when it should be a cube I think) - - Clients (house icon with door and front mat) - - Headoffices (larger building, low rise apartment or office tower) - - Contracts (two hands shaking) - - Projects (some kind of closed book that looks like a dayplanner with colored tabs sticking out) - - Dashboard (speedometer / analog meter black dial, silver surround and lettering like from an old time auto dashboard) - - Units (cog which I don't like) - - Unit models (some kind of mechanical looking pentagram with a circular thing in the center, weird) - - Loan items (power plug for no apparent reason) - - Vendors (shopping basket handheld kind) - - Current user pane (hard hatted torso person) - - Memos (inbox looking thing) - - Notification subscriptions (loudhorn but not 3d, flat side view instead, looks more like a hatchet, man these old icons are fucked and confusing) - - Notification deliveries (loudhorn but smaller and on top of a sheet of paper) - - Wiki page (atomic diagram looking thing) - - Search (magnifying glass) - - Administration (torso with suit and set of keys superimposed) - - Global settings (planet right on the nose) - - Regions (pie chart with wedge extracted slightly) - - Security groups (keys) - - Users (hard hatted torso but front on and flat) - - Custom field ("Abc", probably the font chooser icon in most apps) - - Localized text design (address card) - - Notification deliveries (bull horn / hatchet and sheet of paper) - - Report templates (sheet of paper and small rubber stamp) - - Files in database (filing cabinet) - - Schedule markers (post it note with pin and folded up lower right corner) - - WIKI (atomic nucleus diagram / weird flower) - - GENERAL UI - - Delete (red circle with white X through it) - - OK / ACCEPT (Green circle with white checkmark through it) - - Cancel (orange circle with white "forbidden" bar across it diagonally from top right to lower left) - - Save (3.5'' diskette!?) - - Document attachments (two hardcover books back to back on an angle in 3d) - - Record history (analog clock face) - - Follow up "Review" (schedule marker post-it note with a chain link overtop of it) - - Print / report (inkjet printer) - - Duplicate (rabbit) - - Plugin (puzzle piece) - - Attach file [wiki] (file folder) - - Edit [wiki] (pencil) - - Reply [memo] (inbox used for memo with left facing green arrow superimposed) - - Forward [memo] (inbox used for memo with right facing green arrow superimposed) - - Recent [MRU on main menu] (binoculars) - - - - -LOGO - - Need to standardize on a logo and stick to it from now on - - Simple and clean (script AyaNova used for RI is maybe out) - - Single colour canucks blue with green contrast if absolutely necessary (don't make it necessary) - -COLOURS - - Canucks colours of course, Blue primary and green secondary. - /* =================== - AyaNova 8 Westcoast theme - Based on Canucks current colors - Primary colour = dark blue - Web: #00205B - RGB: 0, 32, 91 - - Secondary colour = green - Web: #00843D - RGB: 0, 132, 61 - * - * #00843D = Green -#00205B = Blue - private Color AyaGreen = System.Drawing.ColorTranslator.FromHtml("#00843D"); - private Color AyaBlue = System.Drawing.ColorTranslator.FromHtml("#00205B"); - =================== */ - - - No indigo or pastels ?? - - - Canucks colors in designer - - https://material.io/tools/color/#!/?view.left=1&view.right=0&primary.color=00205B&secondary.color=00843D - - Picker tool / generator of pallete: https://material.io/design/color/#tools-for-picking-colors - - - https://stackoverflow.com/questions/28503998/how-to-create-custom-palette-with-custom-color-for-material-design-app - - https://material.io/design/color/#color-usage-palettes - - https://www.materialpalette.com/ - - -Vuetify themes: https://vuetifyjs.com/en/style/theme - -======================================================================================== -SHELL and UI elements plan: - - - -EXAMPLE UI INTERACTION ELEMENTS: -=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-= -CATEGORY NAV MENU ITEM -> SHOWS TOP LEVEL UI COMPONENT SPACE / PAGE - TOP PAGE -> SHOWS TOP LEVEL WIDGETS FOR that category which could be control panel, lists, (rarely) reports, (rarely) graphs, calendar etc, but most often lists - -EXAMPLE: -SELECT NAV.INVENTORY -> SHOWS MULTIPLE TOP LEVEL UI WIDGETS RELATED TO INVENTORY: - - PARTS LIST WIDGET - - LINKS TO: CREATE, LIST, REPORT, GRAPHS (BASED ON ROLES), PLUGINS THAT AFFECT ALL INVENTORY - - LIST OPTION: SHOWS LIST OF PARTS WITH ABILITY TO EDIT, DELETE, MASS SELECT AND CHANGE (plugins, delete, tag etc), FILTER BY TAG, DATE RANGE, SORT ETC - - PO LIST - - LINKS TO: CREATE, REPORTS, GRAPHS (ROLES CONTROLLED) - - PART REQUESTS OVERVIEW ETC.... - - PART ASSEMBLIES - - PART CATEGORIES - - PART WAREHOUSES - - Maybe some stock graphs and reports in same page?? Or are these sub types of lists? (probably since you can select in the list what to report / graph) - ----------- -Or, no top level at all, just the list with a default view and can be sorted / filtered then saved as a new customized top level list widget showing as customized? - - And customized moved to HOME view, ordered by source type i.e. all widget lists together and in order of creation or something or nameable maybe? - - Home view can contain any widget that can be customized or the stock ones, - defaults to dashboard of some kind or defaults empty maybe with a placeholder "save widgets here" - - - Stock widgets always remain in their places pre-defined so can't mess up the view / can always find them - - Customized widgets all go to home page? - - This way user can build up the UI they want to see every day - - -TYPES OF CUSTOMIZABLE WIDGETS - - List - - Report - - Control panel (like global options, list of options right in main widget) - - Graph - - Calendar / schedule - - subtypes or morphs? - - Day / month / week etc - -Fixed widgets - - CRUD editor, kind of built into the other widgets as the default editor type for each type - - -UI Made up of the customizable and fixed widgets then subbed in place, so a list widget is generic but then is put into an outer component where it has custom elements and list specific api stuff added - - icon, api, lt etc - - -WIDGET HIEARCHY - -AYWIDGET (OUTER WRAPPER) - HOSTS ONE OF THESE: - List - Report - Graph - Calendar - CRUD editor - -AYWIDGET abilities: - - Can have a name / title and be customized - - Can be positioned in order - - Can be fullscreen or several set smaller sizes - - Can be moved to home page - - -BREAKPOINTS -=-=-=-=-=-= - -Plan: Layout and design each component for the smallest screen size first, then add more elements to each one as the size increases. - - “when in doubt, just remove.” (or place in a menu out of main view) - - It makes no sense to target individual devices anymore. Instead, add breakpoints where your design breaks. - If you start with your design for the smallest device and start to drag your browser window wider, when do the lines become too long to read comfortably? - When could you make better use of the screen? That is the point at which to add a Media Query and write some additional CSS. - - So design with the tiny ones and minimalist, then drag out and see where can add more value with more stuff. - - Ideally at this point I'd like to see small and large only, medium specific design not necessary but testing obviously is (TIME TO MARKET!) - - NAV For example a menu can be fully shown as icons in a larger size but might be behind another click in smaller - - Functionality: figure out what the minimum most important things to show at small size then add more "optional" stuff as it increases - - Grid: show the Name column first and selector, then add the most relevant columns in order of relevancy - - 1-Name, 2-Tags?, 3- etc - - graph: mini graph at smallest size with controls hidden for modifying it, then more controls and larger graph at larger sizes - - Crud: all is needed, but responsive layout so long vertical column in sm and increasing columns by similar group of items in larger - - Menu controls maybe buried if not super needed in sm but all visible in large increasingly by usage - -Can I make one component for each type that is responsive or do I need to make a separate component for each breakpoint I will support? - - One component pros: less code to maintain theoretically, cons: maybe less well designed for that size +UI DESIGN DOC + +Requirements + - Responsive but favoring larger screens primarily + - Smaller screens will be able to do everything but the layout is not the primary one + - Service techs have an ipad or notebook + - Anticipate a list of things each role needs immediately in front of them and try for that + - componentized UI elements so can re-use and mix and even support customizing with user defined layout + - So for example a customer list is a self contained subset of a list widget and can be plunked down anywhere required + - This will save me time so identify the "types" of ui elements (picklist, filterable data list, entry form etc) + - Then can build specific versions of the types identified like a client list is a specialized filterable data list etc. + - If a list then it also knows which element is selected or a list of selected elements so other widgets can operate on it + - A menu or command widget that can be inserted into another widget, i.e. a part picker for a workorder part list widget or elsewhere a part is required + - This way I'm only making a few UI objects, not a new one for every single element. + - Kind of making the pallet first of all required objects then I can "paint" with them on to the UI without getting bogged down in minute details every time I make a form + - UI elements should be responsive and generic enough to work for many different use cases + - they should be rights aware and mode aware (editable, read only) enough to handle all that without recoding again and again + - the page or shell or whatever that holds the widgets should be end user customizable from a widget pallet. + - The more self contained the widget the more useful + + - Most people seem to prefer WBI over RI and the reason always seems to be RI is too simple or requires too many clicks + - So plan on the bigger screen layout being the main UI and smaller screen secondary + - I want things to be simpler and cleaner than it seems many people do so beware of that tendency + - People don't want to have to open sub screens any more than absolutely necessary + - Make sure a screen contains as much as possible to complete it on one screen + - Clean interface with good negative space but not dumbed down too much + - Pro-marketing style, stuff that makes it easier to sell + - emphasize simple fonts with good contrast + - Blue is a good colour, no purple or pastels + - DAshboard / customizable UI + - Ideally people can see as much detail as they want or remove unused ui widget elements + - So, for example on the dashboard they can customize by plunking down a client list widget, adding a "My workorders" widget for a tech + - or for a Ops person they can plunk down on their dashboard a current server status widget or active jobs widget etc + + + - RAVEN PROPOSED NAV PANEL + + - "HOME" (Current user specific stuff only) + - "OVERVIEW" (old "dashboard" not sure of the LT name but it's the old dashboard) of service if a tech or has access to tech related shit like current dashboard + - A customer had thoughts on the dashboard: + - case 1974: shootnsharp@thesoileaus.com "In my opinion, the dashboard would be much more functional and valuable if I could determine how many work orders show on the screen and possibly even what statuses (or be able to sort by status, priority, etc.) The At a Glance stats of Service Rate Quantity is helpful but would be even more relevant if it showed what was approaching due date, overdue, waiting on parts, pending parts requests, items on loan stats, preventative maintenance work orders approaching and overdue. Having the capability to customize the Dashboard is key because each Service business has its own metrics that are most important to its business." + - SCHEDULE (User's own schedule only if applicable, all users can have a schedule so it goes here) + - MEMOS (for user) + - SCHEDULE MARKERS (list for user, convenience extra so don't need to hunt around on calendar) + - SETTINGS + - User translation settings + - Any other user specific settings that the User can control (and sb able to control more than in v7 if it doesn't affect anyone else) + - Change login? + - notification subscriptions + - Notifciation deliveries + - CUSTOMERS + - CUSTOMERS (customers) + - HEAD OFFICES + - SERVICE + - WORKORDERS (was "service" in v7, now all "service" workorders are just workorders) + - ALL LEVELS + - NOTE: Either all levels still in menu at left here or somehow at right in separate boxes maybe, I like the idea of the in menu better with single right pane for simplicity + - TEMPLATES + - QUOTES + - See "Workorders" above same layout + - PREVENTIVE MAINTENANCE + - See "Workorders" above same layout + - UNITS + - UNIT MODELS + - CONTRACTS + - CUSTOMER SERVICE REQUESTS + - LOANERS (not 100% certain about this location for this item) + - SCHEDULE (all users not just current one) + - INVENTORY + - PARTS (part list) + - INVENTORY + - PART REQUESTS + - PURCHASE ORDERS + - PO ITEMS (WEIRD) + - PO RECEIPTS + - PO RECEIPT ITEMS (ALSO WEIRD) + - ADJUSTMENTS + - WIDGETS (for testing purposes) + - VENDORS + - single level, no subitems + - ACCOUNTING + - Any new accounting funcationlity (theres' some new workorder stuff for accting) + - All old plugin accounting integration stuff + - ADMINISTRATION + - GLOBAL SETTINGS + - LICENSE RELATED + - USERS + - LOCALIZED TEXT DESIGN + - REPORT TEMPLATES + - FILES IN DATABASE + - SCHEDULE MARKERS (DEPRECATED) (This shows *all* sm for all users, kind of weird, not documented at all, leaving it out) + - HISTORY (event log) view, filter, sort etc the whole thing here to see what activity is happening in general + - KPI WIDGETS AND GRAPHS AND SHIT FOR BIZ ADMIN + - OPERATIONS CONSOLE + - SERVER CONTROL? (close/open server ops? Or does that happen automatically when doing other jobs?) + - "ARCHIVE" (BACKUP /RESTORE) + - JOBS (view status of, trigger some maybe) + - SERVER LOGS + - METRICS + - NOTIFICATION CONFIG AND CHECK DELIVERIES + + + + [HOLDER] + [HOLDER] + ACTION + ACTION + ACTION + ACTION + ACTION + [HOLDER] + ACTION + + So top level can be a holder or an action + if holder then we are in second level + SECOND LEVEL + Can be a holder or an action + if Holder then we are in third level + Can only be an action + action + action + +FOR REFERENCE HERE IS THE v7 NAV panel LAYOUT: +- V7 nav panel is like this: + - DASHBOARD + - SERVICE + - All levels of workorders of this type + - Templates for workorders of this type + - QUOTES + - All levels of workorders of this type + - Templates for workorders of this type + - PREVENTIVE MAINTENANCE + - All levels of workorders of this type + - Templates for workorders of this type + - SCHEDULE + - INVENTORY + - parts + - po's + - po items (weird) + - po receipts + - po receipt items (also weird) + - adjustments + - adjustment items (strange) + - part inventory + - part requests + - CLIENTS (CUSTOMERS) + - clients (customers) + - head offices + - contracts + - projects + - customer service requests + - UNITS + - units + - unit models + - loan items + - VENDORS + - vendors + - CURRENT USER + - memos + - notification subscriptions + - notification deliveries + - wiki page (personal, wtf?) + - SEARCH + - ADMINISTRATION + - global settings + - regions + - security groups + - users + - custom field design + - localized text design + - notification deliveries (last 7 days) + - report templates + - files in database + - schedule markers (wtf forgot about this what's it for again?) + + + +=-=-=-=-=-= +This is a worked example to determine what UI elements should be where using the Client as the example object type: + +CLIENT OPS +=-=-=-=-=- + - list + - Select individually + - mass operations + - Delete + - Tag + - Import / Export / Integrate + - Notifications + + - Report / Graph + + - Search / Find quickly by typing in part of the name or something + - Filter + - Sort + - Set display number per page (sticky) + - Expand to full screen to show all the columns possible? + - Or...shows as many columns as possible automatically based on screen size available width + + - Single + - CRUD + - TAGS + - Duplicate + - Report / Graph + - Notifications settings + - Service BANK + - CSR + + - Show all + - Units + - Workorders + - Quotes + - PM + - CSR + - Service history feature for quickly seeing totals and dates (see case for deets) + - Export / Integrate + - Attachments + - Wiki + - Follow up / schedule + - Record history (should just show in main UI I think) + - Notes (separate collection, but maybe should be part of main edit ui) + + + - Contracts + - Projects + + =-=-=-=-=-=-=-=- + + + + +Graphics and themes for AyaNova + - No bitmap graphics, vector only!! + - For the manual and docs will use material theme with MKDOCS generator. + +ICON FONT - Going with Font Awesome 5.x SOLID FREE icons +=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +- I'll choose the replacement fonts as I need them from the FontAwesome5 collection and document them here. +- https://fontawesome.com/icons?d=gallery&s=regular,solid&m=free + +- v7: + - v7 icons, all orangey brown in color with bits of highlight in each one of other colors. 3d in general + - Service Workorder (wrench and screwdriver) + - Workorder items (single wrench alone no screwdriver) + - Scheduled users (torso in front of calendar) + - Parts (3d cube) + - Labor (hammer) + - Travel (truck looks like loomis courier truck) + - Loans (plug from electrical cord for no apparent reason) + - Expenses (riffle of US dollar bills) + - Service templates (looks like rubber stamp) + - Quote (pen and paper) + - all subitems same as for service workorder + - PM (alarm clock and paper) + - all subitems same as for service workorder + - Schedule (looks like the schedule calendar screen but tiny and a bit cluttered) + - Inventory (3 shapes, pyramid, ball, cube in 3d effect) + - Parts (cube) + - PO items and PO receipts (both are kind of just documents, PO receipt is same but with a corner to corner orangey stripe across it that is indechipherable) + - Part requests (document like a po with a wrnch and hammer Service icon in front of it weirdly when it should be a cube I think) + - Clients (house icon with door and front mat) + - Headoffices (larger building, low rise apartment or office tower) + - Contracts (two hands shaking) + - Projects (some kind of closed book that looks like a dayplanner with colored tabs sticking out) + - Dashboard (speedometer / analog meter black dial, silver surround and lettering like from an old time auto dashboard) + - Units (cog which I don't like) + - Unit models (some kind of mechanical looking pentagram with a circular thing in the center, weird) + - Loan items (power plug for no apparent reason) + - Vendors (shopping basket handheld kind) + - Current user pane (hard hatted torso person) + - Memos (inbox looking thing) + - Notification subscriptions (loudhorn but not 3d, flat side view instead, looks more like a hatchet, man these old icons are fucked and confusing) + - Notification deliveries (loudhorn but smaller and on top of a sheet of paper) + - Wiki page (atomic diagram looking thing) + - Search (magnifying glass) + - Administration (torso with suit and set of keys superimposed) + - Global settings (planet right on the nose) + - Regions (pie chart with wedge extracted slightly) + - Security groups (keys) + - Users (hard hatted torso but front on and flat) + - Custom field ("Abc", probably the font chooser icon in most apps) + - Localized text design (address card) + - Notification deliveries (bull horn / hatchet and sheet of paper) + - Report templates (sheet of paper and small rubber stamp) + - Files in database (filing cabinet) + - Schedule markers (post it note with pin and folded up lower right corner) + - WIKI (atomic nucleus diagram / weird flower) + - GENERAL UI + - Delete (red circle with white X through it) + - OK / ACCEPT (Green circle with white checkmark through it) + - Cancel (orange circle with white "forbidden" bar across it diagonally from top right to lower left) + - Save (3.5'' diskette!?) + - Document attachments (two hardcover books back to back on an angle in 3d) + - Record history (analog clock face) + - Follow up "Review" (schedule marker post-it note with a chain link overtop of it) + - Print / report (inkjet printer) + - Duplicate (rabbit) + - Plugin (puzzle piece) + - Attach file [wiki] (file folder) + - Edit [wiki] (pencil) + - Reply [memo] (inbox used for memo with left facing green arrow superimposed) + - Forward [memo] (inbox used for memo with right facing green arrow superimposed) + - Recent [MRU on main menu] (binoculars) + + + + +LOGO + - Need to standardize on a logo and stick to it from now on + - Simple and clean (script AyaNova used for RI is maybe out) + - Single colour canucks blue with green contrast if absolutely necessary (don't make it necessary) + +COLOURS + - Canucks colours of course, Blue primary and green secondary. + /* =================== + AyaNova 8 Westcoast theme + Based on Canucks current colors + Primary colour = dark blue + Web: #00205B + RGB: 0, 32, 91 + + Secondary colour = green + Web: #00843D + RGB: 0, 132, 61 + * + * #00843D = Green +#00205B = Blue + private Color AyaGreen = System.Drawing.ColorTranslator.FromHtml("#00843D"); + private Color AyaBlue = System.Drawing.ColorTranslator.FromHtml("#00205B"); + =================== */ + + - No indigo or pastels ?? + + - Canucks colors in designer + - https://material.io/tools/color/#!/?view.left=1&view.right=0&primary.color=00205B&secondary.color=00843D + - Picker tool / generator of pallete: https://material.io/design/color/#tools-for-picking-colors + + - https://stackoverflow.com/questions/28503998/how-to-create-custom-palette-with-custom-color-for-material-design-app + - https://material.io/design/color/#color-usage-palettes + - https://www.materialpalette.com/ + + +Vuetify themes: https://vuetifyjs.com/en/style/theme + +======================================================================================== +SHELL and UI elements plan: + + + +EXAMPLE UI INTERACTION ELEMENTS: +=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-= +CATEGORY NAV MENU ITEM -> SHOWS TOP LEVEL UI COMPONENT SPACE / PAGE + TOP PAGE -> SHOWS TOP LEVEL WIDGETS FOR that category which could be control panel, lists, (rarely) reports, (rarely) graphs, calendar etc, but most often lists + +EXAMPLE: +SELECT NAV.INVENTORY -> SHOWS MULTIPLE TOP LEVEL UI WIDGETS RELATED TO INVENTORY: + - PARTS LIST WIDGET + - LINKS TO: CREATE, LIST, REPORT, GRAPHS (BASED ON ROLES), PLUGINS THAT AFFECT ALL INVENTORY + - LIST OPTION: SHOWS LIST OF PARTS WITH ABILITY TO EDIT, DELETE, MASS SELECT AND CHANGE (plugins, delete, tag etc), FILTER BY TAG, DATE RANGE, SORT ETC + - PO LIST + - LINKS TO: CREATE, REPORTS, GRAPHS (ROLES CONTROLLED) + - PART REQUESTS OVERVIEW ETC.... + - PART ASSEMBLIES + - PART CATEGORIES + - PART WAREHOUSES + - Maybe some stock graphs and reports in same page?? Or are these sub types of lists? (probably since you can select in the list what to report / graph) + +---------- +Or, no top level at all, just the list with a default view and can be sorted / filtered then saved as a new customized top level list widget showing as customized? + - And customized moved to HOME view, ordered by source type i.e. all widget lists together and in order of creation or something or nameable maybe? + - Home view can contain any widget that can be customized or the stock ones, + defaults to dashboard of some kind or defaults empty maybe with a placeholder "save widgets here" + + - Stock widgets always remain in their places pre-defined so can't mess up the view / can always find them + - Customized widgets all go to home page? + - This way user can build up the UI they want to see every day + + +TYPES OF CUSTOMIZABLE WIDGETS + - List + - Report + - Control panel (like global options, list of options right in main widget) + - Graph + - Calendar / schedule + - subtypes or morphs? + - Day / month / week etc + +Fixed widgets + - CRUD editor, kind of built into the other widgets as the default editor type for each type + + +UI Made up of the customizable and fixed widgets then subbed in place, so a list widget is generic but then is put into an outer component where it has custom elements and list specific api stuff added + - icon, api, lt etc + + +WIDGET HIEARCHY + +AYWIDGET (OUTER WRAPPER) + HOSTS ONE OF THESE: + List + Report + Graph + Calendar + CRUD editor + +AYWIDGET abilities: + - Can have a name / title and be customized + - Can be positioned in order + - Can be fullscreen or several set smaller sizes + - Can be moved to home page + + +BREAKPOINTS +=-=-=-=-=-= + +Plan: Layout and design each component for the smallest screen size first, then add more elements to each one as the size increases. + - “when in doubt, just remove.” (or place in a menu out of main view) + - It makes no sense to target individual devices anymore. Instead, add breakpoints where your design breaks. + If you start with your design for the smallest device and start to drag your browser window wider, when do the lines become too long to read comfortably? + When could you make better use of the screen? That is the point at which to add a Media Query and write some additional CSS. + - So design with the tiny ones and minimalist, then drag out and see where can add more value with more stuff. + - Ideally at this point I'd like to see small and large only, medium specific design not necessary but testing obviously is (TIME TO MARKET!) + - NAV For example a menu can be fully shown as icons in a larger size but might be behind another click in smaller + - Functionality: figure out what the minimum most important things to show at small size then add more "optional" stuff as it increases + - Grid: show the Name column first and selector, then add the most relevant columns in order of relevancy + - 1-Name, 2-Tags?, 3- etc + - graph: mini graph at smallest size with controls hidden for modifying it, then more controls and larger graph at larger sizes + - Crud: all is needed, but responsive layout so long vertical column in sm and increasing columns by similar group of items in larger + - Menu controls maybe buried if not super needed in sm but all visible in large increasingly by usage + +Can I make one component for each type that is responsive or do I need to make a separate component for each breakpoint I will support? + - One component pros: less code to maintain theoretically, cons: maybe less well designed for that size diff --git a/devdocs/specs/core-wiki.txt b/devdocs/old-devdocs/specs/core-wiki.txt similarity index 93% rename from devdocs/specs/core-wiki.txt rename to devdocs/old-devdocs/specs/core-wiki.txt index 077b690c..e02b41a9 100644 --- a/devdocs/specs/core-wiki.txt +++ b/devdocs/old-devdocs/specs/core-wiki.txt @@ -1,60 +1,60 @@ -# WIKI specifications - -NOTE: This applies to all core business object types that are basically real world and have an id and a type (all are wikiable, attachable and reviewable) -Not utility type objects like datalist etc - -Sample markdown doc with all elements: - -=-=-=-=-= -Headings -# Heading 1st level -## Heading 2nd level -### Heading 3rd level -#### Heading 4th level -##### Heading 5th level -###### Heading 6th level - -Emphasis text styles -*Italic* -**Bold** - -Hyperlink -[Link](https://ayanova.com) - -Image -![Image](https://www.ayanova.com/images/AyaNova60x60.png) - -Quote block -> Blockquote -> more block quote - -Unordered list -* List -* List -* List - -Ordered list -1. One -2. Two -3. Three - -Nested lists -* First - * subitem One - * subitem Two -* Second - 1. sub one - 2. sub two - -Horizontal rule ---- - -`Inline block` with backticks - -``` -# Multi-line block -print '3 backticks or' -print 'indent 4 spaces' -``` -=-=-=-=-= - +# WIKI specifications + +NOTE: This applies to all core business object types that are basically real world and have an id and a type (all are wikiable, attachable and reviewable) +Not utility type objects like datalist etc + +Sample markdown doc with all elements: + +=-=-=-=-= +Headings +# Heading 1st level +## Heading 2nd level +### Heading 3rd level +#### Heading 4th level +##### Heading 5th level +###### Heading 6th level + +Emphasis text styles +*Italic* +**Bold** + +Hyperlink +[Link](https://ayanova.com) + +Image +![Image](https://www.ayanova.com/images/AyaNova60x60.png) + +Quote block +> Blockquote +> more block quote + +Unordered list +* List +* List +* List + +Ordered list +1. One +2. Two +3. Three + +Nested lists +* First + * subitem One + * subitem Two +* Second + 1. sub one + 2. sub two + +Horizontal rule +--- + +`Inline block` with backticks + +``` +# Multi-line block +print '3 backticks or' +print 'indent 4 spaces' +``` +=-=-=-=-= + diff --git a/devdocs/specs/core-workorder.txt b/devdocs/old-devdocs/specs/core-workorder.txt similarity index 98% rename from devdocs/specs/core-workorder.txt rename to devdocs/old-devdocs/specs/core-workorder.txt index 9a3270fc..9bee8eba 100644 --- a/devdocs/specs/core-workorder.txt +++ b/devdocs/old-devdocs/specs/core-workorder.txt @@ -1,340 +1,340 @@ -WORKORDER - -Workorder form fleshed out in case https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/3850 -Submitting entire wo or just parts at a time?? -If each part has it's own concurrency then can submit whole and bits that aren't different would have same concurrency so no issues - test this idea - - -CONCURRENCY decision / research - updating, in bits seperately, entirely at once? [## DECIDED, BITS MAKES MOST SENSE AND DIRTY TRACKING AT CLIENT ##] - Considering we are looking at a system where some users won't see or even get the data for some parts of the workorder then it's important that they be able to just save their piece of it separately - So this strongly leans towards seperately saved and not entirely at all. - concurrency issue reduction - Things that might require an entire workorder graph be updated at once: - Major header changes? - Customer, Contract because pricing and policies might change? - - Anything that affects balances and totals (are there new features happening showing dollar amounts billable right on workorder?) - in v7 not an issue because need to preview report to see totals - in v8 some talk of seeing totals, so need to determine if that's still a thing, if not then this whole class of concurrency issues dissappears - This would be entirely resolved with a "view" showing a type of "invoice" summary kind of thing where you open that tab and it fetches and calcs and displays - however this would be little difference from a report and a little worse because the end user can't edit it to calculate how they would like it to so... - - ENTIRE GRAPH AFFECTING CHANGES - One idea to support this is if a change is made at header that affects all children then change their concurrency values so updates will fail - This is a good idea, need a clean way to support it but this makes sense - - Dirty tracking at every level and object would save having to send entire workorder, just dirty bits - i.e. have non-mapped dirty fields for every woitemrecord - client uses them to track changes and what needs to be saved - upon save client goes through graph looking for dirty records and saves them each but is senstive to the best order to do it and takes into account if save would lock or unlock - Header fields - dirty - a woitem - dirty? - awoitemlabor - dirty? - If something is changed that affects entire graph then that can be checked for at the client and trigger a full save regardless - WorkorderStatus change would always be the first thing saved as it might be required to UNLOCK the workorder - Client needs entire status list cached on hand to know if a status change affects lock status and if it's going from unlocked to locked then it would need to save the entire workorder graph and let the server handle it - or save bottom up before locking with the status / header change - Actually isn't this just handled at the server as a biz rule? (no because if header saved first then it's locked potentially and sub items can't be save subsequently in a graph walking save) - New items are always dirty so a new labor record added would be dirty and saved individually - At the server upon item being saved there would always need to be a quick check of the entire workorder to see if it's LOCKED status or not - if locked then bumps back with error that wo is now locked (of course they could just change the status in the header and resave I guess) - - -UI stuff - - - - - - - - - - - - - - - - -########### PLANNING BELOW HERE, OUTDATED NOW ######################################## -Lot's to go in here but for now this is holding my planning and thoughts until can set in stone: - - -## Copied over from client todo while testing / planning, probably outdated if you're reading this after May 2020 - -todo: PLANNING WORKORDER considerations: - QUESTIONS: - Why do I need to make a wo first before I can update it? (i.e. why did I make a CREATE route?) - still no idea after lot's of planning, answer is probably not needed at all - - How can I avoid concurrency issues? - concurrency check each record in graph, not entire workorder from top - - How to minimize data sent, make fast saves? - I'm leaning towards the tons of routes option, need to test it out - - PATCH, send all changes in graph in one go - most efficient, sends all changes in one go - if any part fails it all fails - requires second copy of wo for diffing - UPDATE (PATCH): Send only changes in whole graph from client with an OP (for "operation") flag at each level indicating to change that part or not, a flag? - WO (OP flag=no change, no concurrency token, basically empty but for the fields that hold the descendants that are changed) - woitem 0 (OP flag="Delete" and concurrency token, no other data with it, just the id and flag and ctoken) - woitem 1 (OP flag ="update", all fields as in a "put" operation, nothing left out, assumed all are changed) - woitem2 (OP flag="no OP", just a placeholder for children with changes) - labor 2 (OP flag = "update" with all data) - labor 3 (OP flag="delete" with concurrency token and nothing else) - labor 4 (OP flag="Add", with all PUT data) - issues with patch: - how to post a whole object leaving blank when so many fields will be required? - maybe we don't make them required at the object field annotation level but only at the db level and as a biz rule? - how to synchronize objects and id's? - i.e. reverse patch back again - for example, you add two woitems, save, you have two now that are not id'd and don't know which is which - server has to return something identifying which is which and assigned ID, plus it might add data back or change data due to rules or whatever - Maybe server sends back entire saved objects? - issues: - how to update client end with update back from server when saved (server will add id and may change fields or even add things) - - * TONS OF ROUTES: Update individual portions as seperate objects to their own routes sequentially - i.e. client traverses and diffs virgin copy and edited copy of wo - determines what's different, only sends an update for each object to it's own route as appropriate - on successful update fixes up the edited copy of that object - on all updates done, the edited copy becomes the virgin copy (or do we need 3 objects at one point in case of fail?) - - requires second copy of wo for diffing - goes over workorder, looks for changes, sends update for each object individually and patches up local from result - so if a workorderitempart has changed then it sends only that for update individually - Example routes: - Post: Workorder/1/WorkOrderItem/2/Labor/4 {updated object} - WorkOrder/{woid} <-entire workorder, get for all, post for entire, put to update entire (not likely to use but?) - WorkOrder/{woid}/WorkOrderItems <- all workorderitems, post to add new, put to update all as a collection - WorkOrder/{woid}/WorkOrderItems/{woitemid} <- CRUD single woitemid - WorkOrder/{woid}/WorkOrderItems/{woitemid}/Labors <- entire labor collection CRUD ops over all collection (also ADD new labor here (POST)) - WorkOrder/{woid}/WorkOrderItems/{woitemid}/Labors/{laborid} <- Crud on individual item - - This way is pretty solid, will result in a lot of routes but a lot of the code can be shared in the biz object, so for example if updating a labor or a collection of labor most code the same - Efficiency: - Since there is a route for every bit of the workorder the client can pick how high up to update based on diff check - so if only one single bit of a header has changed then only update that bit (or will it need the collection to not remove it? No because collection route is where you remove an item) - or if only a deeply nested labor has changed, just PUTS it to that exact route and udpates concurrency token on result - since the workorder is not really influenced as a whole by updates to portions this could work and be a bit less problematic than JSONPATCH which really seems to be a bit of a stretch - - -NOTE: can put part of the route in the controller, so for example if every route in that controller needs to identify a workorder then this kind of thing is possible, not sure if helpful or not yet: -[Route("api/campus/{campusId:int}/building")] -public class BuildingController : Controller { - //... - - [HttpGet] - [Route("{buildingId:int}")] // Matches GET api/campus/123/building/456 - public IActionResult GetBuilding ([FromRoute]int campusId, [FromRoute]int buildingId) { - //... validate campus id along with building id - } -} - - issues: - very chatty, could be slow - - PUT, update entire workorder on every save - Very easy to code, basically send it all and see what happens - Very clean, no need to worry about bits and pieces being tracked etc - issues: - not very efficient, needs to send entire graph on every save even if user just changed one character - - - How to support undo? - How to show what's dirty on form? - - - - BUSINESS RULES (v7) - In reality there are almost no business rules in v7 workorder graph. - Only serious one is woitempart requires serial if serialized - Rest are all related to length of fields, required fields, date order etc and only a few of those to boot - Looks like this is not an issue regarding v7 stuff at all - - - DEPENDENCIES - Workorder is not dependent on it's children for anything - WoItem is not dependent on any of it's children - In fact nothing in any part of the wo is dependent on anything else during normal ops - - CONCURRENCY - If the client updates part of the wo graph, only that exact record really needs dependency checking. - There *is* however business rules that might take hold but that's all at the server and not related to concurrency directly - For example, on any change to the wo graph the server has to see if the wo is still editable and hasn't been locked or user's rights changed - But that's not strictly concurrency related in the sense that another user change the *same* record being updated - So, for v8 as long as it can handle a portional update to part of the graph and uses the concurrency of that exact record to check then it sidesteps a lot of multi-user scenarios - This was only an issue in v7 due to it using only the wo header itself as the source of concurrency checking which would *always* involve the whole graph in any change anywhere - - for example: - WOHEADER (concurrency id, dirty flag at client) - WOITEM (concurrency id, dirty flag at client) - woitempart (concurrencyid dirty flag at client) - woitemlabor (concurrencyid, dirty flag at client) - WOITEM (concurrency id, dirty flag at client) - woitemscheduser (own concurrency, dirty flag etc) - woitempart (concurrencyid dirty flag at client) - woitemlabor (concurrencyid, dirty flag at client) - - ROUTES - In light of dependencies and concurrency it is ideal if the server can handle updates to any portion of the graph independently - But, do we really want CRUD routes for every descendant of the workorder graph? (maybe, just not sure) - - - - TEST - Do a practical test of a mocked wo, woitem, woitemlabor or whatever, see how it would be updated, fetched concurrency checking etc - QUESTIONS: - How to do CRUD efficiently with a workorder and client? - - - PROPOSAL TO TEST: - Create enough of a graph to test, 3 layers two grandhild collections should be sufficient: - WO - WOITEMS - WOITEMLABORS - WOITEMPARTS - - CREATE (POST): - CreateFromxxxx routes (NO TEST REQUIRED) - POST accepts NEW workorder full graph (test) - RETRIEVE (GET): - Get(id) - simple get, just confirm entire graph comes across - GetByRelative(ayatype, id) (no test required) - - UPDATE (PUT?) - Test code tons of routes method detailed above - - SERVER - Server accepts graph at single WO POST route (since it's not a put) - UI - ui manufactures the return object with the OP fields by doing dirty tracking on changes - DELETE - Not much here except handling delete will be more intensive and sophisticated when have real data but for now if the graph deletes then that's enough - Test how to delete graph without ref. integrity errors - - - UI - Only send the bits that are altered to save bandwidth - All updates are technically a PATCH operation - Because it starts with a wo object provided by the server? - or is this even necessary now? - think Patch - CONCURRENCY: - if any part of the patch fails the whole patch fails - - idea: UI reflects tentativeness state of object: - The UI doesn't imply something is done by changing it fully until the save is completed. - This serves two purposes: - 1) user knows at a glance what isn't saved yet and will know it's waiting for save clearly, hopefully leading them to save more often, - 2) client doesn't need to track invisible shit behind the scenes, can more easily do patch updates right off UI source - - e.g.: - if deleted a row in parts, that row doesn't disappear but rather shows crossed out, maybe grayed out but still there until save to indicate it's tentative status - if added a row, shows green or something or bold or asterisk, (can style with css based on state) until saved - problems: - how to handle regular fields that are changed (that's a lot of field data to track for changes)? - Maybe client keeps a virgin copy of the original wo for comparison - periodically does a compare and flags differences on updates? - (this would also help to serve as an Undo maybe?) - - - - A biz object for each one? - probably need the parent for biz rules and shit so likely best to keep in one file - Controller - all in root controller or seperate controllers? - likely follows biz object decision - case 1714 re-rises the question about concurrency and mutiple editors of a workorder - Look into how independent changes can be from each other, i.e. is it safe to have two users editing two different woitems on a workorder? - This might make people happier. - Like, what exactly affects what else on a workorder. Do you save the whole wo to the route at once even though you just added a woitem or..? - If I code it to send the whole wo on a change to even a grandchild then that's heavy traffic for a minor change - - actually no, it's not really that heavy, even a fairly fat workorder will be way under 100kb, most probably under 1kb - should really only send the minimum data required to fulfil the change. - Maybe need two copies of wo at client so can tell what has changed and then only send that bit. - But then need routes to handle that? - Or can the wo route just accept a blank header with items hanging off it that have changed only? (like a patch?) - - Use foreign keys!! - Consider UI in this as well, will need to decide at least what is visible when - Workorder UI good ideas here: https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/3475 - How to add items, like new woitem? - send to server get back new object? - lots of biz rules and stuff need to happen, want to minimize load at client - but lots of data back and forth is not ideal - maybe request a woitem and get it back? - what exactly needs to be processed in the wo when items are added / removed? - math / totalling? - simple calcs sb client doable - this will drive what has to happen. - Need to go over all wo features and factor them into this decision properly - The whole idea of a completed section of a wo and stuff, is that dropped due to TTM or still viable? - maybe can pick out the best new features of that which can be integrated into existing design rather than re-inventing the wheel - Here is an overview: https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/3412 - How best to be able to service LoanUnits on a workorder? - Just make them Units with extra properties exposed if type of loaner? - This seems simplest, but what will it effect? - Hard to make them serviceable if they are an alternate table of source for what's being repaired as that breaks a lot of other code or adds exceptions - Customer is then who exactly because it's fundamental to a lot of wo functionality? - from a biz perspective isn't it like you are your own customer when you service your own equipment that you loan out? - Does Serial field need to be numeric, could it be text instead? - prompted by case 3428 saying that it's hard to deal with constant conversion to text for UI etc - plus, I'm thinking it opens door to textual scheme like appending -A or whatever to a wo. - or, is that a display issue? - Calling something "serial" implies it's unique but it isn't, maybe I should call it "number" instead or "ID" or something? - INFO: did a test workorder with ALL fields filled out heavily and one woitem, exported from db entire graph based on detailed report so every line was every item repeated - still only 84kb and it's a lot bigger than any typical wo in v8 would be as it will be far more efficient without having to repeat lines flatly - so I think size of object is a non-issue really from a practical standpoint. - - +WORKORDER + +Workorder form fleshed out in case https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/3850 +Submitting entire wo or just parts at a time?? +If each part has it's own concurrency then can submit whole and bits that aren't different would have same concurrency so no issues + test this idea + + +CONCURRENCY decision / research - updating, in bits seperately, entirely at once? [## DECIDED, BITS MAKES MOST SENSE AND DIRTY TRACKING AT CLIENT ##] + Considering we are looking at a system where some users won't see or even get the data for some parts of the workorder then it's important that they be able to just save their piece of it separately + So this strongly leans towards seperately saved and not entirely at all. + concurrency issue reduction + Things that might require an entire workorder graph be updated at once: + Major header changes? + Customer, Contract because pricing and policies might change? + + Anything that affects balances and totals (are there new features happening showing dollar amounts billable right on workorder?) + in v7 not an issue because need to preview report to see totals + in v8 some talk of seeing totals, so need to determine if that's still a thing, if not then this whole class of concurrency issues dissappears + This would be entirely resolved with a "view" showing a type of "invoice" summary kind of thing where you open that tab and it fetches and calcs and displays + however this would be little difference from a report and a little worse because the end user can't edit it to calculate how they would like it to so... + + ENTIRE GRAPH AFFECTING CHANGES + One idea to support this is if a change is made at header that affects all children then change their concurrency values so updates will fail + This is a good idea, need a clean way to support it but this makes sense + + Dirty tracking at every level and object would save having to send entire workorder, just dirty bits + i.e. have non-mapped dirty fields for every woitemrecord + client uses them to track changes and what needs to be saved + upon save client goes through graph looking for dirty records and saves them each but is senstive to the best order to do it and takes into account if save would lock or unlock + Header fields - dirty + a woitem - dirty? + awoitemlabor - dirty? + If something is changed that affects entire graph then that can be checked for at the client and trigger a full save regardless + WorkorderStatus change would always be the first thing saved as it might be required to UNLOCK the workorder + Client needs entire status list cached on hand to know if a status change affects lock status and if it's going from unlocked to locked then it would need to save the entire workorder graph and let the server handle it + or save bottom up before locking with the status / header change + Actually isn't this just handled at the server as a biz rule? (no because if header saved first then it's locked potentially and sub items can't be save subsequently in a graph walking save) + New items are always dirty so a new labor record added would be dirty and saved individually + At the server upon item being saved there would always need to be a quick check of the entire workorder to see if it's LOCKED status or not + if locked then bumps back with error that wo is now locked (of course they could just change the status in the header and resave I guess) + + +UI stuff + + + + + + + + + + + + + + + + +########### PLANNING BELOW HERE, OUTDATED NOW ######################################## +Lot's to go in here but for now this is holding my planning and thoughts until can set in stone: + + +## Copied over from client todo while testing / planning, probably outdated if you're reading this after May 2020 + +todo: PLANNING WORKORDER considerations: + QUESTIONS: + Why do I need to make a wo first before I can update it? (i.e. why did I make a CREATE route?) + still no idea after lot's of planning, answer is probably not needed at all + + How can I avoid concurrency issues? + concurrency check each record in graph, not entire workorder from top + + How to minimize data sent, make fast saves? + I'm leaning towards the tons of routes option, need to test it out + + PATCH, send all changes in graph in one go + most efficient, sends all changes in one go + if any part fails it all fails + requires second copy of wo for diffing + UPDATE (PATCH): Send only changes in whole graph from client with an OP (for "operation") flag at each level indicating to change that part or not, a flag? + WO (OP flag=no change, no concurrency token, basically empty but for the fields that hold the descendants that are changed) + woitem 0 (OP flag="Delete" and concurrency token, no other data with it, just the id and flag and ctoken) + woitem 1 (OP flag ="update", all fields as in a "put" operation, nothing left out, assumed all are changed) + woitem2 (OP flag="no OP", just a placeholder for children with changes) + labor 2 (OP flag = "update" with all data) + labor 3 (OP flag="delete" with concurrency token and nothing else) + labor 4 (OP flag="Add", with all PUT data) + issues with patch: + how to post a whole object leaving blank when so many fields will be required? + maybe we don't make them required at the object field annotation level but only at the db level and as a biz rule? + how to synchronize objects and id's? + i.e. reverse patch back again + for example, you add two woitems, save, you have two now that are not id'd and don't know which is which + server has to return something identifying which is which and assigned ID, plus it might add data back or change data due to rules or whatever + Maybe server sends back entire saved objects? + issues: + how to update client end with update back from server when saved (server will add id and may change fields or even add things) + + * TONS OF ROUTES: Update individual portions as seperate objects to their own routes sequentially + i.e. client traverses and diffs virgin copy and edited copy of wo + determines what's different, only sends an update for each object to it's own route as appropriate + on successful update fixes up the edited copy of that object + on all updates done, the edited copy becomes the virgin copy (or do we need 3 objects at one point in case of fail?) + + requires second copy of wo for diffing + goes over workorder, looks for changes, sends update for each object individually and patches up local from result + so if a workorderitempart has changed then it sends only that for update individually + Example routes: + Post: Workorder/1/WorkOrderItem/2/Labor/4 {updated object} + WorkOrder/{woid} <-entire workorder, get for all, post for entire, put to update entire (not likely to use but?) + WorkOrder/{woid}/WorkOrderItems <- all workorderitems, post to add new, put to update all as a collection + WorkOrder/{woid}/WorkOrderItems/{woitemid} <- CRUD single woitemid + WorkOrder/{woid}/WorkOrderItems/{woitemid}/Labors <- entire labor collection CRUD ops over all collection (also ADD new labor here (POST)) + WorkOrder/{woid}/WorkOrderItems/{woitemid}/Labors/{laborid} <- Crud on individual item + + This way is pretty solid, will result in a lot of routes but a lot of the code can be shared in the biz object, so for example if updating a labor or a collection of labor most code the same + Efficiency: + Since there is a route for every bit of the workorder the client can pick how high up to update based on diff check + so if only one single bit of a header has changed then only update that bit (or will it need the collection to not remove it? No because collection route is where you remove an item) + or if only a deeply nested labor has changed, just PUTS it to that exact route and udpates concurrency token on result + since the workorder is not really influenced as a whole by updates to portions this could work and be a bit less problematic than JSONPATCH which really seems to be a bit of a stretch + + +NOTE: can put part of the route in the controller, so for example if every route in that controller needs to identify a workorder then this kind of thing is possible, not sure if helpful or not yet: +[Route("api/campus/{campusId:int}/building")] +public class BuildingController : Controller { + //... + + [HttpGet] + [Route("{buildingId:int}")] // Matches GET api/campus/123/building/456 + public IActionResult GetBuilding ([FromRoute]int campusId, [FromRoute]int buildingId) { + //... validate campus id along with building id + } +} + + issues: + very chatty, could be slow + + PUT, update entire workorder on every save + Very easy to code, basically send it all and see what happens + Very clean, no need to worry about bits and pieces being tracked etc + issues: + not very efficient, needs to send entire graph on every save even if user just changed one character + + + How to support undo? + How to show what's dirty on form? + + + + BUSINESS RULES (v7) + In reality there are almost no business rules in v7 workorder graph. + Only serious one is woitempart requires serial if serialized + Rest are all related to length of fields, required fields, date order etc and only a few of those to boot + Looks like this is not an issue regarding v7 stuff at all + + + DEPENDENCIES + Workorder is not dependent on it's children for anything + WoItem is not dependent on any of it's children + In fact nothing in any part of the wo is dependent on anything else during normal ops + + CONCURRENCY + If the client updates part of the wo graph, only that exact record really needs dependency checking. + There *is* however business rules that might take hold but that's all at the server and not related to concurrency directly + For example, on any change to the wo graph the server has to see if the wo is still editable and hasn't been locked or user's rights changed + But that's not strictly concurrency related in the sense that another user change the *same* record being updated + So, for v8 as long as it can handle a portional update to part of the graph and uses the concurrency of that exact record to check then it sidesteps a lot of multi-user scenarios + This was only an issue in v7 due to it using only the wo header itself as the source of concurrency checking which would *always* involve the whole graph in any change anywhere + + for example: + WOHEADER (concurrency id, dirty flag at client) + WOITEM (concurrency id, dirty flag at client) + woitempart (concurrencyid dirty flag at client) + woitemlabor (concurrencyid, dirty flag at client) + WOITEM (concurrency id, dirty flag at client) + woitemscheduser (own concurrency, dirty flag etc) + woitempart (concurrencyid dirty flag at client) + woitemlabor (concurrencyid, dirty flag at client) + + ROUTES + In light of dependencies and concurrency it is ideal if the server can handle updates to any portion of the graph independently + But, do we really want CRUD routes for every descendant of the workorder graph? (maybe, just not sure) + + + + TEST + Do a practical test of a mocked wo, woitem, woitemlabor or whatever, see how it would be updated, fetched concurrency checking etc + QUESTIONS: + How to do CRUD efficiently with a workorder and client? + + + PROPOSAL TO TEST: + Create enough of a graph to test, 3 layers two grandhild collections should be sufficient: + WO + WOITEMS + WOITEMLABORS + WOITEMPARTS + + CREATE (POST): + CreateFromxxxx routes (NO TEST REQUIRED) + POST accepts NEW workorder full graph (test) + RETRIEVE (GET): + Get(id) - simple get, just confirm entire graph comes across + GetByRelative(ayatype, id) (no test required) + + UPDATE (PUT?) + Test code tons of routes method detailed above + + SERVER + Server accepts graph at single WO POST route (since it's not a put) + UI + ui manufactures the return object with the OP fields by doing dirty tracking on changes + DELETE + Not much here except handling delete will be more intensive and sophisticated when have real data but for now if the graph deletes then that's enough + Test how to delete graph without ref. integrity errors + + + UI + Only send the bits that are altered to save bandwidth + All updates are technically a PATCH operation + Because it starts with a wo object provided by the server? + or is this even necessary now? + think Patch + CONCURRENCY: + if any part of the patch fails the whole patch fails + + idea: UI reflects tentativeness state of object: + The UI doesn't imply something is done by changing it fully until the save is completed. + This serves two purposes: + 1) user knows at a glance what isn't saved yet and will know it's waiting for save clearly, hopefully leading them to save more often, + 2) client doesn't need to track invisible shit behind the scenes, can more easily do patch updates right off UI source + + e.g.: + if deleted a row in parts, that row doesn't disappear but rather shows crossed out, maybe grayed out but still there until save to indicate it's tentative status + if added a row, shows green or something or bold or asterisk, (can style with css based on state) until saved + problems: + how to handle regular fields that are changed (that's a lot of field data to track for changes)? + Maybe client keeps a virgin copy of the original wo for comparison + periodically does a compare and flags differences on updates? + (this would also help to serve as an Undo maybe?) + + + + A biz object for each one? + probably need the parent for biz rules and shit so likely best to keep in one file + Controller - all in root controller or seperate controllers? + likely follows biz object decision + case 1714 re-rises the question about concurrency and mutiple editors of a workorder + Look into how independent changes can be from each other, i.e. is it safe to have two users editing two different woitems on a workorder? + This might make people happier. + Like, what exactly affects what else on a workorder. Do you save the whole wo to the route at once even though you just added a woitem or..? + If I code it to send the whole wo on a change to even a grandchild then that's heavy traffic for a minor change + - actually no, it's not really that heavy, even a fairly fat workorder will be way under 100kb, most probably under 1kb + should really only send the minimum data required to fulfil the change. + Maybe need two copies of wo at client so can tell what has changed and then only send that bit. + But then need routes to handle that? + Or can the wo route just accept a blank header with items hanging off it that have changed only? (like a patch?) + + Use foreign keys!! + Consider UI in this as well, will need to decide at least what is visible when + Workorder UI good ideas here: https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/3475 + How to add items, like new woitem? + send to server get back new object? + lots of biz rules and stuff need to happen, want to minimize load at client + but lots of data back and forth is not ideal + maybe request a woitem and get it back? + what exactly needs to be processed in the wo when items are added / removed? + math / totalling? + simple calcs sb client doable + this will drive what has to happen. + Need to go over all wo features and factor them into this decision properly + The whole idea of a completed section of a wo and stuff, is that dropped due to TTM or still viable? + maybe can pick out the best new features of that which can be integrated into existing design rather than re-inventing the wheel + Here is an overview: https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/3412 + How best to be able to service LoanUnits on a workorder? + Just make them Units with extra properties exposed if type of loaner? + This seems simplest, but what will it effect? + Hard to make them serviceable if they are an alternate table of source for what's being repaired as that breaks a lot of other code or adds exceptions + Customer is then who exactly because it's fundamental to a lot of wo functionality? + from a biz perspective isn't it like you are your own customer when you service your own equipment that you loan out? + Does Serial field need to be numeric, could it be text instead? + prompted by case 3428 saying that it's hard to deal with constant conversion to text for UI etc + plus, I'm thinking it opens door to textual scheme like appending -A or whatever to a wo. + or, is that a display issue? + Calling something "serial" implies it's unique but it isn't, maybe I should call it "number" instead or "ID" or something? + INFO: did a test workorder with ALL fields filled out heavily and one woitem, exported from db entire graph based on detailed report so every line was every item repeated + still only 84kb and it's a lot bigger than any typical wo in v8 would be as it will be far more efficient without having to repeat lines flatly + so I think size of object is a non-issue really from a practical standpoint. + + diff --git a/devdocs/specs/dispatch-zone.txt b/devdocs/old-devdocs/specs/dispatch-zone.txt similarity index 96% rename from devdocs/specs/dispatch-zone.txt rename to devdocs/old-devdocs/specs/dispatch-zone.txt index c2d723d4..a2d18f47 100644 --- a/devdocs/specs/dispatch-zone.txt +++ b/devdocs/old-devdocs/specs/dispatch-zone.txt @@ -1,12 +1,12 @@ -DISPATCH ZONE SPECS - -CASES - -3472, 3439 - -REQUIREMENTS - -Dispatch zones will be replaced by tags now for users and also will replace scheduleable user groups -I've examined the use cases, v7 usage, new cases for raven and nothing indicates we can't use tags for this with the added feature of tag groups which is a good idea anyway. -TAGS all the things!! - +DISPATCH ZONE SPECS + +CASES + +3472, 3439 + +REQUIREMENTS + +Dispatch zones will be replaced by tags now for users and also will replace scheduleable user groups +I've examined the use cases, v7 usage, new cases for raven and nothing indicates we can't use tags for this with the added feature of tag groups which is a good idea anyway. +TAGS all the things!! + diff --git a/devdocs/specs/hosting.txt b/devdocs/old-devdocs/specs/hosting.txt similarity index 99% rename from devdocs/specs/hosting.txt rename to devdocs/old-devdocs/specs/hosting.txt index 1815ef7f..cd35d9cc 100644 --- a/devdocs/specs/hosting.txt +++ b/devdocs/old-devdocs/specs/hosting.txt @@ -1,14 +1,14 @@ -HOSTING - -We will be hosting users in rental mode and for trialling, we need systems in place to support that automatically, see core-trial-evaluation doc for more details - -- We need a management console to view the load on our server and to alert us to slowdowns so we can expand the virtual server, also we need to be able to do it in more than one datacenter as we would want local endpoints for users ultimately -- We need to be able to tell if a specific AyaNova server is consuming disproportionate resources. -- We need some kind of way to cap the load on a server autoamtically so they can't just have thousands of clients attempting to connect at once (i.e. they should self host if they are over a certain size / bandwith usage) -- RockFish or some other application needs to be able to spin up a new server and db combo that is unique (docker container?) automatically and prune or get rid of it completely after XX days after trial has expired and it is still unlicensed -- Rockfish automatic trial key fulfillment and delivery and installation -- RAVEN built in form to request trial key and automatic fulfillment and install including db is erased any time a trial key is installed when a user already has a trial or no key installed -- RAVEN built in purchase feature -- Rockfish built in ability to work with built in purchase to license a user and for RAVEN to check in with for new license info (i.e. monthly rental charge and license fulfillment) - - +HOSTING + +We will be hosting users in rental mode and for trialling, we need systems in place to support that automatically, see core-trial-evaluation doc for more details + +- We need a management console to view the load on our server and to alert us to slowdowns so we can expand the virtual server, also we need to be able to do it in more than one datacenter as we would want local endpoints for users ultimately +- We need to be able to tell if a specific AyaNova server is consuming disproportionate resources. +- We need some kind of way to cap the load on a server autoamtically so they can't just have thousands of clients attempting to connect at once (i.e. they should self host if they are over a certain size / bandwith usage) +- RockFish or some other application needs to be able to spin up a new server and db combo that is unique (docker container?) automatically and prune or get rid of it completely after XX days after trial has expired and it is still unlicensed +- Rockfish automatic trial key fulfillment and delivery and installation +- RAVEN built in form to request trial key and automatic fulfillment and install including db is erased any time a trial key is installed when a user already has a trial or no key installed +- RAVEN built in purchase feature +- Rockfish built in ability to work with built in purchase to license a user and for RAVEN to check in with for new license info (i.e. monthly rental charge and license fulfillment) + + diff --git a/devdocs/specs/joyce-planning-docs-used/1_Roles.odt b/devdocs/old-devdocs/specs/joyce-planning-docs-used/1_Roles.odt similarity index 100% rename from devdocs/specs/joyce-planning-docs-used/1_Roles.odt rename to devdocs/old-devdocs/specs/joyce-planning-docs-used/1_Roles.odt diff --git a/devdocs/specs/joyce-planning-docs-used/2014-06-24--partsinventoryoverviewDONE.odt b/devdocs/old-devdocs/specs/joyce-planning-docs-used/2014-06-24--partsinventoryoverviewDONE.odt similarity index 100% rename from devdocs/specs/joyce-planning-docs-used/2014-06-24--partsinventoryoverviewDONE.odt rename to devdocs/old-devdocs/specs/joyce-planning-docs-used/2014-06-24--partsinventoryoverviewDONE.odt diff --git a/devdocs/specs/joyce-planning-docs-used/2017-11-22--1_DONEPOandPOReceipt.odt b/devdocs/old-devdocs/specs/joyce-planning-docs-used/2017-11-22--1_DONEPOandPOReceipt.odt similarity index 100% rename from devdocs/specs/joyce-planning-docs-used/2017-11-22--1_DONEPOandPOReceipt.odt rename to devdocs/old-devdocs/specs/joyce-planning-docs-used/2017-11-22--1_DONEPOandPOReceipt.odt diff --git a/devdocs/specs/joyce-planning-docs-used/JoyceOriginalFiles/joycev8files.zip b/devdocs/old-devdocs/specs/joyce-planning-docs-used/JoyceOriginalFiles/joycev8files.zip similarity index 100% rename from devdocs/specs/joyce-planning-docs-used/JoyceOriginalFiles/joycev8files.zip rename to devdocs/old-devdocs/specs/joyce-planning-docs-used/JoyceOriginalFiles/joycev8files.zip diff --git a/devdocs/specs/joyce-planning-docs-used/MainDiff - JohnsCopyOLDfrom JUNE26.odt b/devdocs/old-devdocs/specs/joyce-planning-docs-used/MainDiff - JohnsCopyOLDfrom JUNE26.odt similarity index 100% rename from devdocs/specs/joyce-planning-docs-used/MainDiff - JohnsCopyOLDfrom JUNE26.odt rename to devdocs/old-devdocs/specs/joyce-planning-docs-used/MainDiff - JohnsCopyOLDfrom JUNE26.odt diff --git a/devdocs/specs/joyce-planning-docs-used/Workorder.odt b/devdocs/old-devdocs/specs/joyce-planning-docs-used/Workorder.odt similarity index 100% rename from devdocs/specs/joyce-planning-docs-used/Workorder.odt rename to devdocs/old-devdocs/specs/joyce-planning-docs-used/Workorder.odt diff --git a/devdocs/specs/marketing-sales-planning.txt b/devdocs/old-devdocs/specs/marketing-sales-planning.txt similarity index 98% rename from devdocs/specs/marketing-sales-planning.txt rename to devdocs/old-devdocs/specs/marketing-sales-planning.txt index 42044784..ee459204 100644 --- a/devdocs/specs/marketing-sales-planning.txt +++ b/devdocs/old-devdocs/specs/marketing-sales-planning.txt @@ -1,276 +1,276 @@ -MARKETING AND SALES IDEAS - -This was interesting: https://getpocket.com/explore/item/tapping-into-the-power-of-humble-narcissism -"The first kind of humility is humility about your ideas. Take Rufus Griscom (TED Talk, given with Alisa Volkman: Let’s talk parenting taboos). When he founded the parenting blog Babble, he did something I’ve never seen an entrepreneur do. He said, “Here are the three reasons you should not invest in my company” — and he walked away with $3.1 million in funding that year. Two years later, he went to pitch Babble to Disney, and he included a slide in his pitch deck that read, “Here are the five reasons you should not buy Babble.” Disney acquired it for $40 million. - -By speaking candidly about the downsides of his idea, Rufus made his comments about the upsides more credible. Admitting the flaws outright also made it tougher for investors to come up with their own objections. The harder they had to work to identify what was wrong with the company, the more they thought was right with the company. The conversation changed: his investors proposed solutions to the problems. - -If you ever took a debate class, you were taught to identify the weaknesses in your argument and address them out loud. But we forget to do this when we pitch our ideas: we worry that they’re fragile and we don’t want to shoot ourselves in the foot. We overlook the fact that we’ll actually seem more credible and trustworthy — and other people will see more potential in our ideas — if we have the humility to acknowledge their limitations." - - -We will have two markets: - -SAAS rental market - - User pays monthly fee to use RAVEN on our servers - - Pricing will be a factor of how many scheduleable users, accounting add-on and some kind of protection for us relating to bandwidth and number of simultaneous users - - Taking into account support and upkeep costs, hosting costs etc - - One flat price per month, as long as they keep paying they keep using and will get automatically updated and support included - - When they stop paying they can no longer use it but we won't delete the data immediately but give them time and warnings before we do - - User has the option to switch to a perpetual license by buying one in which case they can then run it self hosted or elsewhere - - This is important to marketing because it removes one of the negative preconceptions around risk using an online service (vendor bankruptcy kind of issues) - -Perpetual market with maintenance subscriptions - - User buys a perpetual license for the software itself - - specifically this means they buy service tech licenses to add in single or groups with discount per group (to be determined based on what makes us the most money and target market) - - User pays for support and updates subscription either monthly, yearly or 3 yearly with increasing discounts for each - - User can update at any time while active - - - -WHAT WE ARE SELLING - -SAAS RENTAL - The ability to use the software for month to month priced by number of techs, accounting addon and whatever we deem to be the fair price to us for server hosting plus bandwidth overages - - ideally charge them for a 20 dollar server but use a 10 dollar server kind of thing - -Perpetual: -AyaNova service technician licenses by count with sliding discount for volume purchases at time of purchase -Accounting add-on -Maintenance subscription for support and updates - - First purchase includes one year of support and udpates (or maybe a shorter time frame at a lower price? Have to research that to see what gets the most revenue) - - Subsequent years are at a rate based on whether they have the accounting add-on (one flat price) and so many dollars per service tech but sliding scale so costs less the more techs - -PHRASING -Marketing will sell the licenses with the phrase "service technician" or whatever the most universal equivalent is with a blurb at the top -explaining that a "service Tech" just means anything you schedule so could be busses or etc, but then forever afterwards just say service tech as it's less confusing - - - - - -WORKSHEET PLANNING STUFF FOLLOWS: - - -POTENTIAL NEW LICENSING SYSTEMS - -What we need: - - Absolutely need recurring revenue, no two ways about that, it's our bread and butter - - Ease of administration and ease of billing procedures - - Automated system as much as possible for both us and the client - -What our customers need - - Clear and easily explainable costs - - Ease of purchase and control over billing system - - Easy to upgrade or downgrade the level of licenses and options - - A reason to keep paying and not simply cancel a subscription when it suits them - - - -SUBSCRIPTION / RENTAL / SAAS LICENSE - - Users pay a subscription fee to be able to use the software - - Includes support and updates as long as their subscription is active - - Software does not work without a subscription at all, they are renting the software - - Quote from a link below: Prices for annual subscriptions are generally some fraction of the perpetual license alternative. - Many companies aim for a crossover point of 4 to 5 years after which the costs for the annual license begin to exceed the perpetual license fee plus the annual support costs. - So, an annual license might be priced at 40% of a perpetual license. - - Not sure about that math - - -SAAS PRICING MODELS COMMONLY USED - -FLAT RATE - - Same flat price for everything for everybody, i.e. 300 a month all in - - PROS: Easy to sell, market and explain - - CONS: rarely used less precedent, harder to extract value from different market segments, you get one basically, no flexibility for the customer - - -USAGE BASED - - Charged based on actual usage, some metric from the software, perhaps number of records or speed of access or space consumed or something - - Workorders per month or scheduled items per month would be a good metric for us - - Often used for scenarios where someone is hosting something and paying for the costs to host it, i.e. if we were hosting for people - - PROS: price scales with use, reduces barriers to use, scales for heavy users compensating for extra costs - - CONS: rarely used less precedent, harder to predict revenue, harder to predict costs for the end user, - -CAPACITY / INFRASTRUCTURE * - - Based on something that represents the size of the company - - We sort of do this now with the price per scheduled user tiers - - Normally it's done with some kind of hardware or other consideration such as the size of the server in use based on the number of CPU cores on the machine - - Idea is it's cheap for a small company and more for a larger company - -TIERED PRICING * - - Multiple packages at different price Points (MOSTLY THIS IS ABOUT VOLUME, NOT FEATURE DIFFERENCES SPECIFICALLY) - - Usually Small, medium and large (3.5 options is the average) - - Basic, Pro, Enterprise - - Targets a customer type for each tier trying to take into effect the needs at each tier with an appropriate level of service - - - PROS: - - Commonly used pricing model so easier to market and for people to understand and compare due to familiarity - - appeals to multiple buyer personas better chance of a sale - - maximize revenue (offering a single $100 package will overcharge users with a $10 willingness to pay, and undercharge users willing to spend $200.) - - clear upselling route - - CONS: - - Potentially confusing (Do not have too many tiers, maybe 3 with an out for excessive costs to us like too much bandwidth or too many support requests) - - Appeals to too many people (don't try to have a tier for every segment) - - Heavy user risk (if top people exceed expected costs no room to move them up [This would be solved by having some kind of cap and overage charges I guess]) - - -PER USER PRICING - - Exactly what it says, per POTENTIAL user of the software. 1 user one price, 2 users double the price 3 treble etc etc. - - Paid monthly or annually (discount of 12% for example) - - PROS: Simple, revenue scales with users, predictable revenue - - CONS: Hard to track, limits adoption as it can get expensive and so people might hold off too many users which increases churn due to less users tied to prodcut, rewards cheating, doesn't reflect real value; company doesn't see the difference from one user to 5 for them - - -PER ACTIVE USER PRICING - - Only charge per active user, don't pay for accounts that are unused - - Often targetted at Enterprise level customers - - Slack is a famous example - - PROS: Customers only pay for what they actually use so reduces their risk of widespread adoption as it won't cost any more if they end up not using it - - CONS: Not much value to a smaller business so extra incentive, not idea for us because it means we don't have defined recurring revenue just like the USAGE BASED model - - -PER FEATURE PRICING - - "Features" as value metric, not "users" (kind of a mix of what we do now) - - Tiers as in TIERED PRICING but by packages with sets of features more than by usage - - PROS: strong upgrade incentive, Compensate for delivery heavy (expensive to provide) features - - CONS: Difficult to get right (hard to determine which features go in which package could get ugly), Leaves a bad taste / easier to feel resentful for the customer as they know they could be getting more - - -FREEMIUM PRICING - - Tier but with a free level to hook people in. - - Pricing begins along a dimension of features, capacity or use case (you can use it to do this but not to do that; e.g. not free for commercial use) - - PROS: foot in the door, viral marketing potential for word of mouth - - CONS: Revenue killer; all revenue to support free needs to come from paid, increases churn, can devalue your core service - - - -=-=-=-=-=-=-=-=-=-=-=- - -OUR PRICING STRATEGY - - What is our pricing strategy? - - Example pricing strategies - - Penetration Pricing: "land and expand" initial unsustainably low pricing for short to medium time period to grab a market then upsell later once you have a big base - - Captive pricing: low intial price for "core" product but lot's of add-on's that are required to really use it and those generate the revenue (inkjet printers) - - Skimming pricing: start with an initial high price and slowly lower it over time (not sure this works in our market) - - Prestige pricing: maintain a high price to convey prestige or have a high prestige tier (with a rounded price $500 not $499.99) - - Free trial pricing: free month then charge to continue usage. Industry average is 50% adoption rate after free trial and 30 days is the average length - - - I want it to be easy enough to sell that we never have to hard sell anyone on it or waste time convincing them, we don't want to have to do "sales" at all - - Penetration or low pricing will give us growth and our expenses are not high so the more recurring revenue from as many sources as possible the better. - - Rather see 500 low price customers than try to fight to keep 3 high price ones, far less risk - - Possibly this means that we would take an average less profit on each sale - - I'd like to see all options available for all users as much as possible. Maybe tiers based on scheduleable resources still? But that's hard to understand for users. - - - -=-=-=-=-=- -PRICING PSYCHOLOGY - - Price Anchoring: - - set an anchor price by highlighting the most expensive package first on the marketing page so that people judge the other prices by comparison to it - - Maybe make the leftmost the most expensive or just otherwise highlight the most expensive so eyes are drawn to it first - - Always start with the most expensive price first when marketing or discussing with a customer - - Charm pricing - - People heavily judge the leftmost digit in the price subconsciously so don't sell for $400 sell for $399; people see the 3 and mentally get stuck on it - - Odd Even pricing - - People might be getting used to the .99 thing so don't end in .99, use .98 or .23 or whatever instead just keep the first digit low - - Product bundle pricing - - bundle shit together; causes people to think outcomes rather than about the individual prices - - Analysis paralysis - - Do not offer more too many options (research suggests 7 options plus or minus 2. So 5 or less is safest.) - - The biggest, most successful SaaS companies have an average of 3.5 packages available on their pricing pages. - - Center stage effect - - use the center column of multiple prices as the "most popular", or one we want to sell the most of; people will choose it more often by default all things being equal. - - - - -REQUIREMENTS - -- JSON format -- secured with hash signature -- All licensed things are in a collection, not just the add-ons - - scheduledusers, accounting etc. -- Old versions should work with new licenses but not the reverse -- Has an ID and source values like current keys, ID may become much more important in future -- ALL TRIAL KEYS ARE REGISTERED TO SOMEONE NO SUCH THING AS TWO LICENSES IN CIRCULATION WITH THE SAME NAME (i.e. no more "Unregistered trial" meaning it's a trial, every user will have a specific name to test it out) - - Rockfish issues the trial key upon first request to empty db - - Need indicator that it's a trial key / evaluation key - -- All licensed things should each have an expiry date possible to turn off that feature - - In the case of options they just stop working - - In the case of main user license everything stops working -- MUST be able to support monthly billing cycle (automatic license installation or approval so user doesn't have to install key every month) - - Rockfish should have a licensed yay or nay or new available route for RAVEN to check periodically and also users can trigger a force check -- RAVEN checks periodically for new license to fetch in line with billing cycle or expiry cycle. - - SAFE fallback if can't contact license server and allow a few misses before something kicks in, but not to allow people to use unlimited by blocking rockfish for example -- Support both perpetual license with rental maintenance subscription and rental license - - Need expiry date for maintenance so code can query if eligable for updates or support requests - - Need expiry date for entire license for rental and trial scenarios -- Support update restriction based on build date and license - -- ?? what about the add-on's expiring at the same time as the sched users. currently the expiration dates differing is a hassle, should it be still supported?? -- ?? what if we are not licensing by scheduled users anymore but by something else -- ?? need to analyze sales and determine the percentage of each level of license issued so I can group into tiers - - Current (5/29/2018) active subscription licenses: - - Single = 35 - - Up to 5 = 18 - - Up to 10 = 10 - - Up to 15 = 1 - - Up to 20 = 12 - - up to 50 = 0 - - Up to 999 = 0 - - QBI - - QBOI - - PTI - - WBI - - RI - - MBI - - OLI - - OutLookScheduleExport - - -Maybe what is needed is: - - A single license expiry date no matter what is in the license - - A single support and updates date no matter what is in the license - - A single license "type" to support tiered pricing - - Tiers: 1 user, up to 10, up to 100, custom? - - Discussed with Joyce and she made a good case for one by one license sales as most customers are small and tiers may not help as they are in the 10 and under stage anyway - so maybe no tiers at all, just licenses for "service technicians" or some more generic term and make a not early that a "service technician" is any scheduleable resource - and then cotinue to use the term service technician afterwards because it's what the majority are scheduling and it is far easier to explain. - For the rental market though we will really need to take into account bandwidth so in future there may be more types of things to track. - - - - - - - -PRODUCT LICENSE CHANGES FROM v7 - - -Still optional and purchased separately as a single Accounting interface option: -QBOI, QBI, PTI - -Possible idea: sold as "Accounting add on" and the user can use one of those of their choice and can switch which means 1 product instead of three which might make keys easier. - Possible downside is that we can't track who uses what or what we sell how much of so puts a kink in marketing or planning for deprecation or where to spend - effort, however there are other ways of addressing that. - - -//INCLUDED ADD-ON's -OLI - INCLUDED / TURNED INTO GENERIC FEATURE IMPORT / EXPORT CONTACTS and SCHEDULE TO ICAL -OutLookScheduleExport - INCLUDED / TURNED INTO GENERIC SCHED EXPORT ICAL FORMAT -Export to xls - Included with RAVEN -QuickNotification - Included with RAVEN -ImportExportDuplicate - Included with RAVEN -RI/WBI/MBI - UNNECESSARY with RAVEN - - - -===================================== - -RESEARCH SOURCES -- http://www.reprisesoftware.com/blog/2017/08/implement-a-recurring-revenue-license-model/ -- https://www.linkedin.com/pulse/20140819084845-458042-the-change-from-perpetual-to-subscription-based-software-licensing -- http://software-monetization.tmcnet.com/articles/429528-long-but-rewarding-road-a-recurring-revenue-model.htm -- How to calculate pricing in a service business: https://www.patriotsoftware.com/accounting/training/blog/how-pricing-services-strategies-models-formula/ +MARKETING AND SALES IDEAS + +This was interesting: https://getpocket.com/explore/item/tapping-into-the-power-of-humble-narcissism +"The first kind of humility is humility about your ideas. Take Rufus Griscom (TED Talk, given with Alisa Volkman: Let’s talk parenting taboos). When he founded the parenting blog Babble, he did something I’ve never seen an entrepreneur do. He said, “Here are the three reasons you should not invest in my company” — and he walked away with $3.1 million in funding that year. Two years later, he went to pitch Babble to Disney, and he included a slide in his pitch deck that read, “Here are the five reasons you should not buy Babble.” Disney acquired it for $40 million. + +By speaking candidly about the downsides of his idea, Rufus made his comments about the upsides more credible. Admitting the flaws outright also made it tougher for investors to come up with their own objections. The harder they had to work to identify what was wrong with the company, the more they thought was right with the company. The conversation changed: his investors proposed solutions to the problems. + +If you ever took a debate class, you were taught to identify the weaknesses in your argument and address them out loud. But we forget to do this when we pitch our ideas: we worry that they’re fragile and we don’t want to shoot ourselves in the foot. We overlook the fact that we’ll actually seem more credible and trustworthy — and other people will see more potential in our ideas — if we have the humility to acknowledge their limitations." + + +We will have two markets: + +SAAS rental market + - User pays monthly fee to use RAVEN on our servers + - Pricing will be a factor of how many scheduleable users, accounting add-on and some kind of protection for us relating to bandwidth and number of simultaneous users + - Taking into account support and upkeep costs, hosting costs etc + - One flat price per month, as long as they keep paying they keep using and will get automatically updated and support included + - When they stop paying they can no longer use it but we won't delete the data immediately but give them time and warnings before we do + - User has the option to switch to a perpetual license by buying one in which case they can then run it self hosted or elsewhere + - This is important to marketing because it removes one of the negative preconceptions around risk using an online service (vendor bankruptcy kind of issues) + +Perpetual market with maintenance subscriptions + - User buys a perpetual license for the software itself + - specifically this means they buy service tech licenses to add in single or groups with discount per group (to be determined based on what makes us the most money and target market) + - User pays for support and updates subscription either monthly, yearly or 3 yearly with increasing discounts for each + - User can update at any time while active + + + +WHAT WE ARE SELLING + +SAAS RENTAL + The ability to use the software for month to month priced by number of techs, accounting addon and whatever we deem to be the fair price to us for server hosting plus bandwidth overages + - ideally charge them for a 20 dollar server but use a 10 dollar server kind of thing + +Perpetual: +AyaNova service technician licenses by count with sliding discount for volume purchases at time of purchase +Accounting add-on +Maintenance subscription for support and updates + - First purchase includes one year of support and udpates (or maybe a shorter time frame at a lower price? Have to research that to see what gets the most revenue) + - Subsequent years are at a rate based on whether they have the accounting add-on (one flat price) and so many dollars per service tech but sliding scale so costs less the more techs + +PHRASING +Marketing will sell the licenses with the phrase "service technician" or whatever the most universal equivalent is with a blurb at the top +explaining that a "service Tech" just means anything you schedule so could be busses or etc, but then forever afterwards just say service tech as it's less confusing + + + + + +WORKSHEET PLANNING STUFF FOLLOWS: + + +POTENTIAL NEW LICENSING SYSTEMS + +What we need: + - Absolutely need recurring revenue, no two ways about that, it's our bread and butter + - Ease of administration and ease of billing procedures + - Automated system as much as possible for both us and the client + +What our customers need + - Clear and easily explainable costs + - Ease of purchase and control over billing system + - Easy to upgrade or downgrade the level of licenses and options + - A reason to keep paying and not simply cancel a subscription when it suits them + + + +SUBSCRIPTION / RENTAL / SAAS LICENSE + - Users pay a subscription fee to be able to use the software + - Includes support and updates as long as their subscription is active + - Software does not work without a subscription at all, they are renting the software + - Quote from a link below: Prices for annual subscriptions are generally some fraction of the perpetual license alternative. + Many companies aim for a crossover point of 4 to 5 years after which the costs for the annual license begin to exceed the perpetual license fee plus the annual support costs. + So, an annual license might be priced at 40% of a perpetual license. + - Not sure about that math + + +SAAS PRICING MODELS COMMONLY USED + +FLAT RATE + - Same flat price for everything for everybody, i.e. 300 a month all in + - PROS: Easy to sell, market and explain + - CONS: rarely used less precedent, harder to extract value from different market segments, you get one basically, no flexibility for the customer + + +USAGE BASED + - Charged based on actual usage, some metric from the software, perhaps number of records or speed of access or space consumed or something + - Workorders per month or scheduled items per month would be a good metric for us + - Often used for scenarios where someone is hosting something and paying for the costs to host it, i.e. if we were hosting for people + - PROS: price scales with use, reduces barriers to use, scales for heavy users compensating for extra costs + - CONS: rarely used less precedent, harder to predict revenue, harder to predict costs for the end user, + +CAPACITY / INFRASTRUCTURE * + - Based on something that represents the size of the company + - We sort of do this now with the price per scheduled user tiers + - Normally it's done with some kind of hardware or other consideration such as the size of the server in use based on the number of CPU cores on the machine + - Idea is it's cheap for a small company and more for a larger company + +TIERED PRICING * + - Multiple packages at different price Points (MOSTLY THIS IS ABOUT VOLUME, NOT FEATURE DIFFERENCES SPECIFICALLY) + - Usually Small, medium and large (3.5 options is the average) + - Basic, Pro, Enterprise + - Targets a customer type for each tier trying to take into effect the needs at each tier with an appropriate level of service + + - PROS: + - Commonly used pricing model so easier to market and for people to understand and compare due to familiarity + - appeals to multiple buyer personas better chance of a sale + - maximize revenue (offering a single $100 package will overcharge users with a $10 willingness to pay, and undercharge users willing to spend $200.) + - clear upselling route + - CONS: + - Potentially confusing (Do not have too many tiers, maybe 3 with an out for excessive costs to us like too much bandwidth or too many support requests) + - Appeals to too many people (don't try to have a tier for every segment) + - Heavy user risk (if top people exceed expected costs no room to move them up [This would be solved by having some kind of cap and overage charges I guess]) + + +PER USER PRICING + - Exactly what it says, per POTENTIAL user of the software. 1 user one price, 2 users double the price 3 treble etc etc. + - Paid monthly or annually (discount of 12% for example) + - PROS: Simple, revenue scales with users, predictable revenue + - CONS: Hard to track, limits adoption as it can get expensive and so people might hold off too many users which increases churn due to less users tied to prodcut, rewards cheating, doesn't reflect real value; company doesn't see the difference from one user to 5 for them + + +PER ACTIVE USER PRICING + - Only charge per active user, don't pay for accounts that are unused + - Often targetted at Enterprise level customers + - Slack is a famous example + - PROS: Customers only pay for what they actually use so reduces their risk of widespread adoption as it won't cost any more if they end up not using it + - CONS: Not much value to a smaller business so extra incentive, not idea for us because it means we don't have defined recurring revenue just like the USAGE BASED model + + +PER FEATURE PRICING + - "Features" as value metric, not "users" (kind of a mix of what we do now) + - Tiers as in TIERED PRICING but by packages with sets of features more than by usage + - PROS: strong upgrade incentive, Compensate for delivery heavy (expensive to provide) features + - CONS: Difficult to get right (hard to determine which features go in which package could get ugly), Leaves a bad taste / easier to feel resentful for the customer as they know they could be getting more + + +FREEMIUM PRICING + - Tier but with a free level to hook people in. + - Pricing begins along a dimension of features, capacity or use case (you can use it to do this but not to do that; e.g. not free for commercial use) + - PROS: foot in the door, viral marketing potential for word of mouth + - CONS: Revenue killer; all revenue to support free needs to come from paid, increases churn, can devalue your core service + + + +=-=-=-=-=-=-=-=-=-=-=- + +OUR PRICING STRATEGY + - What is our pricing strategy? + - Example pricing strategies + - Penetration Pricing: "land and expand" initial unsustainably low pricing for short to medium time period to grab a market then upsell later once you have a big base + - Captive pricing: low intial price for "core" product but lot's of add-on's that are required to really use it and those generate the revenue (inkjet printers) + - Skimming pricing: start with an initial high price and slowly lower it over time (not sure this works in our market) + - Prestige pricing: maintain a high price to convey prestige or have a high prestige tier (with a rounded price $500 not $499.99) + - Free trial pricing: free month then charge to continue usage. Industry average is 50% adoption rate after free trial and 30 days is the average length + + - I want it to be easy enough to sell that we never have to hard sell anyone on it or waste time convincing them, we don't want to have to do "sales" at all + - Penetration or low pricing will give us growth and our expenses are not high so the more recurring revenue from as many sources as possible the better. + - Rather see 500 low price customers than try to fight to keep 3 high price ones, far less risk + - Possibly this means that we would take an average less profit on each sale + - I'd like to see all options available for all users as much as possible. Maybe tiers based on scheduleable resources still? But that's hard to understand for users. + + + +=-=-=-=-=- +PRICING PSYCHOLOGY + - Price Anchoring: + - set an anchor price by highlighting the most expensive package first on the marketing page so that people judge the other prices by comparison to it + - Maybe make the leftmost the most expensive or just otherwise highlight the most expensive so eyes are drawn to it first + - Always start with the most expensive price first when marketing or discussing with a customer + - Charm pricing + - People heavily judge the leftmost digit in the price subconsciously so don't sell for $400 sell for $399; people see the 3 and mentally get stuck on it + - Odd Even pricing + - People might be getting used to the .99 thing so don't end in .99, use .98 or .23 or whatever instead just keep the first digit low + - Product bundle pricing + - bundle shit together; causes people to think outcomes rather than about the individual prices + - Analysis paralysis + - Do not offer more too many options (research suggests 7 options plus or minus 2. So 5 or less is safest.) + - The biggest, most successful SaaS companies have an average of 3.5 packages available on their pricing pages. + - Center stage effect + - use the center column of multiple prices as the "most popular", or one we want to sell the most of; people will choose it more often by default all things being equal. + + + + +REQUIREMENTS + +- JSON format +- secured with hash signature +- All licensed things are in a collection, not just the add-ons + - scheduledusers, accounting etc. +- Old versions should work with new licenses but not the reverse +- Has an ID and source values like current keys, ID may become much more important in future +- ALL TRIAL KEYS ARE REGISTERED TO SOMEONE NO SUCH THING AS TWO LICENSES IN CIRCULATION WITH THE SAME NAME (i.e. no more "Unregistered trial" meaning it's a trial, every user will have a specific name to test it out) + - Rockfish issues the trial key upon first request to empty db + - Need indicator that it's a trial key / evaluation key + +- All licensed things should each have an expiry date possible to turn off that feature + - In the case of options they just stop working + - In the case of main user license everything stops working +- MUST be able to support monthly billing cycle (automatic license installation or approval so user doesn't have to install key every month) + - Rockfish should have a licensed yay or nay or new available route for RAVEN to check periodically and also users can trigger a force check +- RAVEN checks periodically for new license to fetch in line with billing cycle or expiry cycle. + - SAFE fallback if can't contact license server and allow a few misses before something kicks in, but not to allow people to use unlimited by blocking rockfish for example +- Support both perpetual license with rental maintenance subscription and rental license + - Need expiry date for maintenance so code can query if eligable for updates or support requests + - Need expiry date for entire license for rental and trial scenarios +- Support update restriction based on build date and license + +- ?? what about the add-on's expiring at the same time as the sched users. currently the expiration dates differing is a hassle, should it be still supported?? +- ?? what if we are not licensing by scheduled users anymore but by something else +- ?? need to analyze sales and determine the percentage of each level of license issued so I can group into tiers + - Current (5/29/2018) active subscription licenses: + - Single = 35 + - Up to 5 = 18 + - Up to 10 = 10 + - Up to 15 = 1 + - Up to 20 = 12 + - up to 50 = 0 + - Up to 999 = 0 + - QBI + - QBOI + - PTI + - WBI + - RI + - MBI + - OLI + - OutLookScheduleExport + + +Maybe what is needed is: + - A single license expiry date no matter what is in the license + - A single support and updates date no matter what is in the license + - A single license "type" to support tiered pricing + - Tiers: 1 user, up to 10, up to 100, custom? + - Discussed with Joyce and she made a good case for one by one license sales as most customers are small and tiers may not help as they are in the 10 and under stage anyway + so maybe no tiers at all, just licenses for "service technicians" or some more generic term and make a not early that a "service technician" is any scheduleable resource + and then cotinue to use the term service technician afterwards because it's what the majority are scheduling and it is far easier to explain. + For the rental market though we will really need to take into account bandwidth so in future there may be more types of things to track. + + + + + + + +PRODUCT LICENSE CHANGES FROM v7 + + +Still optional and purchased separately as a single Accounting interface option: +QBOI, QBI, PTI + +Possible idea: sold as "Accounting add on" and the user can use one of those of their choice and can switch which means 1 product instead of three which might make keys easier. + Possible downside is that we can't track who uses what or what we sell how much of so puts a kink in marketing or planning for deprecation or where to spend + effort, however there are other ways of addressing that. + + +//INCLUDED ADD-ON's +OLI - INCLUDED / TURNED INTO GENERIC FEATURE IMPORT / EXPORT CONTACTS and SCHEDULE TO ICAL +OutLookScheduleExport - INCLUDED / TURNED INTO GENERIC SCHED EXPORT ICAL FORMAT +Export to xls - Included with RAVEN +QuickNotification - Included with RAVEN +ImportExportDuplicate - Included with RAVEN +RI/WBI/MBI - UNNECESSARY with RAVEN + + + +===================================== + +RESEARCH SOURCES +- http://www.reprisesoftware.com/blog/2017/08/implement-a-recurring-revenue-license-model/ +- https://www.linkedin.com/pulse/20140819084845-458042-the-change-from-perpetual-to-subscription-based-software-licensing +- http://software-monetization.tmcnet.com/articles/429528-long-but-rewarding-road-a-recurring-revenue-model.htm +- How to calculate pricing in a service business: https://www.patriotsoftware.com/accounting/training/blog/how-pricing-services-strategies-models-formula/ - SAAS pricing models: https://www.cobloom.com/blog/saas-pricing-models \ No newline at end of file diff --git a/devdocs/specs/part-category-deprecated.txt b/devdocs/old-devdocs/specs/part-category-deprecated.txt similarity index 96% rename from devdocs/specs/part-category-deprecated.txt rename to devdocs/old-devdocs/specs/part-category-deprecated.txt index 699a6e9d..094de643 100644 --- a/devdocs/specs/part-category-deprecated.txt +++ b/devdocs/old-devdocs/specs/part-category-deprecated.txt @@ -1 +1 @@ -Replaced with tags case 3373 +Replaced with tags case 3373 diff --git a/devdocs/specs/plugin-dump.txt b/devdocs/old-devdocs/specs/plugin-dump.txt similarity index 98% rename from devdocs/specs/plugin-dump.txt rename to devdocs/old-devdocs/specs/plugin-dump.txt index d1e17f19..fcb5437a 100644 --- a/devdocs/specs/plugin-dump.txt +++ b/devdocs/old-devdocs/specs/plugin-dump.txt @@ -1 +1 @@ -Consolidating all import export to one plugin, see case 3503 +Consolidating all import export to one plugin, see case 3503 diff --git a/devdocs/specs/plugin-export-to-xls.txt b/devdocs/old-devdocs/specs/plugin-export-to-xls.txt similarity index 98% rename from devdocs/specs/plugin-export-to-xls.txt rename to devdocs/old-devdocs/specs/plugin-export-to-xls.txt index 9913f01a..1febdec2 100644 --- a/devdocs/specs/plugin-export-to-xls.txt +++ b/devdocs/old-devdocs/specs/plugin-export-to-xls.txt @@ -1 +1 @@ -Consolidated all export import to one single feature see case 3503 +Consolidated all export import to one single feature see case 3503 diff --git a/devdocs/specs/plugin-outlook-schedule.txt b/devdocs/old-devdocs/specs/plugin-outlook-schedule.txt similarity index 98% rename from devdocs/specs/plugin-outlook-schedule.txt rename to devdocs/old-devdocs/specs/plugin-outlook-schedule.txt index 5fe4d165..65c1f721 100644 --- a/devdocs/specs/plugin-outlook-schedule.txt +++ b/devdocs/old-devdocs/specs/plugin-outlook-schedule.txt @@ -1,7 +1,7 @@ -FIRST OF ALL CHECK TO SEE WHO IS USING THIS OR ANY OTHER FRINGE PLUGINS -THAT IS A CURRENT SUBSCRIBER - -Consolidate all outlook sched related plugins to a single way of dealing with outlook. -Also maybe different types of schedule like google calendar etc etc - -Might even be related to case 3503 the dump utility as it could dump sched items to ical format or whatever +FIRST OF ALL CHECK TO SEE WHO IS USING THIS OR ANY OTHER FRINGE PLUGINS +THAT IS A CURRENT SUBSCRIBER + +Consolidate all outlook sched related plugins to a single way of dealing with outlook. +Also maybe different types of schedule like google calendar etc etc + +Might even be related to case 3503 the dump utility as it could dump sched items to ical format or whatever diff --git a/devdocs/specs/postgres-useful-info.txt b/devdocs/old-devdocs/specs/postgres-useful-info.txt similarity index 89% rename from devdocs/specs/postgres-useful-info.txt rename to devdocs/old-devdocs/specs/postgres-useful-info.txt index 73c6a6bb..b83486af 100644 --- a/devdocs/specs/postgres-useful-info.txt +++ b/devdocs/old-devdocs/specs/postgres-useful-info.txt @@ -1,27 +1,27 @@ -POSTGRES USEFUL INFO - -//this is handy: -http://okigiveup.net/what-postgresql-tells-you-about-its-performance/ - -How to find log files and configure them -https://www.endpoint.com/blog/2014/11/12/dear-postgresql-where-are-my-logs - - - -2020-05-21 THIS SUPERSEDES BELOW -HOW TO FIND SHITTY INDEXES: https://gist.github.com/jberkus/6b1bcaf7724dfc2a54f3 - -top five tables by size (bytes) -SELECT - relname AS "table_name", - pg_table_size(C.oid) AS "table_size" -FROM - pg_class C -LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace) -WHERE nspname NOT IN ('pg_catalog', 'information_schema') AND nspname !~ '^pg_toast' AND relkind IN ('r') -ORDER BY pg_table_size(C.oid) -DESC LIMIT 10; - - -TOTAL DATABASE SIZE +POSTGRES USEFUL INFO + +//this is handy: +http://okigiveup.net/what-postgresql-tells-you-about-its-performance/ + +How to find log files and configure them +https://www.endpoint.com/blog/2014/11/12/dear-postgresql-where-are-my-logs + + + +2020-05-21 THIS SUPERSEDES BELOW +HOW TO FIND SHITTY INDEXES: https://gist.github.com/jberkus/6b1bcaf7724dfc2a54f3 + +top five tables by size (bytes) +SELECT + relname AS "table_name", + pg_table_size(C.oid) AS "table_size" +FROM + pg_class C +LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace) +WHERE nspname NOT IN ('pg_catalog', 'information_schema') AND nspname !~ '^pg_toast' AND relkind IN ('r') +ORDER BY pg_table_size(C.oid) +DESC LIMIT 10; + + +TOTAL DATABASE SIZE select pg_database_size(current_database());//size in bytes \ No newline at end of file diff --git a/devdocs/specs/priorities.txt b/devdocs/old-devdocs/specs/priorities.txt similarity index 98% rename from devdocs/specs/priorities.txt rename to devdocs/old-devdocs/specs/priorities.txt index 59c96a37..676e9a17 100644 --- a/devdocs/specs/priorities.txt +++ b/devdocs/old-devdocs/specs/priorities.txt @@ -1,2 +1,2 @@ -Would like to replace with a tag, but they have colors. -No cases regarding this that I can find in a quick search, but I suspect there was something somewhere, will update here when found +Would like to replace with a tag, but they have colors. +No cases regarding this that I can find in a quick search, but I suspect there was something somewhere, will update here when found diff --git a/devdocs/specs/scheduleable-user-role-rights-to-workorder.txt b/devdocs/old-devdocs/specs/scheduleable-user-role-rights-to-workorder.txt similarity index 98% rename from devdocs/specs/scheduleable-user-role-rights-to-workorder.txt rename to devdocs/old-devdocs/specs/scheduleable-user-role-rights-to-workorder.txt index 4983275a..b1428ff5 100644 --- a/devdocs/specs/scheduleable-user-role-rights-to-workorder.txt +++ b/devdocs/old-devdocs/specs/scheduleable-user-role-rights-to-workorder.txt @@ -1,111 +1,111 @@ -SCHEDULEABLE USER ROLE RIGHTS - - Tech (full) - Full access to Work order all areas - costs not visible unless they have a separate role that allows that, at minimum inventory - restricted - can enter price overrides and see prices - can see all wo items and subitems and edit any of them - - Tech (limited) - This person basically fills out a workorder that someone else created / does the work but has no control over the details and can't see anyone else's stuff - Like a subcontractor but as they are staff they also have access to full range of peripheral standard AyaNova 8 features like reminders, ancillary objects like customer etc, contract, customer notes, follow up, attachments etc - Can not create or delete a work order or work order item - No costs or prices anywhere - Can only see workorder items they are scheduled on - Specific rights to Work order areas: - Header - all visible but all read only, can see wiki, attachments, status, contract etc but not change them - Status can be changed if role allows since there are roles tied to status now - this supports process control where a limited tech can edit then "hand off" to a superior for final editing by changing status - ??Signatures fields not sure if read only or available - Main menu only available menu items are: - "Report" and only work order reports that are available to their role - probably nothing else as they are not able to create nor delete a work order - - Work order items - only their own work order item they are scheduled on is visible, no others - No fields visible other than Summary, technotes, ??priority?? - No Work order item menu (no access to any menu items in woitem) - - Units - view only and barebones, just enough to confirm the unit to be worked on matches, no context menu access - Scheduled Users - view only and only their own, no one else's, can convert to labor record but no other context menu access - Tasks - can set a task result but not edit or change the list, no context menu access - Parts - can view but not edit, no context menu access, and no price or costs, just the barebones enough to confirm they have the correct parts in hand, assumed pre-entered for them by another user - part, quantity, name, upc, description, serial numbers - Part Requests - read only - Labors - view and edit their own, no price or cost fields visible, can create new but the user will always default to themselves and can't be changed - Menu items available are: New, Append Tasks, mark for deletion (no mark all for deletion) - Travels - same as labors, same menu options - Expenses - Only fields are summary, cost, tax paid and defaults to themselves, other fields not shown assumed edited by another user with rights - Loans - view only and barebones, no menu, just enough for them to see what item they are supposed to bring in case they do and possibly the time frame in case the customer asks? - Outside service - read only no control or menu access - - Subcontractor (full) - Overall UI access (just these, NOTHING else) - Home - Schedule READ ONLY, can view the schedule which shows only their own scheduled user items on workorders so they can open them - Notification widget (bell icon) - Can view notifications sent to them, but have no control over subscribing etc, this is so someone can direct notify them or they can receive errors from system - General menu items - About (all sections shown except the two license related sections at bottom) - - WORK ORDER ACCESS - No access to peripheral ayanova features (notification, Links from workorder picklists like customer etc, contract, customer notes, follow up, attachments etc) - No costs / prices anywhere - Can not create nor delete a work order or woitem - Can only see workorder items they are scheduled on - - Specific rights to Work order areas: - Header - restricted to customer name, address, ??signatures??, nothing else, no wiki, no contract, no tags etc - Main menu only available menu item is "Report" and only work order reports that are set to be available to a Subcontractor full role - - Work order items - only their own work order item they are scheduled on is visible, no others - No fields visible other than Summary, technotes, ??priority?? - No Work order item menu (no access to any menu items in woitem) - - Units - view only and barebones, just enough to confirm the unit to be worked on matches, no context menu access - Scheduled Users - view only and only their own, no one else's, can convert to labor record but no other context menu access - Tasks - can set a task result but not edit or change the list, no context menu access - Parts - can view but not edit, no context menu access, and no price or costs, just the barebones enough to confirm they have the correct parts in hand, assumed pre-entered for them by another user - part, quantity, name, upc, description, serial numbers - Part Requests - no access / not shown - Labors - view and edit their own, no price or cost fields visible, can create new but the user will always default to themselves and can't be changed - Menu items available are: New, Append Tasks, mark for deletion (no mark all for deletion) - Travels - same as labors, same menu options - ??Expenses - Not sure but if allowed then only summary, cost, tax paid and defaults to themselves, other fields not shown assumed edited by another user with rights - Loans - view only and barebones, just enough for them to see what item they are supposed to bring in case they do and possibly the time frame in case the customer asks? - Outside service - no access / not shown - - Sub-contractor (limited) - Overall UI access (just these, NOTHING else) - Home - Schedule READ ONLY, can view the schedule which shows only their own scheduled user items on workorders so they can open them - Notification widget (bell icon) - Can view notifications sent to them, but have no control over subscribing etc, this is so someone can direct notify them or they can receive errors from system - General menu items - About (all sections shown except the two license related sections at bottom) - WORK ORDER ACCESS - Essentially it's a labor entry only user - No access to peripheral ayanova features (notification, Links from workorder picklists like customer etc, contract, customer notes, follow up, attachments etc) - No costs / prices anywhere - Can not create nor delete a work order or woitem - Can only see workorder items they are scheduled on - - Specific rights to Work order areas: - Header - restricted to customer name for confirmation nothing else - Main menu only available menu item is "Report" and only work order reports that are set to be available to a Subcontractor limited role - - Work order items - only their own work order item they are scheduled on is visible, no others - No fields visible other than Sequence, Summary, technotes - No Work order item menu (no access to any menu items in woitem) - - Units - not shown / no access - Scheduled Users - view only and only their own, no one else's, can convert to labor record but no other context menu access - Tasks - can set a task result but not edit or change the list, no context menu access - Parts - not shown / no access - Part Requests - not shown / no access - Labors - view and edit their own, no price or cost fields visible, can create new but the user will always default to themselves and can't be changed - Menu items available are: New, Append Tasks, mark for deletion (no mark all for deletion) - Travels - same as labors, same menu options - Expenses - not shown / no access - Loans - not shown / no access - Outside service - not shown / no access - +SCHEDULEABLE USER ROLE RIGHTS + + Tech (full) + Full access to Work order all areas + costs not visible unless they have a separate role that allows that, at minimum inventory - restricted + can enter price overrides and see prices + can see all wo items and subitems and edit any of them + + Tech (limited) + This person basically fills out a workorder that someone else created / does the work but has no control over the details and can't see anyone else's stuff + Like a subcontractor but as they are staff they also have access to full range of peripheral standard AyaNova 8 features like reminders, ancillary objects like customer etc, contract, customer notes, follow up, attachments etc + Can not create or delete a work order or work order item + No costs or prices anywhere + Can only see workorder items they are scheduled on + Specific rights to Work order areas: + Header - all visible but all read only, can see wiki, attachments, status, contract etc but not change them + Status can be changed if role allows since there are roles tied to status now + this supports process control where a limited tech can edit then "hand off" to a superior for final editing by changing status + ??Signatures fields not sure if read only or available + Main menu only available menu items are: + "Report" and only work order reports that are available to their role + probably nothing else as they are not able to create nor delete a work order + + Work order items - only their own work order item they are scheduled on is visible, no others + No fields visible other than Summary, technotes, ??priority?? + No Work order item menu (no access to any menu items in woitem) + + Units - view only and barebones, just enough to confirm the unit to be worked on matches, no context menu access + Scheduled Users - view only and only their own, no one else's, can convert to labor record but no other context menu access + Tasks - can set a task result but not edit or change the list, no context menu access + Parts - can view but not edit, no context menu access, and no price or costs, just the barebones enough to confirm they have the correct parts in hand, assumed pre-entered for them by another user + part, quantity, name, upc, description, serial numbers + Part Requests - read only + Labors - view and edit their own, no price or cost fields visible, can create new but the user will always default to themselves and can't be changed + Menu items available are: New, Append Tasks, mark for deletion (no mark all for deletion) + Travels - same as labors, same menu options + Expenses - Only fields are summary, cost, tax paid and defaults to themselves, other fields not shown assumed edited by another user with rights + Loans - view only and barebones, no menu, just enough for them to see what item they are supposed to bring in case they do and possibly the time frame in case the customer asks? + Outside service - read only no control or menu access + + Subcontractor (full) + Overall UI access (just these, NOTHING else) + Home + Schedule READ ONLY, can view the schedule which shows only their own scheduled user items on workorders so they can open them + Notification widget (bell icon) + Can view notifications sent to them, but have no control over subscribing etc, this is so someone can direct notify them or they can receive errors from system + General menu items + About (all sections shown except the two license related sections at bottom) + + WORK ORDER ACCESS + No access to peripheral ayanova features (notification, Links from workorder picklists like customer etc, contract, customer notes, follow up, attachments etc) + No costs / prices anywhere + Can not create nor delete a work order or woitem + Can only see workorder items they are scheduled on + + Specific rights to Work order areas: + Header - restricted to customer name, address, ??signatures??, nothing else, no wiki, no contract, no tags etc + Main menu only available menu item is "Report" and only work order reports that are set to be available to a Subcontractor full role + + Work order items - only their own work order item they are scheduled on is visible, no others + No fields visible other than Summary, technotes, ??priority?? + No Work order item menu (no access to any menu items in woitem) + + Units - view only and barebones, just enough to confirm the unit to be worked on matches, no context menu access + Scheduled Users - view only and only their own, no one else's, can convert to labor record but no other context menu access + Tasks - can set a task result but not edit or change the list, no context menu access + Parts - can view but not edit, no context menu access, and no price or costs, just the barebones enough to confirm they have the correct parts in hand, assumed pre-entered for them by another user + part, quantity, name, upc, description, serial numbers + Part Requests - no access / not shown + Labors - view and edit their own, no price or cost fields visible, can create new but the user will always default to themselves and can't be changed + Menu items available are: New, Append Tasks, mark for deletion (no mark all for deletion) + Travels - same as labors, same menu options + ??Expenses - Not sure but if allowed then only summary, cost, tax paid and defaults to themselves, other fields not shown assumed edited by another user with rights + Loans - view only and barebones, just enough for them to see what item they are supposed to bring in case they do and possibly the time frame in case the customer asks? + Outside service - no access / not shown + + Sub-contractor (limited) + Overall UI access (just these, NOTHING else) + Home + Schedule READ ONLY, can view the schedule which shows only their own scheduled user items on workorders so they can open them + Notification widget (bell icon) + Can view notifications sent to them, but have no control over subscribing etc, this is so someone can direct notify them or they can receive errors from system + General menu items + About (all sections shown except the two license related sections at bottom) + WORK ORDER ACCESS + Essentially it's a labor entry only user + No access to peripheral ayanova features (notification, Links from workorder picklists like customer etc, contract, customer notes, follow up, attachments etc) + No costs / prices anywhere + Can not create nor delete a work order or woitem + Can only see workorder items they are scheduled on + + Specific rights to Work order areas: + Header - restricted to customer name for confirmation nothing else + Main menu only available menu item is "Report" and only work order reports that are set to be available to a Subcontractor limited role + + Work order items - only their own work order item they are scheduled on is visible, no others + No fields visible other than Sequence, Summary, technotes + No Work order item menu (no access to any menu items in woitem) + + Units - not shown / no access + Scheduled Users - view only and only their own, no one else's, can convert to labor record but no other context menu access + Tasks - can set a task result but not edit or change the list, no context menu access + Parts - not shown / no access + Part Requests - not shown / no access + Labors - view and edit their own, no price or cost fields visible, can create new but the user will always default to themselves and can't be changed + Menu items available are: New, Append Tasks, mark for deletion (no mark all for deletion) + Travels - same as labors, same menu options + Expenses - not shown / no access + Loans - not shown / no access + Outside service - not shown / no access + diff --git a/devdocs/specs/todo-before-release.txt b/devdocs/old-devdocs/specs/todo-before-release.txt similarity index 96% rename from devdocs/specs/todo-before-release.txt rename to devdocs/old-devdocs/specs/todo-before-release.txt index d9f10e66..dea062e5 100644 --- a/devdocs/specs/todo-before-release.txt +++ b/devdocs/old-devdocs/specs/todo-before-release.txt @@ -1,57 +1,57 @@ -TODO related to Release - - -These are items that should be handled before release, a checklist of last minute stuff - -ROCKFISH License key route stuff, make sure it's ready to make requests adn handle customers in real world scenario -RAVEN LICENSE KEY TRIAL - - make sure the various workarounds to enable trial key fetching are disabled / removed, see License.RequestTrialKey and various others - - Basically, if you remove the special CONST guid trial dbid value the rest of the code that needs to be changed should jump out due to compiler errors - -DbUtil::DBIsEmpty() - - Check that shit was updated to ensure all relevant tables are involved - - -All dependencies in AyaNova.csproj project file should be locked down to a version release - - for example "Npgsql.EntityFrameworkCore.PostgreSQL" package should be set to a determined last change version - - Then test everything, confirm all ok, and no more changes to that file until determined after release it's safe to do so - - It should be a snapshot in time. - -figure out the tiniest possible distribution and which docker container from Microsoft it will work with - - right now using sdk version on DO server because of fuckery, but ultimately it needs to be the minimal possible - -Branch / tags / repository - - Need to figure out how to branch and tag properly so can start on next version without affecting release version - - In other words snapshot the release in the repo. - - Currently it's not an issue, but maybe it should be done properly - -Remove widget route from release (or hide it) but keep in debug - (But...would it be handy for diagnosing things??) - -DB INDEXES / PERFORMANCE - - Absolutely have to fine tune the indexes before release. - - Found a lot of useful info on examining index usage with postgres, there are some built in stats in PostgreSQL that show how indexes are being used and or not used properly or usefully - - A quick search should show many ways to query for used tables etc - - Monitor unussed indexes: https://jmorano.moretrix.com/2014/02/postgresql-monitor-unused-indexes/ - - Many queries to do with tuning: https://gist.github.com/ruckus/5718112 - - Useful for learning: https://www.datadoghq.com/blog/postgresql-monitoring/ - - - -DB CONNECTIONS: -https://news.ycombinator.com/item?id=18425923 -wild_preference 2 hours ago [-] -The other half of this is correctly using the connection pool in the application layer to begin with. -One of the most common performance errors I see in random http applications is grabbing db connections for too long, like in middleware, or too aggressively in parallel queries. -reply -sb8244 2 hours ago [-] -This is so true and easy to overlook until a post mortem. A great exercise is to audit how connections are maintained in your application, before it's too late. -reply -macintux 1 hour ago [-] -I'm reminded of a systems failure described in, IIRC, the O'Reilly book "Release It!". Java ODBC exception swallowed resulted in eventually running out of connections. -Very tough problem to troubleshoot without extensive monitoring. - - -DOCUMENTATION TODO's - -Do a search for "TODO" all caps in the docs, there are things that are on hold and need to be fleshed out. +TODO related to Release + + +These are items that should be handled before release, a checklist of last minute stuff + +ROCKFISH License key route stuff, make sure it's ready to make requests adn handle customers in real world scenario +RAVEN LICENSE KEY TRIAL + - make sure the various workarounds to enable trial key fetching are disabled / removed, see License.RequestTrialKey and various others + - Basically, if you remove the special CONST guid trial dbid value the rest of the code that needs to be changed should jump out due to compiler errors + +DbUtil::DBIsEmpty() + - Check that shit was updated to ensure all relevant tables are involved + + +All dependencies in AyaNova.csproj project file should be locked down to a version release + - for example "Npgsql.EntityFrameworkCore.PostgreSQL" package should be set to a determined last change version + - Then test everything, confirm all ok, and no more changes to that file until determined after release it's safe to do so + - It should be a snapshot in time. + +figure out the tiniest possible distribution and which docker container from Microsoft it will work with + - right now using sdk version on DO server because of fuckery, but ultimately it needs to be the minimal possible + +Branch / tags / repository + - Need to figure out how to branch and tag properly so can start on next version without affecting release version + - In other words snapshot the release in the repo. + - Currently it's not an issue, but maybe it should be done properly + +Remove widget route from release (or hide it) but keep in debug + (But...would it be handy for diagnosing things??) + +DB INDEXES / PERFORMANCE + - Absolutely have to fine tune the indexes before release. + - Found a lot of useful info on examining index usage with postgres, there are some built in stats in PostgreSQL that show how indexes are being used and or not used properly or usefully + - A quick search should show many ways to query for used tables etc + - Monitor unussed indexes: https://jmorano.moretrix.com/2014/02/postgresql-monitor-unused-indexes/ + - Many queries to do with tuning: https://gist.github.com/ruckus/5718112 + - Useful for learning: https://www.datadoghq.com/blog/postgresql-monitoring/ + - + +DB CONNECTIONS: +https://news.ycombinator.com/item?id=18425923 +wild_preference 2 hours ago [-] +The other half of this is correctly using the connection pool in the application layer to begin with. +One of the most common performance errors I see in random http applications is grabbing db connections for too long, like in middleware, or too aggressively in parallel queries. +reply +sb8244 2 hours ago [-] +This is so true and easy to overlook until a post mortem. A great exercise is to audit how connections are maintained in your application, before it's too late. +reply +macintux 1 hour ago [-] +I'm reminded of a systems failure described in, IIRC, the O'Reilly book "Release It!". Java ODBC exception swallowed resulted in eventually running out of connections. +Very tough problem to troubleshoot without extensive monitoring. + + +DOCUMENTATION TODO's + +Do a search for "TODO" all caps in the docs, there are things that are on hold and need to be fleshed out. Do not release with the todo tag in there still!!!! \ No newline at end of file diff --git a/devdocs/specs/todo-original-todo-doc.txt b/devdocs/old-devdocs/specs/todo-original-todo-doc.txt similarity index 98% rename from devdocs/specs/todo-original-todo-doc.txt rename to devdocs/old-devdocs/specs/todo-original-todo-doc.txt index 05247ce6..ddb7b885 100644 --- a/devdocs/specs/todo-original-todo-doc.txt +++ b/devdocs/old-devdocs/specs/todo-original-todo-doc.txt @@ -1,237 +1,237 @@ -# TODO original todo docs - -This was my original todo doc which I've pared down to only what I want to work on a few steps ahead. -Keeping this for reference as it has a lot of ideas about core services etc that will be useful - - - - - - A NEW START - - - -Get shit done: - -Use an agile like process and start coding ASAP with the lowest level pre-requisite stuff. - -I get stuff done faster when I see results and coding isn't bad to start early as long as it's done in the correct order and is iterated agilely - -Code tests and then code against them, don't get crazy about unit testing every little thing, just what is necessary to validate -Using an agile-like process re-iterate and continually add new stuff while testing. - - -I want an installable, testable product ready to deploy even if it only has one feature and no front end yet. - -Then starting from that base, add in all the common, shared, features first. - -Ideally we have a real product that can be installed and run as soon as possible and then build onto that and iterate, adding feature by feature. - - -1) Determine the first things to implement, ideally everything that isn't a business object requirement, bootstrap process, configuration etc. -2) Implement the core with sysop stuff, generator equivalent, db, maybe not even any user accounts yet, just the framework - - Want to be able to install as in production, start the sever, configure, view the sysop stuff make an online account and test there etc -3) Add a single simple business feature, maybe login and user creation, license etc - - Code the front end for that feature, at this point need shell and etc. - -4) Test all the above be sure about it, make sure it follows the guidelines for coding standards etc, then get into the actual features -5) Code AyaNova business features - - ** DO NOT WASTE TIME PLANNING AND DOCUMENTING EXISTING UNCHANGING FEATURES, LET AYANOVA SOURCE BE THE GUIDE FOR THAT ** - - Just document changes or new stuff only - - This is where we get into the stuff below and the biz object cases etc - - Code in order from the simplest most fundamental objects towards the most esoteric and complex multi object items - - Save the most complex objects for last so as to save time as no doubt changes will come up in other coding - - For example, there are no doubt objects that are mostly standalone and don't involve a lot of other objects, start there - - - - - - - - - - - - -****************************************************************************************************************** -****************************************************************************************************************** - OLD PLAN BELOW HERE KEPT FOR REF BUT NEW PLAN SUPERSEDES -****************************************************************************************************************** -****************************************************************************************************************** - - - - - -## FEATURE PLANNING / RE-ORG / AUDIT CASES - -- PLANNING STEP 1: Go through all AyaNova 7.x, 8.x cases and any other places there is feature stuff - - Move to RAVEN the ones that are worth keeping / looking into (snap judgements) - - Set all cases moved to Raven to priority 3 indicating unprioritized - - Stuff that will never be done for sure just close. - - Stuff that won't be done in RAVEN but might be worth keeping until the release of RAVEN before closing drop priority down to 5 - - When done there should be no more cases above priority 5 in 7.x unless they will be fixed in 7.x - -- PLANNING STEP 2: Examine RAVEN cases and re-prioritize and categorize them: - - SET THE CATEGORY COLON DENOMINATED i.e. (CLIENT, REGION, WORKORDER:TASKS:CR:NEW, UI, SECURITY etc) by prepending the title with the category. - - If it's completely new feature then the last tag should be ":NEW" - - IF it's customer requested put a :CR tag in the title - - UNPRIORITIZED - - default for items until I categorize them - - PRIORITY 3 - - MUST HAVE IN INITIAL RELEASE - - PRIORITY 1 and 2 - - flag as highest priority 1 for work on first and 2 for work on secondly - - SHOULD HAVE IN FUTURE RELEASE - - PRIORITY 4 and 5 - - flag below highest as priority 4 or 5 depending on urgency - -- PLANNING STEP 3 THE WORKORDER LAYOUT - - This is tricky so needs a whole step - - Determine new workorder layout and structure - - Don't need exact features, rough is ok - - Step 4 will get into the details of the workorder - -****************************************************************************************************************** -****************************************************************************************************************** - NOT DONE BELOW HERE -****************************************************************************************************************** -****************************************************************************************************************** - - - - -- PLANNING STEP 4 FEATURES DOCUMENTS - - Read through my own notes in CODING-STANDARDS doc and REASEARCH.TXT and SOLUTIONS.TXT - - VERY IMPORTANT stuff in there, a lot of sysops stuff and practical decision stuff - - Review it all and update any related cases / make new cases as appropriate. - - - - Find common features that are shared with objects so they can be "Interfaced" and planned for - - Tag handling, UI preferences and MRU's and user settings - - Localization stuff - - Notification - - Common menu options that are shared by objects - - Need a set of sections that deal with just this kind of thing as it will be coded FIRST. - - Common UI widgets Document every common UI widget needed and where. - - The RAVEN ui will be made up of a lot of tiny widgets that are re-used here and there, that's what I will be making so need to document that - - Essentially everything in the UI will be a bunch of widgets housed in a bunch of modules housed in a shell - - Identifying them all up front will save tremendous time in development - - For example: in lots of places we need to show a filterable list of workorders tied to the object being viewed - - Like on the client form you need to see a list of workorders for that client - - On the unit form a list of workorders for that unit - - So a WORKORDER LIST widget is one that will be re-used time and again so document that and it's features - - Then it's just a matter of snapping it into any area it's needed - - this will translate to a business object and probably a route in the api etc etc - - Search widget and results display, that kind of thing - - Identify the first object to code, ideally it should have the most common features and the least of it's own features so I can focus on the shared stuff. - - - - What I want to end up with is a set of documents one for each major feature - - In each document I want to list what is kept, what is changed and what is new - - Add points of what each feature currently does and needs - - Then go through the cases and note new and changes relevant to that object - - Consider and make decisions and rank as priority 1 (in first release) and priority 2 - subsequent release - - iterate until there is at the end what I'm after - - - This is the list I will work from to ensure everything gets done - - I want each documents items in the best order of implementation as much as possible - - THIS IS IMPORTANT: I don't want to code a feature then see that I should have done something different later - - Then I can go through it while coding as my todo list basically - - Ideally then can test as each object is ported, kind of like each object is a new feature in quick release cycle - - - -- PLANNING STEP 5 USER INTERFACE - - Design the user interface for each section above, I want to see visual design that I can work from instead of winging it. - - ?? Need a design for at least two views, desktop / tablet and phone but need to research this a bit I guess - - Doesn't need to be perfect, a rough sketch and placement is fine. - - Need to design the widgets essentially - - Need to account for each view depending on ROLE viewing it. - - Find the commonalities for the roles so there is a pre-defined levels of access for each widget that match roles - - Like a Read only limited view, a full control view, a whatever view, each type named and replicate concept to all widgets - - Widget should be aware of roles and what to allow for each of them - -- STEP 6 CODING - - Code the NFR / SHELL and fundamental / common features like tag handling etc. - - Since a widget is kind of standalone ready, maybe a widget playground to test out widgets on a blank canvas without worrying about shell stuff at first. - - - - - - - - -- HOSTING planning - - Just a light initial assesment will not be super important at first, only interested in big picture stuff that might affect coding - - What will we need for hosting? - - What is the unit of software that each customer would use - - I.E. do we have one container per customer and spin them up as required - - Apply to design - - - - -## INITIAL CODING: FRAMEWORK SKELETON ALL NON FUNCTIONAL REQUIREMENTS - -- Make a list of all the things that it should do for front and back end -- This is really the foundational skeleton of everything and is the most important step, if it takes a while so be it, it will save a fortune in time later -- The design should be frozen once this skeleton satisfies NFR -- Once this is in place then can just fill in functionally required code and objects from design -- It's also a reference point for any other new projects going forward so keep a snapshot / Subversion tag that THIS IS IT!! -- There should be no research or figuring out required after the skeleton is completed (ideally) -- Build initial framework first with all the "non functional requirement" (everything but the actual business classes) specific features in it. Take a snapshot so it can be the basis for other projects in future. -- All tools should be in place - - Development tools - - Testing tools - - Once we have something to test look into something like: https://jenkins.io/solutions/docker/ containerized? - - Unit - - Integration - - Load - - Building tools - - Once we have something to build look into something like: https://jenkins.io/solutions/docker/ containerized? - - Releasing - - versioning - - updating - - containerization - - All database types - - Installer / installation - - Management interfaces or tools -- BACK END API - - Sample routes with two api versions (0 and 1.0) - - ideally a small sample of code showing all the layers of code involved with all the NFR features desired like circuit breakers you name it - - Users and Client for starters with a list of clients, a client entry and edit and delete - - - dependency injection / loose coupling - - https://joonasw.net/view/aspnet-core-di-deep-dive - - - - Upgradeable - - Versionable - - Circuit breakers - - Performance and other metrics and logging - - All the NFR in the PROCESS and BEST PRACTICES section of my coding-standards doc -- UI Skeleton to support this backend skeleton - - All NFR that are UI level (a SPA web application) - - UI concerns that may affect back end stuff should be in the skeleton - - The guts of the UI presentation host whatever it's called without the actual specific bits to the app - - Loading - - Upgrading - - Handling errors - - talking to the api - -- TESTING - - - - Smoke test first in a limited test VM that simulates a droplet of 512mb ram, 1cpu, docker container with db etc - - Test in a DO droplet under load with lots of data and see what memory and cpu and disk resources are required and how it performs - - - - -## FR CODING - - After the above move on to functional requirements coding - - Test and deploy daily at least - - +# TODO original todo docs + +This was my original todo doc which I've pared down to only what I want to work on a few steps ahead. +Keeping this for reference as it has a lot of ideas about core services etc that will be useful + + + + + + A NEW START + + + +Get shit done: + +Use an agile like process and start coding ASAP with the lowest level pre-requisite stuff. + +I get stuff done faster when I see results and coding isn't bad to start early as long as it's done in the correct order and is iterated agilely + +Code tests and then code against them, don't get crazy about unit testing every little thing, just what is necessary to validate +Using an agile-like process re-iterate and continually add new stuff while testing. + + +I want an installable, testable product ready to deploy even if it only has one feature and no front end yet. + +Then starting from that base, add in all the common, shared, features first. + +Ideally we have a real product that can be installed and run as soon as possible and then build onto that and iterate, adding feature by feature. + + +1) Determine the first things to implement, ideally everything that isn't a business object requirement, bootstrap process, configuration etc. +2) Implement the core with sysop stuff, generator equivalent, db, maybe not even any user accounts yet, just the framework + - Want to be able to install as in production, start the sever, configure, view the sysop stuff make an online account and test there etc +3) Add a single simple business feature, maybe login and user creation, license etc + - Code the front end for that feature, at this point need shell and etc. + +4) Test all the above be sure about it, make sure it follows the guidelines for coding standards etc, then get into the actual features +5) Code AyaNova business features + - ** DO NOT WASTE TIME PLANNING AND DOCUMENTING EXISTING UNCHANGING FEATURES, LET AYANOVA SOURCE BE THE GUIDE FOR THAT ** + - Just document changes or new stuff only + - This is where we get into the stuff below and the biz object cases etc + - Code in order from the simplest most fundamental objects towards the most esoteric and complex multi object items + - Save the most complex objects for last so as to save time as no doubt changes will come up in other coding + - For example, there are no doubt objects that are mostly standalone and don't involve a lot of other objects, start there + + + + + + + + + + + + +****************************************************************************************************************** +****************************************************************************************************************** + OLD PLAN BELOW HERE KEPT FOR REF BUT NEW PLAN SUPERSEDES +****************************************************************************************************************** +****************************************************************************************************************** + + + + + +## FEATURE PLANNING / RE-ORG / AUDIT CASES + +- PLANNING STEP 1: Go through all AyaNova 7.x, 8.x cases and any other places there is feature stuff + - Move to RAVEN the ones that are worth keeping / looking into (snap judgements) + - Set all cases moved to Raven to priority 3 indicating unprioritized + - Stuff that will never be done for sure just close. + - Stuff that won't be done in RAVEN but might be worth keeping until the release of RAVEN before closing drop priority down to 5 + - When done there should be no more cases above priority 5 in 7.x unless they will be fixed in 7.x + +- PLANNING STEP 2: Examine RAVEN cases and re-prioritize and categorize them: + - SET THE CATEGORY COLON DENOMINATED i.e. (CLIENT, REGION, WORKORDER:TASKS:CR:NEW, UI, SECURITY etc) by prepending the title with the category. + - If it's completely new feature then the last tag should be ":NEW" + - IF it's customer requested put a :CR tag in the title + - UNPRIORITIZED + - default for items until I categorize them + - PRIORITY 3 + - MUST HAVE IN INITIAL RELEASE + - PRIORITY 1 and 2 + - flag as highest priority 1 for work on first and 2 for work on secondly + - SHOULD HAVE IN FUTURE RELEASE + - PRIORITY 4 and 5 + - flag below highest as priority 4 or 5 depending on urgency + +- PLANNING STEP 3 THE WORKORDER LAYOUT + - This is tricky so needs a whole step + - Determine new workorder layout and structure + - Don't need exact features, rough is ok + - Step 4 will get into the details of the workorder + +****************************************************************************************************************** +****************************************************************************************************************** + NOT DONE BELOW HERE +****************************************************************************************************************** +****************************************************************************************************************** + + + + +- PLANNING STEP 4 FEATURES DOCUMENTS + - Read through my own notes in CODING-STANDARDS doc and REASEARCH.TXT and SOLUTIONS.TXT + - VERY IMPORTANT stuff in there, a lot of sysops stuff and practical decision stuff + - Review it all and update any related cases / make new cases as appropriate. + + + - Find common features that are shared with objects so they can be "Interfaced" and planned for + - Tag handling, UI preferences and MRU's and user settings + - Localization stuff + - Notification + - Common menu options that are shared by objects + - Need a set of sections that deal with just this kind of thing as it will be coded FIRST. + - Common UI widgets Document every common UI widget needed and where. + - The RAVEN ui will be made up of a lot of tiny widgets that are re-used here and there, that's what I will be making so need to document that + - Essentially everything in the UI will be a bunch of widgets housed in a bunch of modules housed in a shell + - Identifying them all up front will save tremendous time in development + - For example: in lots of places we need to show a filterable list of workorders tied to the object being viewed + - Like on the client form you need to see a list of workorders for that client + - On the unit form a list of workorders for that unit + - So a WORKORDER LIST widget is one that will be re-used time and again so document that and it's features + - Then it's just a matter of snapping it into any area it's needed + - this will translate to a business object and probably a route in the api etc etc + - Search widget and results display, that kind of thing + - Identify the first object to code, ideally it should have the most common features and the least of it's own features so I can focus on the shared stuff. + + + - What I want to end up with is a set of documents one for each major feature + - In each document I want to list what is kept, what is changed and what is new + - Add points of what each feature currently does and needs + - Then go through the cases and note new and changes relevant to that object + - Consider and make decisions and rank as priority 1 (in first release) and priority 2 - subsequent release + - iterate until there is at the end what I'm after + + - This is the list I will work from to ensure everything gets done + - I want each documents items in the best order of implementation as much as possible + - THIS IS IMPORTANT: I don't want to code a feature then see that I should have done something different later + - Then I can go through it while coding as my todo list basically + - Ideally then can test as each object is ported, kind of like each object is a new feature in quick release cycle + + + +- PLANNING STEP 5 USER INTERFACE + - Design the user interface for each section above, I want to see visual design that I can work from instead of winging it. + - ?? Need a design for at least two views, desktop / tablet and phone but need to research this a bit I guess + - Doesn't need to be perfect, a rough sketch and placement is fine. + - Need to design the widgets essentially + - Need to account for each view depending on ROLE viewing it. + - Find the commonalities for the roles so there is a pre-defined levels of access for each widget that match roles + - Like a Read only limited view, a full control view, a whatever view, each type named and replicate concept to all widgets + - Widget should be aware of roles and what to allow for each of them + +- STEP 6 CODING + - Code the NFR / SHELL and fundamental / common features like tag handling etc. + - Since a widget is kind of standalone ready, maybe a widget playground to test out widgets on a blank canvas without worrying about shell stuff at first. + + + + + + + + +- HOSTING planning + - Just a light initial assesment will not be super important at first, only interested in big picture stuff that might affect coding + - What will we need for hosting? + - What is the unit of software that each customer would use + - I.E. do we have one container per customer and spin them up as required + - Apply to design + + + + +## INITIAL CODING: FRAMEWORK SKELETON ALL NON FUNCTIONAL REQUIREMENTS + +- Make a list of all the things that it should do for front and back end +- This is really the foundational skeleton of everything and is the most important step, if it takes a while so be it, it will save a fortune in time later +- The design should be frozen once this skeleton satisfies NFR +- Once this is in place then can just fill in functionally required code and objects from design +- It's also a reference point for any other new projects going forward so keep a snapshot / Subversion tag that THIS IS IT!! +- There should be no research or figuring out required after the skeleton is completed (ideally) +- Build initial framework first with all the "non functional requirement" (everything but the actual business classes) specific features in it. Take a snapshot so it can be the basis for other projects in future. +- All tools should be in place + - Development tools + - Testing tools + - Once we have something to test look into something like: https://jenkins.io/solutions/docker/ containerized? + - Unit + - Integration + - Load + - Building tools + - Once we have something to build look into something like: https://jenkins.io/solutions/docker/ containerized? + - Releasing + - versioning + - updating + - containerization + - All database types + - Installer / installation + - Management interfaces or tools +- BACK END API + - Sample routes with two api versions (0 and 1.0) + - ideally a small sample of code showing all the layers of code involved with all the NFR features desired like circuit breakers you name it + - Users and Client for starters with a list of clients, a client entry and edit and delete + + - dependency injection / loose coupling + - https://joonasw.net/view/aspnet-core-di-deep-dive + + + - Upgradeable + - Versionable + - Circuit breakers + - Performance and other metrics and logging + - All the NFR in the PROCESS and BEST PRACTICES section of my coding-standards doc +- UI Skeleton to support this backend skeleton + - All NFR that are UI level (a SPA web application) + - UI concerns that may affect back end stuff should be in the skeleton + - The guts of the UI presentation host whatever it's called without the actual specific bits to the app + - Loading + - Upgrading + - Handling errors + - talking to the api + +- TESTING + - + - Smoke test first in a limited test VM that simulates a droplet of 512mb ram, 1cpu, docker container with db etc + - Test in a DO droplet under load with lots of data and see what memory and cpu and disk resources are required and how it performs + + + + +## FR CODING + - After the above move on to functional requirements coding + - Test and deploy daily at least + + diff --git a/devdocs/specs/ui-ideas/interesting colour scheme powder blue and yellow 50s vibe.jpg b/devdocs/old-devdocs/specs/ui-ideas/interesting colour scheme powder blue and yellow 50s vibe.jpg similarity index 100% rename from devdocs/specs/ui-ideas/interesting colour scheme powder blue and yellow 50s vibe.jpg rename to devdocs/old-devdocs/specs/ui-ideas/interesting colour scheme powder blue and yellow 50s vibe.jpg diff --git a/devdocs/specs/unit-of-measures.txt b/devdocs/old-devdocs/specs/unit-of-measures.txt similarity index 98% rename from devdocs/specs/unit-of-measures.txt rename to devdocs/old-devdocs/specs/unit-of-measures.txt index 35af4cc6..4fb25d37 100644 --- a/devdocs/specs/unit-of-measures.txt +++ b/devdocs/old-devdocs/specs/unit-of-measures.txt @@ -1,2 +1,2 @@ -DEPRECATED? -Still not decided yet but leaning heavily towards ditching it, see case 3433 and 2038 +DEPRECATED? +Still not decided yet but leaning heavily towards ditching it, see case 3433 and 2038 diff --git a/devdocs/specs/unit-service-type.txt b/devdocs/old-devdocs/specs/unit-service-type.txt similarity index 98% rename from devdocs/specs/unit-service-type.txt rename to devdocs/old-devdocs/specs/unit-service-type.txt index eae55fec..4b5e777f 100644 --- a/devdocs/specs/unit-service-type.txt +++ b/devdocs/old-devdocs/specs/unit-service-type.txt @@ -1,3 +1,3 @@ -Deprecated for tag -Workorder will still have a redundant TAGS area in the unit service section so that section can be specfically tagged with unit service type tags or whatever the user wishes -See case 3373 +Deprecated for tag +Workorder will still have a redundant TAGS area in the unit service section so that section can be specfically tagged with unit service type tags or whatever the user wishes +See case 3373 diff --git a/devdocs/specs/user-certifications.txt b/devdocs/old-devdocs/specs/user-certifications.txt similarity index 95% rename from devdocs/specs/user-certifications.txt rename to devdocs/old-devdocs/specs/user-certifications.txt index 15911db5..6d72bcca 100644 --- a/devdocs/specs/user-certifications.txt +++ b/devdocs/old-devdocs/specs/user-certifications.txt @@ -1,2 +1,2 @@ -Deprecated maybe? -See case 3440, 1138 +Deprecated maybe? +See case 3440, 1138 diff --git a/devdocs/specs/user-skills.txt b/devdocs/old-devdocs/specs/user-skills.txt similarity index 95% rename from devdocs/specs/user-skills.txt rename to devdocs/old-devdocs/specs/user-skills.txt index 15911db5..6d72bcca 100644 --- a/devdocs/specs/user-skills.txt +++ b/devdocs/old-devdocs/specs/user-skills.txt @@ -1,2 +1,2 @@ -Deprecated maybe? -See case 3440, 1138 +Deprecated maybe? +See case 3440, 1138 diff --git a/devdocs/specs/workorder-categories.txt b/devdocs/old-devdocs/specs/workorder-categories.txt similarity index 96% rename from devdocs/specs/workorder-categories.txt rename to devdocs/old-devdocs/specs/workorder-categories.txt index 7542ab7a..466679b3 100644 --- a/devdocs/specs/workorder-categories.txt +++ b/devdocs/old-devdocs/specs/workorder-categories.txt @@ -1,2 +1,2 @@ -Deprecated to tags (verify this is possible)? -See case 3373 +Deprecated to tags (verify this is possible)? +See case 3373 diff --git a/devdocs/specs/workorder-item-type.txt b/devdocs/old-devdocs/specs/workorder-item-type.txt similarity index 97% rename from devdocs/specs/workorder-item-type.txt rename to devdocs/old-devdocs/specs/workorder-item-type.txt index 3da2844a..b46276a4 100644 --- a/devdocs/specs/workorder-item-type.txt +++ b/devdocs/old-devdocs/specs/workorder-item-type.txt @@ -1,7 +1,7 @@ -Deprecated to tags -See case 3373 -It will work, types don't appear to do anything and are documented as for filtering and reporting and sorting so that's a tag - -Just need to remember that the Workorder ITEM itself needs a TAGS area so that it can be separately tagged as with other areas of workorder like unit service type etc. - - +Deprecated to tags +See case 3373 +It will work, types don't appear to do anything and are documented as for filtering and reporting and sorting so that's a tag + +Just need to remember that the Workorder ITEM itself needs a TAGS area so that it can be separately tagged as with other areas of workorder like unit service type etc. + + diff --git a/devdocs/specs/workorder.odt b/devdocs/old-devdocs/specs/workorder.odt similarity index 100% rename from devdocs/specs/workorder.odt rename to devdocs/old-devdocs/specs/workorder.odt diff --git a/devdocs/todo.txt b/devdocs/old-devdocs/todo.txt similarity index 96% rename from devdocs/todo.txt rename to devdocs/old-devdocs/todo.txt index c4de4e7a..f76a0864 100644 --- a/devdocs/todo.txt +++ b/devdocs/old-devdocs/todo.txt @@ -1,24 +1,24 @@ - - - -=-=-=-=- -LAST DOCUMENTATION LEFT OFF AT -HeadOffices seems to be done whatever is next below - - - -PERPETUAL AS OF 4/6 2023 -rance.jackson@izonecenter.com,mparsons@vicom.com.au,gorazd.bregar@hpe.si,internet@accs.net,jberkel@pdisoftware.com,support@wetechnology.net, - -SUBSCRIBERS AS OF 4/6/2023 -jdragan@pro-ees.com,steve@sgrelectronics.co.uk,service@sportseffect.com,stan@tri-starmedical.com,johncrdnl@gmail.com - -SUBJECT: AyaNova 8.0.XX released -BODY: -AyaNova 8.0.XX has just been released. - -This release focuses on minor improvements and bug fixes and is not a critical update. - -More details and links to upgrade instructions here: -https://ayanova.com/docs/changelog/#ayanova-8033-2023-01-24 - + + + +=-=-=-=- +LAST DOCUMENTATION LEFT OFF AT +HeadOffices seems to be done whatever is next below + + + +PERPETUAL AS OF 4/6 2023 +rance.jackson@izonecenter.com,mparsons@vicom.com.au,gorazd.bregar@hpe.si,internet@accs.net,jberkel@pdisoftware.com,support@wetechnology.net, + +SUBSCRIBERS AS OF 4/6/2023 +jdragan@pro-ees.com,steve@sgrelectronics.co.uk,service@sportseffect.com,stan@tri-starmedical.com,johncrdnl@gmail.com + +SUBJECT: AyaNova 8.0.XX released +BODY: +AyaNova 8.0.XX has just been released. + +This release focuses on minor improvements and bug fixes and is not a critical update. + +More details and links to upgrade instructions here: +https://ayanova.com/docs/changelog/#ayanova-8033-2023-01-24 + diff --git a/devdocs/tools.txt b/devdocs/old-devdocs/tools.txt similarity index 100% rename from devdocs/tools.txt rename to devdocs/old-devdocs/tools.txt