today's date using custom Helper date.toLocaleDateString() : {{ todaysLocaleStringDate}}
\n\ttoday's date using custom Helper todaysget that users date.getFullYear etc: {{ todaysget}}\n\t
today's date using custom Helper long format of ayClientMetaData: {{ todaysMonthDDYYYYDate}}
today's date using custom Helper todaysDateYearFromParts formatter.formatToParts(parsedDate): {{ todaysDateYearFromParts}}
\n\n\n","Style":".example {\n color: blue;\n}","JsPrerender":"async function ayPrepareData(reportData){ \n //this function (if present) is called with the report data \n //before the report is rendered\n //modify data as required here and return it to change the data before the report renders\n //see the help documentation for details\n return reportData;\n}","JsHelpers":"//Register custom Handlebars helpers here to use in your report script\n//https://handlebarsjs.com/guide/#custom-helpers\n\n\nHandlebars.registerHelper('todaysDate', function() {\n var dt1=new Date();\n return dt1\n});// today's date with no formatting\n\nHandlebars.registerHelper('todaysLocaleStringDate', function() {\n var dt2=new Date();\n return dt2.toLocaleDateString() \n});// today's date displayed in the localedatestring\n\n\nHandlebars.registerHelper('todaysget', function() {\n var dt5 =new Date();\n var date = dt5.getFullYear()+'-'+(dt5.getMonth()+1)+'-'+dt5.getDate() + \" \" + +dt5.getHours() + \":\" + +dt5.getMinutes() ;\n return date\n});// today's date displayed \n\n\nHandlebars.registerHelper('todaysMonthDDYYYYDate', function() {\n var dt3=new Date();\n return dt3.toLocaleDateString(\n AYMETA.ayClientMetaData.LanguageName,//use Client browser default Language, change this setting here to force an alternative language\n {\n timeZone: AYMETA.ayClientMetaData.TimeZoneName,//use Client browser's default TimeZone, change this setting here to force a specific time zone\n dateStyle: \"long\"\n }\n ) ;\n});// today's date displayed in MONTH DD, YYYY format\n\n\n\n\n\n//\n// CUSTOM FORMAT TO PARTS HELPER\n// this offers the most control over the return format\n// Locale aware conversion to parts that can be returned in any format\n//\nHandlebars.registerHelper('todaysDateYearFromParts', function () {\n\n //parse todays date\n let parsedDate = new Date();\n\n //Set formatter options\n //https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/formatToParts\n let formatter = new Intl.DateTimeFormat('en-us', {\n weekday: 'long',\n year: 'numeric',\n month: 'long', //long to show the full name of month, short to show short name, numeric to show the month number\n day: 'numeric',\n hour: 'numeric',\n minute: 'numeric',\n second: 'numeric',\n fractionalSecondDigits: 3,\n hour12: true,\n timeZone: 'Canada/Pacific' //refer to https://en.wikipedia.org/wiki/List_of_tz_database_time_zones for appropriate TZ database name to use\n //OR use what is displayed in the output for your ayClientMetaData's TimeZoneName:\n });\n\n let parts = formatter.formatToParts(parsedDate);\n /*\n // parts example return value: \n [ \n { type: 'weekday', value: 'Monday' }, \n { type: 'literal', value: ', ' }, \n { type: 'month', value: '12' }, \n { type: 'literal', value: '/' }, \n { type: 'day', value: '17' }, \n { type: 'literal', value: '/' }, \n { type: 'year', value: '2012' }, \n { type: 'literal', value: ', ' }, \n { type: 'hour', value: '3' }, \n { type: 'literal', value: ':' }, \n { type: 'minute', value: '00' }, \n { type: 'literal', value: ':' }, \n { type: 'second', value: '42' }, \n { type: 'fractionalSecond', value: '000' },\n { type: 'literal', value: ' ' }, \n { type: 'dayPeriod', value: 'AM' } \n ]\n */\n//identify here which of the above will use when returning\n let partWeekDay = parts.find(({ type }) => type === 'weekday').value;\n let partDay = parts.find(({ type }) => type === 'day').value;\n let partMonth = parts.find(({ type }) => type === 'month').value;\n let partYear = parts.find(({ type }) => type === 'year').value;\n let partHour = parts.find(({ type }) => type === 'hour').value;\n let partMin = parts.find(({ type }) => type === 'minute').value;\n let partdayPeriod = parts.find(({ type }) => type === 'dayPeriod').value;\n\n\n \n //return in some custom format\n return `${partWeekDay} ${partDay}, ${partMonth} ${partYear} - ${partHour}:${partMin} ${partdayPeriod}`;\n \n //return below instead to see array of the possible values for each type while initially figuring out what to customize to\n //return JSON.stringify(parts);\n});","RenderType":0,"HeaderTemplate":null,"FooterTemplate":null,"DisplayHeaderFooter":false,"PaperFormat":0,"Landscape":false,"MarginOptionsBottom":null,"MarginOptionsLeft":null,"MarginOptionsRight":null,"MarginOptionsTop":null,"PageRanges":null,"PreferCSSPageSize":false,"PrintBackground":false,"Scale":1.0000}
\ No newline at end of file
diff --git a/server/AyaNova/resource/rpt/stock-report-templates/SAMPLE one object prints per page.ayrt b/server/AyaNova/resource/rpt/stock-report-templates/SAMPLE one object prints per page.ayrt
index 406db699..7ddd5ecf 100644
--- a/server/AyaNova/resource/rpt/stock-report-templates/SAMPLE one object prints per page.ayrt
+++ b/server/AyaNova/resource/rpt/stock-report-templates/SAMPLE one object prints per page.ayrt
@@ -1 +1 @@
-{"Name":"SAMPLE one object prints per page","Active":true,"Notes":"","Roles":124927,"ObjectType":2,"Template":"\n\n\n\n\t
Example: Translation helper
\n\t
See Report editor help documentation for details
\n\t
this will show on the first page only as is HTML code BEFORE the #each aspect which is used for iteration
\n\t
if want this on its own page unto itself, wrap it also in a class that does a page-break
\n\n{{#each ayReportData}} \n\t
\t\t\n\t\t
{{ayT 'WidgetName' }}: {{ Name }}
\n\t\t
{{ayT 'WidgetSerial' }}:{{ Serial }}
\n\t\t
{{ayT 'WidgetDollarAmount' }}:{{ DollarAmount }}
\n\t\t
{{ayT 'WidgetStartDate' }}:{{ StartDate }}
\n\t\t
{{ayT 'WidgetNotes' }}:{{ Notes }}
\t\t\n\t
\n{{/each}}\n\n\n\n\n","Style":".example {\n color: blue;\n}\n\n\n.singlePage\n{\npage-break-after: always;\n}","JsPrerender":"async function ayPrepareData(reportData) {\n //Fetch translation keys required for report \n //Server will get the translations that match the current logged in user's language\n //Only translation keys pre-fetched here will be available for use with the ayT translation helper\n\n //NOTE: you *must* await the call to ayGetTranslations or they will not be present for the report template use\n\n await ayGetTranslations([\n \"Widget\",\n \"WidgetName\",\n \"WidgetSerial\",\n \"WidgetDollarAmount\",\n \"WidgetCount\",\n \"WidgetStartDate\",\n \"WidgetEndDate\",\n \"WidgetNotes\",\n \"WidgetCustom1\",\n \"WidgetCustom2\",\n \"WidgetCustom3\",\n \"WidgetCustom4\",\n \"WidgetCustom5\",\n \"WidgetCustom6\",\n \"WidgetCustom7\",\n \"WidgetCustom8\",\n \"WidgetCustom9\",\n \"WidgetCustom10\",\n \"WidgetCustom11\",\n \"WidgetCustom12\",\n \"WidgetCustom13\",\n \"WidgetCustom14\",\n \"WidgetCustom15\",\n \"WidgetCustom16\",\n ]);\n\n return reportData;\n}","JsHelpers":"//Register custom Handlebars helpers here to use in your report script\n//https://handlebarsjs.com/guide/#custom-helpers\nHandlebars.registerHelper('loud', function (aString) {\n return aString.toUpperCase()\n})","RenderType":0,"HeaderTemplate":null,"FooterTemplate":null,"DisplayHeaderFooter":false,"PaperFormat":0,"Landscape":false,"MarginOptionsBottom":null,"MarginOptionsLeft":null,"MarginOptionsRight":null,"MarginOptionsTop":null,"PageRanges":null,"PreferCSSPageSize":false,"PrintBackground":false,"Scale":1.0000}
\ No newline at end of file
+{"Name":"SAMPLE one object prints per page","Active":true,"Notes":"","Roles":124927,"AType":2,"Template":"\n\n\n\n\t
Example: Translation helper
\n\t
See Report editor help documentation for details
\n\t
this will show on the first page only as is HTML code BEFORE the #each aspect which is used for iteration
\n\t
if want this on its own page unto itself, wrap it also in a class that does a page-break
\n\n{{#each ayReportData}} \n\t
\t\t\n\t\t
{{ayT 'WidgetName' }}: {{ Name }}
\n\t\t
{{ayT 'WidgetSerial' }}:{{ Serial }}
\n\t\t
{{ayT 'WidgetDollarAmount' }}:{{ DollarAmount }}
\n\t\t
{{ayT 'WidgetStartDate' }}:{{ StartDate }}
\n\t\t
{{ayT 'WidgetNotes' }}:{{ Notes }}
\t\t\n\t
\n{{/each}}\n\n\n\n\n","Style":".example {\n color: blue;\n}\n\n\n.singlePage\n{\npage-break-after: always;\n}","JsPrerender":"async function ayPrepareData(reportData) {\n //Fetch translation keys required for report \n //Server will get the translations that match the current logged in user's language\n //Only translation keys pre-fetched here will be available for use with the ayT translation helper\n\n //NOTE: you *must* await the call to ayGetTranslations or they will not be present for the report template use\n\n await ayGetTranslations([\n \"Widget\",\n \"WidgetName\",\n \"WidgetSerial\",\n \"WidgetDollarAmount\",\n \"WidgetCount\",\n \"WidgetStartDate\",\n \"WidgetEndDate\",\n \"WidgetNotes\",\n \"WidgetCustom1\",\n \"WidgetCustom2\",\n \"WidgetCustom3\",\n \"WidgetCustom4\",\n \"WidgetCustom5\",\n \"WidgetCustom6\",\n \"WidgetCustom7\",\n \"WidgetCustom8\",\n \"WidgetCustom9\",\n \"WidgetCustom10\",\n \"WidgetCustom11\",\n \"WidgetCustom12\",\n \"WidgetCustom13\",\n \"WidgetCustom14\",\n \"WidgetCustom15\",\n \"WidgetCustom16\",\n ]);\n\n return reportData;\n}","JsHelpers":"//Register custom Handlebars helpers here to use in your report script\n//https://handlebarsjs.com/guide/#custom-helpers\nHandlebars.registerHelper('loud', function (aString) {\n return aString.toUpperCase()\n})","RenderType":0,"HeaderTemplate":null,"FooterTemplate":null,"DisplayHeaderFooter":false,"PaperFormat":0,"Landscape":false,"MarginOptionsBottom":null,"MarginOptionsLeft":null,"MarginOptionsRight":null,"MarginOptionsTop":null,"PageRanges":null,"PreferCSSPageSize":false,"PrintBackground":false,"Scale":1.0000}
\ No newline at end of file
diff --git a/server/AyaNova/resource/rpt/stock-report-templates/SAMPLE showing IF ELSE inline html.ayrt b/server/AyaNova/resource/rpt/stock-report-templates/SAMPLE showing IF ELSE inline html.ayrt
index 2053d9ca..df6028a3 100644
--- a/server/AyaNova/resource/rpt/stock-report-templates/SAMPLE showing IF ELSE inline html.ayrt
+++ b/server/AyaNova/resource/rpt/stock-report-templates/SAMPLE showing IF ELSE inline html.ayrt
@@ -1 +1 @@
-{"Name":"SAMPLE showing IF ELSE inline html","Active":true,"Notes":"","Roles":124927,"ObjectType":2,"Template":"\n\n\n\t
Example: custom fields usage
\n\t
this is an examle report template that shows value of Count in red if has 0 or null, or shows green if has ANY value
\n\n\t
\n\t\t{{#each ayReportData}}\n\t\t
Name: {{ Name }}
\n\t\t{{#if Count}}
Count is: {{ Count }}
{{else}}
has 0 or null
{{/if}}\n\t\t
\t\t\n\t\t{{/each}}\n\t
\n\n\n","Style":".redFont {\r\n color: red;\r\n}\r\n\r\n.greenFont {\r\n color: green;\r\n}\r\n","JsPrerender":"async function ayPrepareData(reportData){ \n return reportData;\n}","JsHelpers":"","RenderType":0,"HeaderTemplate":null,"FooterTemplate":null,"DisplayHeaderFooter":false,"PaperFormat":0,"Landscape":false,"MarginOptionsBottom":null,"MarginOptionsLeft":null,"MarginOptionsRight":null,"MarginOptionsTop":null,"PageRanges":null,"PreferCSSPageSize":false,"PrintBackground":false,"Scale":1.0000}
\ No newline at end of file
+{"Name":"SAMPLE showing IF ELSE inline html","Active":true,"Notes":"","Roles":124927,"AType":2,"Template":"\n\n\n\t
Example: custom fields usage
\n\t
this is an examle report template that shows value of Count in red if has 0 or null, or shows green if has ANY value
\n\n\t
\n\t\t{{#each ayReportData}}\n\t\t
Name: {{ Name }}
\n\t\t{{#if Count}}
Count is: {{ Count }}
{{else}}
has 0 or null
{{/if}}\n\t\t
\t\t\n\t\t{{/each}}\n\t
\n\n\n","Style":".redFont {\r\n color: red;\r\n}\r\n\r\n.greenFont {\r\n color: green;\r\n}\r\n","JsPrerender":"async function ayPrepareData(reportData){ \n return reportData;\n}","JsHelpers":"","RenderType":0,"HeaderTemplate":null,"FooterTemplate":null,"DisplayHeaderFooter":false,"PaperFormat":0,"Landscape":false,"MarginOptionsBottom":null,"MarginOptionsLeft":null,"MarginOptionsRight":null,"MarginOptionsTop":null,"PageRanges":null,"PreferCSSPageSize":false,"PrintBackground":false,"Scale":1.0000}
\ No newline at end of file
diff --git a/server/AyaNova/resource/rpt/stock-report-templates/SAMPLE showing tag only if has specific tagword.ayrt b/server/AyaNova/resource/rpt/stock-report-templates/SAMPLE showing tag only if has specific tagword.ayrt
index 12ad01c6..4c895e7d 100644
--- a/server/AyaNova/resource/rpt/stock-report-templates/SAMPLE showing tag only if has specific tagword.ayrt
+++ b/server/AyaNova/resource/rpt/stock-report-templates/SAMPLE showing tag only if has specific tagword.ayrt
@@ -1 +1 @@
-{"Name":"SAMPLE showing tag only if has specific tagword","Active":true,"Notes":"","Roles":124927,"ObjectType":2,"Template":"\n\n\n\t
Example: custom fields usage
\n\t
See help documentation for details
\n\n\t
\n\t\t{{#each ayReportData}}\n\n\t\tName: {{ Name }}
\n\t\t\n\t\t
Tags:
\n\t\t
Displays first tag :::::{{ Tags.[0]}}
\n\t\t
Displays all tags for this object::::: {{ Tags}}
\n\t\t
Displays if has brown in its tags::::: {{ isInTag2 Tags}}
\n\t\t
Count: {{Count}}
\n\t\t\n\t\t\n\t\t
\n\t\t\t {{#if CustomFields.c4}} - true custom fields c4 is true
{{else}} - custom fields c4 is false
{{/if}}\n\t\t\t - Actual Count value: {{Count}}
\n\t\t\t {{#if Count}} - renders in red font if 'Count' has any value
{{else}} - renders in green font if false, undefined, null, \"\", 0, or []
{{/if}}\n\t\t
\n\n\t\t
{{isInTag3 Tags}}
\n\t\t\n\t\t{{/each}}\n\t
\n\n\n","Style":".redMe {\r\n color: red;\r\n}\r\n\r\n.greenMe {\r\n color: green;\r\n}\r\n\r\n.redfont {\r\n color: red;\r\n}","JsPrerender":"async function ayPrepareData(reportData){ \n return reportData;\n}","JsHelpers":"\r\n\r\nHandlebars.registerHelper('isInTag', function (Tags) \r\n{\r\n for (var i=0; i
\" + \"brownbrwnbrown is in here!!!!!!!!!!!!\" +\"\");\r\n\t\t}\r\n }\r\n return 'some other text'; //if don't want to return any element at all, comment this else aspect out fully\r\n});\r\n","RenderType":0,"HeaderTemplate":null,"FooterTemplate":null,"DisplayHeaderFooter":false,"PaperFormat":0,"Landscape":false,"MarginOptionsBottom":null,"MarginOptionsLeft":null,"MarginOptionsRight":null,"MarginOptionsTop":null,"PageRanges":null,"PreferCSSPageSize":false,"PrintBackground":false,"Scale":1.0000}
\ No newline at end of file
+{"Name":"SAMPLE showing tag only if has specific tagword","Active":true,"Notes":"","Roles":124927,"AType":2,"Template":"\n\n\n\tExample: custom fields usage
\n\tSee help documentation for details
\n\n\t\n\t\t{{#each ayReportData}}\n\n\t\tName: {{ Name }}
\n\t\t\n\t\t
Tags:
\n\t\t
Displays first tag :::::{{ Tags.[0]}}
\n\t\t
Displays all tags for this object::::: {{ Tags}}
\n\t\t
Displays if has brown in its tags::::: {{ isInTag2 Tags}}
\n\t\t
Count: {{Count}}
\n\t\t\n\t\t\n\t\t
\n\t\t\t {{#if CustomFields.c4}} - true custom fields c4 is true
{{else}} - custom fields c4 is false
{{/if}}\n\t\t\t - Actual Count value: {{Count}}
\n\t\t\t {{#if Count}} - renders in red font if 'Count' has any value
{{else}} - renders in green font if false, undefined, null, \"\", 0, or []
{{/if}}\n\t\t
\n\n\t\t
{{isInTag3 Tags}}
\n\t\t\n\t\t{{/each}}\n\t
\n\n\n","Style":".redMe {\r\n color: red;\r\n}\r\n\r\n.greenMe {\r\n color: green;\r\n}\r\n\r\n.redfont {\r\n color: red;\r\n}","JsPrerender":"async function ayPrepareData(reportData){ \n return reportData;\n}","JsHelpers":"\r\n\r\nHandlebars.registerHelper('isInTag', function (Tags) \r\n{\r\n for (var i=0; i\" + \"brownbrwnbrown is in here!!!!!!!!!!!!\" +\"\");\r\n\t\t}\r\n }\r\n return 'some other text'; //if don't want to return any element at all, comment this else aspect out fully\r\n});\r\n","RenderType":0,"HeaderTemplate":null,"FooterTemplate":null,"DisplayHeaderFooter":false,"PaperFormat":0,"Landscape":false,"MarginOptionsBottom":null,"MarginOptionsLeft":null,"MarginOptionsRight":null,"MarginOptionsTop":null,"PageRanges":null,"PreferCSSPageSize":false,"PrintBackground":false,"Scale":1.0000}
\ No newline at end of file
diff --git a/server/AyaNova/resource/rpt/stock-report-templates/SAMPLE widgets invoice rpt footer last pg only.ayrt b/server/AyaNova/resource/rpt/stock-report-templates/SAMPLE widgets invoice rpt footer last pg only.ayrt
index 2991f56f..49553f8f 100644
--- a/server/AyaNova/resource/rpt/stock-report-templates/SAMPLE widgets invoice rpt footer last pg only.ayrt
+++ b/server/AyaNova/resource/rpt/stock-report-templates/SAMPLE widgets invoice rpt footer last pg only.ayrt
@@ -1 +1 @@
-{"Name":"SAMPLE widgets invoice rpt footer last pg only","Active":true,"Notes":"","Roles":124927,"ObjectType":2,"Template":"\n\n\n\n\n\n\t\t\t\n\t\t
\n\t\t\t \n \n | {{ ayLogo \"small\" }} | \n PO#: A1A1G43 | \n Our Account #: 198453 | \n
\n \n \n | \n Ordered Date: 2020-09-13 | \n
\n \n \n | \n ETA Date: 2020-09-19 | \n
\n \n \n | VENDOR: | \n | \n DELIVER TO: | \n
\n \n | vendorName | \n | \n My Company Name | \n
\n \n | vstaddress | \n | \n 123 - 123 MyStreetname Ave | \n
\n \n | vstcity vststate vstpostal | \n | \n My City, My State, My Postal | \n
\n \n | Contact: vcontact vphone vemail | \n | \n Ordered By: creator Phone: creatorphone | \n
\n \n | | \n
\n \n | Our Part#: | \n Serial# | \n Price Per: | \n Net: | \n Tax A: | \n Tax B: | \n Line Total: | \n
\n \n\t\t\t\n\t\t\t\t{{#each ayReportData}}\n\t\t\t\t\t\t\t\t\n\t\t\t\t| {{Name}} | \n \t\t{{Serial}} | \n \t\t{{ayCurrency DollarAmount}} | \n \t\txx.xx | \n \t\tx.xx | \n \t\tx.xx | \n \t\t{{ayCurrency DollarAmount}} | \t\t\n\t\t\t\t
\n\t\t\t \t{{/each}}\n\t\t\t\n\t\t
\n\n
\n \n \n\t\t\t\t| | \n\t\t\t\t
\n\t\t\t\t\n\t\t\t\t | \n\t\t\t\tNet Total: | \n\t\t\t\t $xxx.xx | \n\t\t\t\t
\n\t\t\t\t\n\t\t\t\t| | \n\t\t\t\tTax A Total: | \n\t\t\t\t $xx.xx | \n\t\t\t\t
\n\t\t\t\t\n\t\t\t\t| Direct all inquiries to My Company 1-888-555-5555 | \n\t\t\t\tTax B Total: | \n\t\t\t\t$xx.xx | \n\t\t\t\t
\n \t\t\t\n \t\t\t| Approval for off-specification goods must be obtained via a new purchase order | \n \t\t\tPO Total: | \n \t\t\t{{ ayCurrency MyTotalDollarAmount }} | \n \t\t\t
\n \n
\n\n\t
\n \n\n\n\n\n","Style":"\ntable { \n font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif;\n border-collapse: collapse;\n white-space: pre-wrap;\n font-size: 9pt;\n width: 100%;\n }\n\nthead {\n display: table-header-group; /* so as to print the table-header on all subsequent pages */\n}\ntfoot {\n page-break-inside: avoid;\n}\n\n.heading {\n border-style: solid;\n border-width: 1pt;\n border-color: #e8e5e5; \n margin: 10pt;\n background-color: #e8e5e5;\n padding: 5pt; \n font-size: 11pt; \n} \n.fontsizeBig {\n font-size: 11pt;\n font-weight: bold ;\n\n}\n\n.rightlean {\n text-align: right;\n}\n.leftlean {\n text-align: left;\n}\n.centerlean {\n text-align: center;\n}\n\ntbody tr:nth-child(even) {\n background-color: lightgray; /* MUST checkmark Print background in PDF Options for this to show */\n} \n\n\n","JsPrerender":"async function ayPrepareData(reportData) {\n //this function (if present) is called with the report data \n //before the report is rendered\n //modify data as required here and return it to change the data before the report renders \n\n\n//Example of both manipulating the reportData before rendering the report (by adding a running total field)\n //and adding a field to the overall data calculating the total dollar amount for all records\n\n let TotalDollarAmount = 0; //Declare a temporary variable to hold the running total\n\n //Iterate through all the records in the reportData\n //adding the dollar amount of each item to the TotalDollarAmount variable\n for (EachItem of reportData.ayReportData) { //EachItem is name i've give, reportData.ayReportData is set\n\n //make sure it has a value before attempting to add it to the running total\n if (EachItem.DollarAmount != null) { //EachItem is name I've given, DollarAmount is the \n TotalDollarAmount += EachItem.DollarAmount;\n }\n\n //add a new key to each record in the reportData object named \"MyRunningTotal\" with the running total so far\n EachItem.MyRunningTotal=TotalDollarAmount;\n }\n\n //Add the TotalDollarAmount variable to the reportData so it can be \n //accessed in the report template\n reportData.MyTotalDollarAmount=TotalDollarAmount;\n\n\n\n//below gets your translations for the following field labels\nawait ayGetTranslations([\n \"Widget\",\n \"WidgetName\",\n \"WidgetSerial\",\n \"WidgetDollarAmount\",\n \"WidgetCount\",\n \"WidgetStartDate\",\n \"WidgetEndDate\",\n \"WidgetNotes\",\n \"WidgetCustom1\",\n \"WidgetCustom2\",\n \"WidgetCustom3\",\n \"WidgetCustom4\",\n \"WidgetCustom5\",\n \"WidgetCustom6\",\n \"WidgetCustom7\",\n \"WidgetCustom8\",\n \"WidgetCustom9\",\n \"WidgetCustom10\",\n \"WidgetCustom11\",\n \"WidgetCustom12\",\n \"WidgetCustom13\",\n \"WidgetCustom14\",\n \"WidgetCustom15\",\n \"WidgetCustom16\",\n ]);\n\n return reportData;\n}\n","JsHelpers":"//Register custom Handlebars helpers here to use in your report script\n//https://handlebarsjs.com/guide/#custom-helpers\nHandlebars.registerHelper('loud', function (aString) {\n return aString.toUpperCase()\n})\nHandlebars.registerHelper('words', function() {\n return \"stuff and text\"\n})\n\n\nHandlebars.registerHelper('todaysMonthDDYYYYDate', function() {\n var dt3=new Date();\n return dt3.toLocaleDateString(\n AYMETA.ayClientMetaData.LanguageName,//use Client browser default Language, change this setting here to force an alternative language\n {\n timeZone: AYMETA.ayClientMetaData.TimeZoneName,//use Client browser's default TimeZone, change this setting here to force a specific time zone\n dateStyle: \"long\"\n }\n ) ;\n});// today's date displayed in MONTH DD, YYYY format\n\n","RenderType":0,"HeaderTemplate":" Todays date: \nPage of \n","FooterTemplate":" ","DisplayHeaderFooter":true,"PaperFormat":10,"Landscape":false,"MarginOptionsBottom":"15mm","MarginOptionsLeft":"10mm","MarginOptionsRight":"10mm","MarginOptionsTop":"15mm","PageRanges":null,"PreferCSSPageSize":false,"PrintBackground":true,"Scale":1.0000}
\ No newline at end of file
+{"Name":"SAMPLE widgets invoice rpt footer last pg only","Active":true,"Notes":"","Roles":124927,"AType":2,"Template":"\n\n\n\n\n\n\t\t\t\n\t\t
\n\t\t\t \n \n | {{ ayLogo \"small\" }} | \n PO#: A1A1G43 | \n Our Account #: 198453 | \n
\n \n \n | \n Ordered Date: 2020-09-13 | \n
\n \n \n | \n ETA Date: 2020-09-19 | \n
\n \n \n | VENDOR: | \n | \n DELIVER TO: | \n
\n \n | vendorName | \n | \n My Company Name | \n
\n \n | vstaddress | \n | \n 123 - 123 MyStreetname Ave | \n
\n \n | vstcity vststate vstpostal | \n | \n My City, My State, My Postal | \n
\n \n | Contact: vcontact vphone vemail | \n | \n Ordered By: creator Phone: creatorphone | \n
\n \n | | \n
\n \n | Our Part#: | \n Serial# | \n Price Per: | \n Net: | \n Tax A: | \n Tax B: | \n Line Total: | \n
\n \n\t\t\t\n\t\t\t\t{{#each ayReportData}}\n\t\t\t\t\t\t\t\t\n\t\t\t\t| {{Name}} | \n \t\t{{Serial}} | \n \t\t{{ayCurrency DollarAmount}} | \n \t\txx.xx | \n \t\tx.xx | \n \t\tx.xx | \n \t\t{{ayCurrency DollarAmount}} | \t\t\n\t\t\t\t
\n\t\t\t \t{{/each}}\n\t\t\t\n\t\t
\n\n
\n \n \n\t\t\t\t| | \n\t\t\t\t
\n\t\t\t\t\n\t\t\t\t | \n\t\t\t\tNet Total: | \n\t\t\t\t $xxx.xx | \n\t\t\t\t
\n\t\t\t\t\n\t\t\t\t| | \n\t\t\t\tTax A Total: | \n\t\t\t\t $xx.xx | \n\t\t\t\t
\n\t\t\t\t\n\t\t\t\t| Direct all inquiries to My Company 1-888-555-5555 | \n\t\t\t\tTax B Total: | \n\t\t\t\t$xx.xx | \n\t\t\t\t
\n \t\t\t\n \t\t\t| Approval for off-specification goods must be obtained via a new purchase order | \n \t\t\tPO Total: | \n \t\t\t{{ ayCurrency MyTotalDollarAmount }} | \n \t\t\t
\n \n
\n\n\t
\n \n\n\n\n\n","Style":"\ntable { \n font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif;\n border-collapse: collapse;\n white-space: pre-wrap;\n font-size: 9pt;\n width: 100%;\n }\n\nthead {\n display: table-header-group; /* so as to print the table-header on all subsequent pages */\n}\ntfoot {\n page-break-inside: avoid;\n}\n\n.heading {\n border-style: solid;\n border-width: 1pt;\n border-color: #e8e5e5; \n margin: 10pt;\n background-color: #e8e5e5;\n padding: 5pt; \n font-size: 11pt; \n} \n.fontsizeBig {\n font-size: 11pt;\n font-weight: bold ;\n\n}\n\n.rightlean {\n text-align: right;\n}\n.leftlean {\n text-align: left;\n}\n.centerlean {\n text-align: center;\n}\n\ntbody tr:nth-child(even) {\n background-color: lightgray; /* MUST checkmark Print background in PDF Options for this to show */\n} \n\n\n","JsPrerender":"async function ayPrepareData(reportData) {\n //this function (if present) is called with the report data \n //before the report is rendered\n //modify data as required here and return it to change the data before the report renders \n\n\n//Example of both manipulating the reportData before rendering the report (by adding a running total field)\n //and adding a field to the overall data calculating the total dollar amount for all records\n\n let TotalDollarAmount = 0; //Declare a temporary variable to hold the running total\n\n //Iterate through all the records in the reportData\n //adding the dollar amount of each item to the TotalDollarAmount variable\n for (EachItem of reportData.ayReportData) { //EachItem is name i've give, reportData.ayReportData is set\n\n //make sure it has a value before attempting to add it to the running total\n if (EachItem.DollarAmount != null) { //EachItem is name I've given, DollarAmount is the \n TotalDollarAmount += EachItem.DollarAmount;\n }\n\n //add a new key to each record in the reportData object named \"MyRunningTotal\" with the running total so far\n EachItem.MyRunningTotal=TotalDollarAmount;\n }\n\n //Add the TotalDollarAmount variable to the reportData so it can be \n //accessed in the report template\n reportData.MyTotalDollarAmount=TotalDollarAmount;\n\n\n\n//below gets your translations for the following field labels\nawait ayGetTranslations([\n \"Widget\",\n \"WidgetName\",\n \"WidgetSerial\",\n \"WidgetDollarAmount\",\n \"WidgetCount\",\n \"WidgetStartDate\",\n \"WidgetEndDate\",\n \"WidgetNotes\",\n \"WidgetCustom1\",\n \"WidgetCustom2\",\n \"WidgetCustom3\",\n \"WidgetCustom4\",\n \"WidgetCustom5\",\n \"WidgetCustom6\",\n \"WidgetCustom7\",\n \"WidgetCustom8\",\n \"WidgetCustom9\",\n \"WidgetCustom10\",\n \"WidgetCustom11\",\n \"WidgetCustom12\",\n \"WidgetCustom13\",\n \"WidgetCustom14\",\n \"WidgetCustom15\",\n \"WidgetCustom16\",\n ]);\n\n return reportData;\n}\n","JsHelpers":"//Register custom Handlebars helpers here to use in your report script\n//https://handlebarsjs.com/guide/#custom-helpers\nHandlebars.registerHelper('loud', function (aString) {\n return aString.toUpperCase()\n})\nHandlebars.registerHelper('words', function() {\n return \"stuff and text\"\n})\n\n\nHandlebars.registerHelper('todaysMonthDDYYYYDate', function() {\n var dt3=new Date();\n return dt3.toLocaleDateString(\n AYMETA.ayClientMetaData.LanguageName,//use Client browser default Language, change this setting here to force an alternative language\n {\n timeZone: AYMETA.ayClientMetaData.TimeZoneName,//use Client browser's default TimeZone, change this setting here to force a specific time zone\n dateStyle: \"long\"\n }\n ) ;\n});// today's date displayed in MONTH DD, YYYY format\n\n","RenderType":0,"HeaderTemplate":" Todays date: \nPage of \n","FooterTemplate":" ","DisplayHeaderFooter":true,"PaperFormat":10,"Landscape":false,"MarginOptionsBottom":"15mm","MarginOptionsLeft":"10mm","MarginOptionsRight":"10mm","MarginOptionsTop":"15mm","PageRanges":null,"PreferCSSPageSize":false,"PrintBackground":true,"Scale":1.0000}
\ No newline at end of file
diff --git a/server/AyaNova/resource/rpt/stock-report-templates/SAMPLE widgets invoice rpt head footer repeats.ayrt b/server/AyaNova/resource/rpt/stock-report-templates/SAMPLE widgets invoice rpt head footer repeats.ayrt
index c9c23e3e..d2133f3b 100644
--- a/server/AyaNova/resource/rpt/stock-report-templates/SAMPLE widgets invoice rpt head footer repeats.ayrt
+++ b/server/AyaNova/resource/rpt/stock-report-templates/SAMPLE widgets invoice rpt head footer repeats.ayrt
@@ -1 +1 @@
-{"Name":"SAMPLE widgets invoice rpt head footer repeats","Active":true,"Notes":"","Roles":124927,"ObjectType":2,"Template":"\n\n\n\n\n\n\t\t\t\n\t\t
\n\t\t\t \n \n | {{ ayLogo \"small\" }} | \n PO#: A1A1G43 | \n Our Account #: 198453 | \n
\n \n \n | \n Ordered Date: 2020-09-13 | \n
\n \n \n | \n ETA Date: 2020-09-19 | \n
\n \n \n | VENDOR: | \n | \n DELIVER TO: | \n
\n \n | vendorName | \n | \n My Company Name | \n
\n \n | vstaddress | \n | \n 123 - 123 MyStreetname Ave | \n
\n \n | vstcity vststate vstpostal | \n | \n My City, My State, My Postal | \n
\n \n | Contact: vcontact vphone vemail | \n | \n Ordered By: creator Phone: creatorphone | \n
\n\n \n | | \n
\n \n \n | Our Part#: | \n Serial# | \n Price Per: | \n Net: | \n Tax A: | \n Tax B: | \n Line Total: | \n
\n \n \n \n\t\t\t\t| | \n\t\t\t\t
\n\t\t\t\t\n\t\t\t\t | \n\t\t\t\tNet Total for all pages: | \n\t\t\t\t $xxx.xx | \n\t\t\t\t
\n\t\t\t\t\n\t\t\t\t| | \n\t\t\t\tTax A Total for all pages: | \n\t\t\t\t $xx.xx | \n\t\t\t\t
\n\t\t\t\t\n\t\t\t\t| Direct all inquiries to My Company 1-888-555-5555 | \n\t\t\t\tTax B Total for all pages: | \n\t\t\t\t$xx.xx | \n\t\t\t\t
\n \t\t\t\n \t\t\t| Approval for off-specification goods must be obtained via a new purchase order | \n \t\t\tPO Total for all pages: | \n \t\t\t{{ ayCurrency MyTotalDollarAmount }} | \n \t\t\t
\n \n\t\t\t\n\t\t\t\t{{#each ayReportData}}\n\t\t\t\t\t\t\t\t\n\t\t\t\t| {{Name}} | \n \t\t{{Serial}} | \n \t\t{{ayCurrency DollarAmount}} | \n \t\txx.xx | \n \t\tx.xx | \n \t\tx.xx | \n \t\t{{ayCurrency DollarAmount}} | \t\t\n\t\t\t\t
\n\t\t\t \t{{/each}}\n\t\t\t\n\t\t
\n\n\n\n\t
\n \n\n\n\n\n","Style":"\ntable { \n font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif;\n border-collapse: collapse;\n white-space: pre-wrap;\n font-size: 9pt;\n width: 100%;\n }\n\nthead {\n display: table-header-group; /* so as to print the table-header on all subsequent pages */\n}\ntfoot {\n display: table-footer-group; /* so as to print the table-footer on all subsequent pages */\n page-break-inside: avoid;\n}\n\n.heading {\n border-style: solid;\n border-width: 1pt;\n border-color: #e8e5e5; \n margin: 10pt;\n background-color: #e8e5e5;\n padding: 5pt; \n font-size: 11pt; \n} \n.fontsizeBig {\n font-size: 10pt;\n font-weight: bold ;\n\n}\n\n.rightlean {\n text-align: right;\n}\n.leftlean {\n text-align: left;\n}\n.centerlean {\n text-align: center;\n}\n\ntbody tr:nth-child(even) {\n background-color: lightgray; /* MUST checkmark Print background in PDF Options for this to show */\n} \n\n\n","JsPrerender":"async function ayPrepareData(reportData) {\n //this function (if present) is called with the report data \n //before the report is rendered\n //modify data as required here and return it to change the data before the report renders \n\n\n//Example of both manipulating the reportData before rendering the report (by adding a running total field)\n //and adding a field to the overall data calculating the total dollar amount for all records\n\n let TotalDollarAmount = 0; //Declare a temporary variable to hold the running total\n\n //Iterate through all the records in the reportData\n //adding the dollar amount of each item to the TotalDollarAmount variable\n for (EachItem of reportData.ayReportData) { //EachItem is name i've give, reportData.ayReportData is set\n\n //make sure it has a value before attempting to add it to the running total\n if (EachItem.DollarAmount != null) { //EachItem is name I've given, DollarAmount is the \n TotalDollarAmount += EachItem.DollarAmount;\n }\n\n //add a new key to each record in the reportData object named \"MyRunningTotal\" with the running total so far\n EachItem.MyRunningTotal=TotalDollarAmount;\n }\n\n //Add the TotalDollarAmount variable to the reportData so it can be \n //accessed in the report template\n reportData.MyTotalDollarAmount=TotalDollarAmount;\n\n\n\n//below gets your translations for the following field labels\nawait ayGetTranslations([\n \"Widget\",\n \"WidgetName\",\n \"WidgetSerial\",\n \"WidgetDollarAmount\",\n \"WidgetCount\",\n \"WidgetStartDate\",\n \"WidgetEndDate\",\n \"WidgetNotes\",\n \"WidgetCustom1\",\n \"WidgetCustom2\",\n \"WidgetCustom3\",\n \"WidgetCustom4\",\n \"WidgetCustom5\",\n \"WidgetCustom6\",\n \"WidgetCustom7\",\n \"WidgetCustom8\",\n \"WidgetCustom9\",\n \"WidgetCustom10\",\n \"WidgetCustom11\",\n \"WidgetCustom12\",\n \"WidgetCustom13\",\n \"WidgetCustom14\",\n \"WidgetCustom15\",\n \"WidgetCustom16\",\n ]);\n\n return reportData;\n}\n","JsHelpers":"//Register custom Handlebars helpers here to use in your report script\n//https://handlebarsjs.com/guide/#custom-helpers\nHandlebars.registerHelper('loud', function (aString) {\n return aString.toUpperCase()\n})\nHandlebars.registerHelper('words', function() {\n return \"stuff and text\"\n})\n\n\nHandlebars.registerHelper('todaysMonthDDYYYYDate', function() {\n var dt3=new Date();\n return dt3.toLocaleDateString(\n AYMETA.ayClientMetaData.LanguageName,//use Client browser default Language, change this setting here to force an alternative language\n {\n timeZone: AYMETA.ayClientMetaData.TimeZoneName,//use Client browser's default TimeZone, change this setting here to force a specific time zone\n dateStyle: \"long\"\n }\n ) ;\n});// today's date displayed in MONTH DD, YYYY format\n\n","RenderType":0,"HeaderTemplate":" Todays date: \nPage of \n","FooterTemplate":" ","DisplayHeaderFooter":true,"PaperFormat":10,"Landscape":false,"MarginOptionsBottom":"15mm","MarginOptionsLeft":"10mm","MarginOptionsRight":"10mm","MarginOptionsTop":"15mm","PageRanges":null,"PreferCSSPageSize":false,"PrintBackground":true,"Scale":1.0000}
\ No newline at end of file
+{"Name":"SAMPLE widgets invoice rpt head footer repeats","Active":true,"Notes":"","Roles":124927,"AType":2,"Template":"\n\n\n\n\n\n\t\t\t\n\t\t
\n\t\t\t \n \n | {{ ayLogo \"small\" }} | \n PO#: A1A1G43 | \n Our Account #: 198453 | \n
\n \n \n | \n Ordered Date: 2020-09-13 | \n
\n \n \n | \n ETA Date: 2020-09-19 | \n
\n \n \n | VENDOR: | \n | \n DELIVER TO: | \n
\n \n | vendorName | \n | \n My Company Name | \n
\n \n | vstaddress | \n | \n 123 - 123 MyStreetname Ave | \n
\n \n | vstcity vststate vstpostal | \n | \n My City, My State, My Postal | \n
\n \n | Contact: vcontact vphone vemail | \n | \n Ordered By: creator Phone: creatorphone | \n
\n\n \n | | \n
\n \n \n | Our Part#: | \n Serial# | \n Price Per: | \n Net: | \n Tax A: | \n Tax B: | \n Line Total: | \n
\n \n \n \n\t\t\t\t| | \n\t\t\t\t
\n\t\t\t\t\n\t\t\t\t | \n\t\t\t\tNet Total for all pages: | \n\t\t\t\t $xxx.xx | \n\t\t\t\t
\n\t\t\t\t\n\t\t\t\t| | \n\t\t\t\tTax A Total for all pages: | \n\t\t\t\t $xx.xx | \n\t\t\t\t
\n\t\t\t\t\n\t\t\t\t| Direct all inquiries to My Company 1-888-555-5555 | \n\t\t\t\tTax B Total for all pages: | \n\t\t\t\t$xx.xx | \n\t\t\t\t
\n \t\t\t\n \t\t\t| Approval for off-specification goods must be obtained via a new purchase order | \n \t\t\tPO Total for all pages: | \n \t\t\t{{ ayCurrency MyTotalDollarAmount }} | \n \t\t\t
\n \n\t\t\t\n\t\t\t\t{{#each ayReportData}}\n\t\t\t\t\t\t\t\t\n\t\t\t\t| {{Name}} | \n \t\t{{Serial}} | \n \t\t{{ayCurrency DollarAmount}} | \n \t\txx.xx | \n \t\tx.xx | \n \t\tx.xx | \n \t\t{{ayCurrency DollarAmount}} | \t\t\n\t\t\t\t
\n\t\t\t \t{{/each}}\n\t\t\t\n\t\t
\n\n\n\n\t
\n \n\n\n\n\n","Style":"\ntable { \n font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif;\n border-collapse: collapse;\n white-space: pre-wrap;\n font-size: 9pt;\n width: 100%;\n }\n\nthead {\n display: table-header-group; /* so as to print the table-header on all subsequent pages */\n}\ntfoot {\n display: table-footer-group; /* so as to print the table-footer on all subsequent pages */\n page-break-inside: avoid;\n}\n\n.heading {\n border-style: solid;\n border-width: 1pt;\n border-color: #e8e5e5; \n margin: 10pt;\n background-color: #e8e5e5;\n padding: 5pt; \n font-size: 11pt; \n} \n.fontsizeBig {\n font-size: 10pt;\n font-weight: bold ;\n\n}\n\n.rightlean {\n text-align: right;\n}\n.leftlean {\n text-align: left;\n}\n.centerlean {\n text-align: center;\n}\n\ntbody tr:nth-child(even) {\n background-color: lightgray; /* MUST checkmark Print background in PDF Options for this to show */\n} \n\n\n","JsPrerender":"async function ayPrepareData(reportData) {\n //this function (if present) is called with the report data \n //before the report is rendered\n //modify data as required here and return it to change the data before the report renders \n\n\n//Example of both manipulating the reportData before rendering the report (by adding a running total field)\n //and adding a field to the overall data calculating the total dollar amount for all records\n\n let TotalDollarAmount = 0; //Declare a temporary variable to hold the running total\n\n //Iterate through all the records in the reportData\n //adding the dollar amount of each item to the TotalDollarAmount variable\n for (EachItem of reportData.ayReportData) { //EachItem is name i've give, reportData.ayReportData is set\n\n //make sure it has a value before attempting to add it to the running total\n if (EachItem.DollarAmount != null) { //EachItem is name I've given, DollarAmount is the \n TotalDollarAmount += EachItem.DollarAmount;\n }\n\n //add a new key to each record in the reportData object named \"MyRunningTotal\" with the running total so far\n EachItem.MyRunningTotal=TotalDollarAmount;\n }\n\n //Add the TotalDollarAmount variable to the reportData so it can be \n //accessed in the report template\n reportData.MyTotalDollarAmount=TotalDollarAmount;\n\n\n\n//below gets your translations for the following field labels\nawait ayGetTranslations([\n \"Widget\",\n \"WidgetName\",\n \"WidgetSerial\",\n \"WidgetDollarAmount\",\n \"WidgetCount\",\n \"WidgetStartDate\",\n \"WidgetEndDate\",\n \"WidgetNotes\",\n \"WidgetCustom1\",\n \"WidgetCustom2\",\n \"WidgetCustom3\",\n \"WidgetCustom4\",\n \"WidgetCustom5\",\n \"WidgetCustom6\",\n \"WidgetCustom7\",\n \"WidgetCustom8\",\n \"WidgetCustom9\",\n \"WidgetCustom10\",\n \"WidgetCustom11\",\n \"WidgetCustom12\",\n \"WidgetCustom13\",\n \"WidgetCustom14\",\n \"WidgetCustom15\",\n \"WidgetCustom16\",\n ]);\n\n return reportData;\n}\n","JsHelpers":"//Register custom Handlebars helpers here to use in your report script\n//https://handlebarsjs.com/guide/#custom-helpers\nHandlebars.registerHelper('loud', function (aString) {\n return aString.toUpperCase()\n})\nHandlebars.registerHelper('words', function() {\n return \"stuff and text\"\n})\n\n\nHandlebars.registerHelper('todaysMonthDDYYYYDate', function() {\n var dt3=new Date();\n return dt3.toLocaleDateString(\n AYMETA.ayClientMetaData.LanguageName,//use Client browser default Language, change this setting here to force an alternative language\n {\n timeZone: AYMETA.ayClientMetaData.TimeZoneName,//use Client browser's default TimeZone, change this setting here to force a specific time zone\n dateStyle: \"long\"\n }\n ) ;\n});// today's date displayed in MONTH DD, YYYY format\n\n","RenderType":0,"HeaderTemplate":" Todays date: \nPage of \n","FooterTemplate":" ","DisplayHeaderFooter":true,"PaperFormat":10,"Landscape":false,"MarginOptionsBottom":"15mm","MarginOptionsLeft":"10mm","MarginOptionsRight":"10mm","MarginOptionsTop":"15mm","PageRanges":null,"PreferCSSPageSize":false,"PrintBackground":true,"Scale":1.0000}
\ No newline at end of file
diff --git a/server/AyaNova/util/AySchema.cs b/server/AyaNova/util/AySchema.cs
index 8e009de7..f6800c4c 100644
--- a/server/AyaNova/util/AySchema.cs
+++ b/server/AyaNova/util/AySchema.cs
@@ -268,7 +268,7 @@ namespace AyaNova.Util
await ExecQueryAsync("CREATE TABLE aevent (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, created TIMESTAMP NOT NULL, userid BIGINT NOT NULL,"
+ "ayid BIGINT NOT NULL, ayatype INTEGER NOT NULL, ayevent INTEGER NOT NULL, textra VARCHAR(255))");
//INDEX: Most selective first as there is more UNIQUE ID's than UNIQUE types
- await ExecQueryAsync("CREATE INDEX idx_aevent_ayid_aytype ON aevent (ayid, ayatype);");
+ await ExecQueryAsync("CREATE INDEX idx_aevent_ayid_aType ON aevent (ayid, ayatype);");
//TODO: this may be a very low used index, revisit it down the road
await ExecQueryAsync("CREATE INDEX idx_aevent_userid ON aevent (userid);");
@@ -288,17 +288,17 @@ namespace AyaNova.Util
//await ExecQueryAsync("CREATE UNIQUE INDEX asearchdictionary_word_idx ON asearchdictionary (word);");
//search key
- await ExecQueryAsync("CREATE TABLE asearchkey (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, wordid BIGINT NOT NULL REFERENCES asearchdictionary (id), objectid BIGINT NOT NULL, objecttype INTEGER NOT NULL)");
+ await ExecQueryAsync("CREATE TABLE asearchkey (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, wordid BIGINT NOT NULL REFERENCES asearchdictionary (id), objectid BIGINT NOT NULL, atype INTEGER NOT NULL)");
//INDEX: Most selective first as there is more UNIQUE ID's than UNIQUE types
- //to take advantage of this always query with where objectid=xx and objecttype=yy order
+ //to take advantage of this always query with where objectid=xx and atype=yy order
//Only delete would use this, but, likely not needed as it's not in a loop
- //await ExecQueryAsync("CREATE INDEX asearchkey_typeid_idx ON asearchkey (objectid, objecttype );");
+ //await ExecQueryAsync("CREATE INDEX asearchkey_typeid_idx ON asearchkey (objectid, atype );");
//This is what is needed during Searching
- //search does a lot of hits on searchkey looking for the wordid and optionally objecttype
- //In testing this did not pan out, in fact it was much faster to search both with and without a objecttype specified to simply have an index on wordid
- // await ExecQueryAsync("CREATE INDEX asearchkey_wordid_otype_idx ON asearchkey (wordid, objecttype);");
+ //search does a lot of hits on searchkey looking for the wordid and optionally atype
+ //In testing this did not pan out, in fact it was much faster to search both with and without a atype specified to simply have an index on wordid
+ // await ExecQueryAsync("CREATE INDEX asearchkey_wordid_otype_idx ON asearchkey (wordid, atype);");
await ExecQueryAsync("CREATE INDEX idx_asearchkey_wordid ON asearchkey (wordid);");
//Search indexing stored procedure
@@ -306,7 +306,7 @@ namespace AyaNova.Util
CREATE OR REPLACE PROCEDURE public.aydosearchindex(
wordlist TEXT[],
ayobjectid BIGINT,
- ayobjecttype INTEGER,
+ ayatype INTEGER,
cleanfirst boolean)
LANGUAGE 'plpgsql'
@@ -318,12 +318,12 @@ BEGIN
RAISE EXCEPTION 'Bad object id --> %', ayobjectid;
END IF;
- IF ayobjecttype=0 THEN
- RAISE EXCEPTION 'Bad object type --> %', ayobjecttype;
+ IF ayatype=0 THEN
+ RAISE EXCEPTION 'Bad object type --> %', ayatype;
END IF;
IF cleanfirst=true THEN
- delete from asearchkey where objectid=ayobjectid and objecttype=ayobjecttype;
+ delete from asearchkey where objectid=ayobjectid and atype=ayatype;
END IF;
FOREACH s IN ARRAY wordlist
@@ -331,9 +331,9 @@ BEGIN
SELECT id INTO wordid FROM asearchdictionary WHERE word = s;
IF wordid IS NULL THEN
insert into asearchdictionary (word) values(s) on conflict (word) do update set word=excluded.word returning id into wordid;
- insert into asearchkey (wordid,objectid,objecttype) values(wordid,ayobjectid,ayobjecttype);
+ insert into asearchkey (wordid,objectid,atype) values(wordid,ayobjectid,ayatype);
ELSE
- insert into asearchkey (wordid,objectid,objecttype) values(wordid,ayobjectid,ayobjecttype);
+ insert into asearchkey (wordid,objectid,atype) values(wordid,ayobjectid,ayatype);
END IF;
END LOOP;
END;
@@ -343,13 +343,13 @@ $BODY$;
//Name fetcher function
//CoreBizObject ADD here
await ExecQueryAsync(@"
-CREATE OR REPLACE FUNCTION PUBLIC.AYGETNAME(IN AYOBJECTID BIGINT, IN AYOBJECTTYPE INTEGER) RETURNS TEXT AS $BODY$
+CREATE OR REPLACE FUNCTION PUBLIC.AYGETNAME(IN AYOBJECTID BIGINT, IN AYATYPE INTEGER) RETURNS TEXT AS $BODY$
DECLARE
aytable TEXT DEFAULT '';
aynamecolumn TEXT DEFAULT 'name';
returnstr TEXT DEFAULT '';
BEGIN
- case ayobjecttype
+ case ayatype
when 0 then return 'LT:NoType';
when 1 then return 'LT:Global';
when 2 then aytable = 'awidget';
@@ -496,7 +496,7 @@ $BODY$ LANGUAGE PLPGSQL STABLE");
LogUpdateMessage(log);
await ExecQueryAsync("CREATE TABLE afileattachment (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, "
- + "attachtoobjectid BIGINT NOT NULL, attachtoobjecttype INTEGER NOT NULL, "
+ + "attachtoobjectid BIGINT NOT NULL, attachtoatype INTEGER NOT NULL, "
+ "storedfilename TEXT NOT NULL, displayfilename TEXT NOT NULL, contenttype TEXT, lastmodified TIMESTAMP NOT NULL, notes TEXT, exists BOOL NOT NULL, size BIGINT NOT NULL)");
//index required for ops that need to check if file already in db (delete, count refs etc)
@@ -505,7 +505,7 @@ $BODY$ LANGUAGE PLPGSQL STABLE");
//index for the common issue of checking if an object has an attachment and retrieving them
//note always query (where clause) in this same order for best performance
- await ExecQueryAsync("CREATE INDEX idx_afileattachment_attachtoobjectid_attachtoobjecttype ON afileattachment (attachtoobjectid, attachtoobjecttype );");
+ await ExecQueryAsync("CREATE INDEX idx_afileattachment_attachtoobjectid_attachtoatype ON afileattachment (attachtoobjectid, attachtoatype );");
await SetSchemaLevelAsync(++currentSchema);
}
@@ -520,7 +520,7 @@ $BODY$ LANGUAGE PLPGSQL STABLE");
LogUpdateMessage(log);
await ExecQueryAsync("CREATE TABLE aopsjob (gid uuid PRIMARY KEY, name TEXT NOT NULL, created TIMESTAMP NOT NULL, exclusive BOOL NOT NULL, "
- + "startafter TIMESTAMP NOT NULL, jobtype INTEGER NOT NULL, subtype INTEGER, objectid BIGINT, objecttype INTEGER, jobstatus INTEGER NOT NULL, jobinfo TEXT)");
+ + "startafter TIMESTAMP NOT NULL, jobtype INTEGER NOT NULL, subtype INTEGER, objectid BIGINT, atype INTEGER, jobstatus INTEGER NOT NULL, jobinfo TEXT)");
await ExecQueryAsync("CREATE TABLE aopsjoblog (gid uuid PRIMARY KEY, jobid uuid NOT NULL, created TIMESTAMP NOT NULL, statustext TEXT NOT NULL)");
await SetSchemaLevelAsync(++currentSchema);
}
@@ -619,9 +619,9 @@ $BODY$ LANGUAGE PLPGSQL STABLE");
await ExecQueryAsync("CREATE TABLE areview (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, name TEXT NOT NULL, "
+ "notes TEXT, wiki TEXT, customfields TEXT, tags VARCHAR(255) ARRAY, "
+ "duedate TIMESTAMP NOT NULL, completeddate TIMESTAMP NULL, completionnotes TEXT, userid BIGINT NOT NULL REFERENCES auser(id), "
- + "assignedbyuserid BIGINT NOT NULL REFERENCES auser(id), objecttype INTEGER NOT NULL, objectid BIGINT NOT NULL)");
+ + "assignedbyuserid BIGINT NOT NULL REFERENCES auser(id), atype INTEGER NOT NULL, objectid BIGINT NOT NULL)");
- await ExecQueryAsync("CREATE INDEX idx_areview_objectid_objecttype ON areview (objectid, objecttype );");
+ await ExecQueryAsync("CREATE INDEX idx_areview_objectid_atype ON areview (objectid, atype );");
await ExecQueryAsync("CREATE INDEX idx_areview_userid ON areview (userid);");
await ExecQueryAsync("CREATE INDEX idx_areview_duedate ON areview (duedate);");
await ExecQueryAsync("CREATE INDEX idx_areview_completeddate ON areview (completeddate);");
@@ -630,20 +630,20 @@ $BODY$ LANGUAGE PLPGSQL STABLE");
//SERVICE BANK
//Note: I'm allowing negative balances so this code differs slightly from the example it was drawn from https://dba.stackexchange.com/a/19368
await ExecQueryAsync("CREATE TABLE aservicebank (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, name TEXT NOT NULL, "
- + "entrydate TIMESTAMP NOT NULL, lastentrydate TIMESTAMP NULL, objecttype INTEGER NOT NULL, objectid BIGINT NOT NULL, sourcetype INTEGER NOT NULL, sourceid BIGINT NOT NULL, "
+ + "entrydate TIMESTAMP NOT NULL, lastentrydate TIMESTAMP NULL, atype INTEGER NOT NULL, objectid BIGINT NOT NULL, sourcetype INTEGER NOT NULL, sourceid BIGINT NOT NULL, "
+ "incidents DECIMAL(19,5) NOT NULL, incidentsbalance DECIMAL(19,5) NOT NULL, lastincidentsbalance DECIMAL(19,5) NULL, "
+ "currency DECIMAL(38,18) NOT NULL, currencybalance DECIMAL(38,18) NOT NULL, lastcurrencybalance DECIMAL(38,18) NULL, "
+ "hours DECIMAL(19,5) NOT NULL, hoursbalance DECIMAL(19,5) NOT NULL, lasthoursbalance DECIMAL(19,5) NULL, "
- + "CONSTRAINT unq_servicebank UNIQUE (entrydate, objectid, objecttype, incidentsbalance, hoursbalance, currencybalance), "
- + "CONSTRAINT unq_servicebank_previous_values UNIQUE (lastentrydate, objectid, objecttype, lastincidentsbalance, lasthoursbalance, lastcurrencybalance), "
- + "CONSTRAINT fk_servicebank_self FOREIGN KEY (lastentrydate, objectid, objecttype, lastincidentsbalance, lasthoursbalance, lastcurrencybalance) REFERENCES aservicebank(entrydate, objectid, objecttype, incidentsbalance, hoursbalance, currencybalance), "
+ + "CONSTRAINT unq_servicebank UNIQUE (entrydate, objectid, atype, incidentsbalance, hoursbalance, currencybalance), "
+ + "CONSTRAINT unq_servicebank_previous_values UNIQUE (lastentrydate, objectid, atype, lastincidentsbalance, lasthoursbalance, lastcurrencybalance), "
+ + "CONSTRAINT fk_servicebank_self FOREIGN KEY (lastentrydate, objectid, atype, lastincidentsbalance, lasthoursbalance, lastcurrencybalance) REFERENCES aservicebank(entrydate, objectid, atype, incidentsbalance, hoursbalance, currencybalance), "
+ "CONSTRAINT chk_servicebank_valid_incidentbalance CHECK(incidentsbalance = COALESCE(lastincidentsbalance, 0) + incidents), "
+ "CONSTRAINT chk_servicebank_valid_currencybalance CHECK(currencybalance = COALESCE(lastcurrencybalance, 0) + currency), "
+ "CONSTRAINT chk_servicebank_valid_hoursbalance CHECK(hoursbalance = COALESCE(lasthoursbalance, 0) + hours), "
+ "CONSTRAINT chk_servicebank_valid_dates_sequence CHECK(lastentrydate < entrydate), "
+ "CONSTRAINT chk_servicebank_valid_previous_columns CHECK((lastentrydate IS NULL AND lastincidentsbalance IS NULL AND lastcurrencybalance IS NULL AND lasthoursbalance IS NULL) OR (lastentrydate IS NOT NULL AND lastincidentsbalance IS NOT NULL AND lastcurrencybalance IS NOT NULL AND lasthoursbalance IS NOT NULL)) "
+ " )");
- await ExecQueryAsync("CREATE INDEX idx_aservicebank_objectid_objecttype ON aservicebank (objectid, objecttype );");
+ await ExecQueryAsync("CREATE INDEX idx_aservicebank_objectid_atype ON aservicebank (objectid, atype );");
//CONTRACT
await ExecQueryAsync("CREATE TABLE acontract (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, name TEXT NOT NULL UNIQUE, active BOOL NOT NULL, "
@@ -1000,7 +1000,7 @@ $BODY$ LANGUAGE PLPGSQL STABLE");
{
LogUpdateMessage(log);
await ExecQueryAsync("CREATE TABLE areport (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, name TEXT NOT NULL UNIQUE, active BOOL NOT NULL, "
- + "notes TEXT, roles INTEGER NOT NULL, objecttype INTEGER NOT NULL, template TEXT, style TEXT, jsprerender TEXT, jshelpers TEXT, rendertype INTEGER NOT NULL, "
+ + "notes TEXT, roles INTEGER NOT NULL, atype INTEGER NOT NULL, template TEXT, style TEXT, jsprerender TEXT, jshelpers TEXT, rendertype INTEGER NOT NULL, "
+ "headertemplate TEXT, footertemplate TEXT, displayheaderfooter BOOL, paperformat INTEGER NOT NULL, landscape BOOL, marginoptionsbottom TEXT, "
+ "marginoptionsleft TEXT, marginoptionsright TEXT, marginoptionstop TEXT, pageranges TEXT, prefercsspagesize BOOL, printbackground BOOL, scale DECIMAL(8,5) )");
await SetSchemaLevelAsync(++currentSchema);
diff --git a/server/AyaNova/util/FileUtil.cs b/server/AyaNova/util/FileUtil.cs
index a2c68c71..e75651a9 100644
--- a/server/AyaNova/util/FileUtil.cs
+++ b/server/AyaNova/util/FileUtil.cs
@@ -451,7 +451,7 @@ namespace AyaNova.Util
Notes = notes,
ContentType = contentType,
AttachToObjectId = attachToObject.ObjectId,
- AttachToObjectType = attachToObject.ObjectType,
+ AttachToAType = attachToObject.AType,
LastModified = lastModified,
Size = FileSize
@@ -495,7 +495,7 @@ namespace AyaNova.Util
//
internal static async Task DeleteAttachmentsForObjectAsync(AyaType ayaType, long ayaId, AyContext ct)
{
- var deleteList = await ct.FileAttachment.Where(z => z.AttachToObjectId == ayaId && z.AttachToObjectType == ayaType).ToListAsync();
+ var deleteList = await ct.FileAttachment.Where(z => z.AttachToObjectId == ayaId && z.AttachToAType == ayaType).ToListAsync();
foreach (var d in deleteList)
{
await DeleteFileAttachmentAsync(d, ct);