{"Name":"Labor Billing & Hours Grouped By Technician","Active":true,"Notes":"Custom Prepare to group by the technician, and get running totals of NC, Billable and Actual for grouping AND for all wo records in this report","Roles":51182,"AType":37,"IncludeWoItemDescendants":false,"Template":"\n\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n {{#each ayReportData}}\n \n \n \n \n \n \n {{#each items}}\n \n \n \n \n \n \n \n \n \n \n \n \n {{/each}}\n \n \n \n \n \n \n \n \n \n \n \n \n \n {{/each}}\n \n
{{ayT \"WorkOrder\"}}{{ayT \"WorkOrderItemLaborServiceStartDate\"}} / {{ayT \"WorkOrderItemLaborServiceStopDate\"}} {{ayT \"WorkOrderItemLaborServiceRateID\"}}{{ayT \"WorkOrderItemLaborRateCharge\"}}Actual Total Quantity{{ayT \"WorkOrderItemLaborNoChargeQuantity\"}}{{ayT \"WorkOrderItemLaborServiceRateQuantity\"}}{{ayT \"NetValue\"}}
{{ayT 'WorkOrderItemLabors'}} for {{group}}# of labor items: {{count}}
 {{Serial}}{{ayDateTime ServiceStartDate}} to {{ayDateTime ServiceStopDate}}{{ServiceRateViz}}{{ayCurrency PriceViz}} {{UnitOfMeasureViz}}{{diffHours}}{{NoChargeQuantity}}{{ServiceRateQuantity}}{{ayCurrency NetViz}}
 
Total {{ayT \"WorkOrderItemLaborServiceRateQuantity\"}} + {{ayT \"WorkOrderItemLaborNoChargeQuantity\" }} = {{EachGroupWOLaborsNCQtyplusBillableQty}} for {{group}}{{EachGroupWOActualHoursQty}}{{EachGroupWOLaborsNCQty}}{{EachGroupWOLaborsBillableQty}}{{ayCurrency EachGroupWOLaborsNetViz}}
 
\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
 Total {{ayT 'WorkOrderItemLabors'}} recordsTotal Combined {{ayT \"WorkOrderItemLaborServiceRateQuantity\"}} & {{ayT \"WorkOrderItemLaborServiceRateQuantity\"}}Total {{ayT \"WorkOrderItemLaborNoChargeQuantity\"}}Total {{ayT \"WorkOrderItemLaborServiceRateQuantity\"}}Total {{ayT \"NetValue\"}}
 {{AllWOLaborsCount}}{{AllWOLaborsNCQtyplusBillableQty}}{{AllWOLaborsNCQty}}{{AllWOLaborsBillableQty}}{{ayCurrency AllWOLaborsNetViz}}
\n
\n\n\n","Style":".singlePage\r\n{\r\npage-break-after: always;\r\n\r\n}\r\nbody {\r\n font-family: 'Helvetica', 'Helvetica Neue', Arial, sans-serif; \r\n}\r\n\r\n.reporttitle { \r\n margin-bottom: 20pt; \r\n font-weight: bold; \r\n font-size: 14pt; \r\n color: #9e9e9e;\r\n text-align: left;\r\n} \r\n\r\ntable { \r\n border-collapse: collapse;\r\n white-space: pre-wrap;\r\n width: 100%; \r\n table-layout: fixed;\r\n }\r\n\r\nth {\r\n height: 30px;\r\n font-size: 10pt; \r\n color: #9e9e9e;\r\n}\r\n\r\ntfoot th{\r\n border-top: solid 1pt #9e9e9e;\r\n height: 50px;\r\n text-align: center;\r\n}\r\n\r\ntbody td {\r\n padding: 10px;\r\n word-wrap: break-word;\r\n font-size: 9pt;\r\n text-align: center;\r\n}\r\n\r\ntbody tr:nth-child(even) {\r\n background-color: #f8f8f8; /* MUST checkmark Print background in PDF Options for this to show */\r\n}\r\n\r\ntfoot td{\r\n font-size: 10pt;\r\n text-align: center;\r\n }\r\n\r\n.rightlean {\r\n text-align: right;\r\n}\r\n.leftlean {\r\n text-align: left;\r\n}\r\n.centerlean {\r\n text-align: center;\r\n}\r\n\r\n\r\n.fontgreen {\r\n color: green;\r\n}\r\n.fontblue {\r\n color: blue;\r\n}\r\n.fontred {\r\n color:red;\r\n font-weight: bold;\r\n}\r\n.fontpurple {\r\n color: purple;\r\n}\r\n","JsPrerender":"async function ayPrepareData(reportData) {\n\nawait ayGetTranslations([\"Total\", \"WorkOrder\", \"WorkOrderList\", \"WorkOrderItemLabors\", \"WorkOrderItemLaborUserID\", \"WorkOrderItemLaborServiceRateID\", \"WorkOrderItemLaborRateCharge\", \"WorkOrderItemLaborServiceRateQuantity\", \"WorkOrderItemLaborServiceDetails\", \"WorkOrderItemLaborNoChargeQuantity\", \"WorkOrderItemLaborServiceStartDate\", \"WorkOrderItemLaborServiceStopDate\", \"NetValue\"]);\n\n\n\t//below is the code to group by the technician - the UserViz\n\tlet ret = [];\n //iterate workorders -> items -> workorder item labors\n reportData.ayReportData.forEach(workorder => {\n workorder.Items.forEach(workorderitem => {\n workorderitem.Labors.forEach(labor => {\n //new shape of data required for report\n let record = {\n Serial: workorder.Serial,\n ServiceRateViz: labor.ServiceRateViz,\n PriceViz: labor.PriceViz,\n UnitOfMeasureViz: labor.UnitOfMeasureViz,\n ServiceStartDate: labor.ServiceStartDate,\n ServiceStopDate: labor.ServiceStopDate,\n NoChargeQuantity: labor.NoChargeQuantity,\n ServiceRateQuantity: labor.ServiceRateQuantity,\n\t\t\t\t\tServiceDetails: labor.ServiceDetails,\n NetViz: labor.NetViz\n };\n\n //Find or create group and insert this record \n let groupObject = ret.find(z => z.group == labor.UserViz);\n if (groupObject != undefined) {\n //there is already a matching group in the return array so just push this record into it\n groupObject.items.push(record);\n //update the count for this group's items\n groupObject.count++;\n } else {\n //No group yet, so start a new one in the ret array and push this record into it\n ret.push({ group: labor.UserViz, items: [record], count: 1 });\n }\n\n })\n })\n });\n\n //replace the ayReportData with our new shaped format of data\n reportData.ayReportData = ret;\n\n \n//need to now edit below to get running totals of THE DATA returned above - can't reference items as not in the returned data\n\n\t//below declares variables for running total for ALL\n\treportData.AllWOLaborsNCQty = 0; \n\treportData.AllWOLaborsBillableQty = 0;\n\treportData.AllWOLaborsNCQtyplusBillableQty = 0; \n\treportData.AllWOLaborsNetViz = 0;\n\t\n\treportData.AllWOLaborsCount = 0;\n\n \t\t\n\n\t\t\t\tfor (EachGroup of reportData.ayReportData) \n\t\t\t\t{\n\t\t\t\t//below declares a key on the entire grouping to hold running totals for each labor record for each Item for EachWO for each \"items\" \n\t\t\t\tEachGroup.EachGroupWOLaborsNCQty = 0;\n\t\t\t\tEachGroup.EachGroupWOLaborsBillableQty = 0;\n\t\t\t\tEachGroup.EachGroupWOLaborsNCQtyplusBillableQty = 0;\n\t\t\t\tEachGroup.EachGroupWOLaborsNetViz = 0;\n\t\t\t\tEachGroup.EachGroupWOActualHoursQty = 0;\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\t for (groupitem of EachGroup.items) \n\t\t\t\t\t\t \t{\n\t\t\t\t\t\t\t\t\t\treportData.AllWOLaborsCount += 1;\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\tif (groupitem.ServiceStartDate != null && groupitem.ServiceStopDate != null) \n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\tdateTime1 = new Date (groupitem.ServiceStopDate);\n\t\t\t\t\t\t\t\t\t\t\tdateTime2 = new Date (groupitem.ServiceStartDate);\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\tdiffMillis = (dateTime1.getTime() - dateTime2.getTime()); \n\t\t\t\t\t\t\t\t\t\t\tgroupitem.diffHours = (diffMillis/3600) / 1000;\n\n\t\t\t\t\t\t\t\t\t\t\tEachGroup.EachGroupWOActualHoursQty += groupitem.diffHours;\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tif (groupitem.NoChargeQuantity != null) \n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\tEachGroup.EachGroupWOLaborsNCQty += groupitem.NoChargeQuantity;\t\n\t\t\t\t\t\t\t\t\t\t\t\t\tEachGroup.EachGroupWOLaborsNCQtyplusBillableQty += groupitem.NoChargeQuantity;\t\n\t\t\t\t\t\t\t\t\t\t\t\t\treportData.AllWOLaborsNCQty\t+= groupitem.NoChargeQuantity;\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\treportData.AllWOLaborsNCQtyplusBillableQty += groupitem.NoChargeQuantity;\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tif (groupitem.ServiceRateQuantity != null) \n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\tEachGroup.EachGroupWOLaborsBillableQty += groupitem.ServiceRateQuantity; \n\t\t\t\t\t\t\t\t\t\t\t\t\tEachGroup.EachGroupWOLaborsNCQtyplusBillableQty += groupitem.ServiceRateQuantity;\n\t\t\t\t\t\t\t\t\t\t\t\t\treportData.AllWOLaborsBillableQty += groupitem.ServiceRateQuantity; \n\t\t\t\t\t\t\t\t\t\t\t\t\treportData.AllWOLaborsNCQtyplusBillableQty += groupitem.ServiceRateQuantity; \n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tif (groupitem.NetViz != null) \n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\tEachGroup.EachGroupWOLaborsNetViz += groupitem.NetViz;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\treportData.AllWOLaborsNetViz += groupitem.NetViz; //this is the actual adding to running total for all\n\t\t\t\t\t\t\t\t\t\t\t\t}\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t \t\t\n\t\t\t\t\t\t \t}\n\t\t\t\t}\n\t\t\t\n\n\t//return the data into the pipeline to send to the report template \n\treturn reportData;\n}\n\n\n\n","JsHelpers":"","RenderType":0,"HeaderTemplate":"","FooterTemplate":"    Printed date:    \nPage  of         ","DisplayHeaderFooter":true,"PaperFormat":10,"Landscape":true,"MarginOptionsBottom":"20mm","MarginOptionsLeft":"20mm","MarginOptionsRight":"15mm","MarginOptionsTop":"15mm","PageRanges":null,"PreferCSSPageSize":false,"PrintBackground":true,"Scale":1.00000}