From 18c9d2e7d4568ad072fe56a2c5943fcaef88ba0f Mon Sep 17 00:00:00 2001 From: John Cardinal Date: Thu, 30 Sep 2021 20:24:48 +0000 Subject: [PATCH] case 3994 --- .../ayanova/docs/ay-start-changes-from-v7.md | 4 ++ server/AyaNova/DataList/CustomerDataList.cs | 36 +++++++++++++- server/AyaNova/DataList/UnitDataList.cs | 49 ++++++++++++++++--- server/AyaNova/biz/CustomerBiz.cs | 34 +++++++++++++ server/AyaNova/biz/UnitBiz.cs | 41 +++++++++++++++- server/AyaNova/models/Customer.cs | 5 +- server/AyaNova/models/Unit.cs | 6 +++ server/AyaNova/resource/de.json | 4 +- server/AyaNova/resource/en.json | 4 +- server/AyaNova/resource/es.json | 4 +- server/AyaNova/resource/fr.json | 4 +- 11 files changed, 175 insertions(+), 16 deletions(-) diff --git a/docs/8.0/ayanova/docs/ay-start-changes-from-v7.md b/docs/8.0/ayanova/docs/ay-start-changes-from-v7.md index e1b694bb..48d4d142 100644 --- a/docs/8.0/ayanova/docs/ay-start-changes-from-v7.md +++ b/docs/8.0/ayanova/docs/ay-start-changes-from-v7.md @@ -127,6 +127,10 @@ Tasks have been changed to a collection stored *with* the work order rather than Pricing and costs are now clearly displayed on the work order in a consistent manner between all billable items that have prices. List price and final price are both shown so that it's clear that a contract or manual override have affected the final price. Most non management roles will not see costs or prices by default. Most prices (except for Parts which tend to have volatile pricing) are not stored with the work order but instead calculated on the fly when a work order is opened / printed. This is part of the decoupling process that allows for easily changing the Contract or Customer on an existing Work order. This means that similar to v7 some items like taxes and rates cannot be changed once they have been used on a work order however Parts are an exception as the pricing is considered more volatile so part prices are "snapshotted" on being added to a work order. +#### Customer and Unit data list "Last completed... " columns + +In v7 the Clients grid and the Units grid show the "Last closed service workorder" and "Last closed service date" columns. +In v8 since Closed is now a propert of the work order status the Customer and Unit data tables will show "Last completed work order" as "Last completed service date" instead. ### Quotes diff --git a/server/AyaNova/DataList/CustomerDataList.cs b/server/AyaNova/DataList/CustomerDataList.cs index 875f6a8a..558bd408 100644 --- a/server/AyaNova/DataList/CustomerDataList.cs +++ b/server/AyaNova/DataList/CustomerDataList.cs @@ -9,8 +9,21 @@ namespace AyaNova.DataList { public CustomerDataList() { - DefaultListAType = AyaType.Customer; - SQLFrom = "from acustomer left join aheadoffice on (acustomer.headofficeid=aheadoffice.id) left join acontract on (acustomer.contractid=acontract.id)"; + DefaultListAType = AyaType.Customer; + SQLFrom = @"FROM ACUSTOMER +LEFT JOIN AHEADOFFICE ON (ACUSTOMER.HEADOFFICEID = AHEADOFFICE.ID) +LEFT JOIN ACONTRACT ON (ACUSTOMER.CONTRACTID = ACONTRACT.ID) +LEFT JOIN LATERAL + (SELECT serial AS LASTWORKORDERSERIAL, + SERVICEDATE AS LASTWORKORDERSERVICEDATE, + AWORKORDER.ID AS LASTWORKORDERID + FROM AWORKORDER + LEFT JOIN AWORKORDERSTATUS ON AWORKORDER.LASTSTATUSID = AWORKORDERSTATUS.ID + WHERE AWORKORDERSTATUS.COMPLETED = TRUE + AND AWORKORDER.CUSTOMERID = ACUSTOMER.ID + ORDER BY AWORKORDER.ID DESC + LIMIT 1) AS LWO ON TRUE"; + var RoleSet = BizRoles.GetRoleSet(DefaultListAType); AllowedRoles = RoleSet.ReadFullRecord | RoleSet.Change; DefaultColumns = new List() { "customername", "customerphone1", "customeremail", "customerheadoffice" }; @@ -18,6 +31,25 @@ namespace AyaNova.DataList FieldDefinitions = new List(); + + FieldDefinitions.Add(new DataListFieldDefinition + { + FieldKey = "LastCompletedWorkOrder", + TKey = "LastCompletedWorkOrder", + AType = (int)AyaType.WorkOrder, + UiFieldDataType = (int)UiFieldDataType.Integer, + SqlIdColumnName = "lwo.LASTWORKORDERID", + SqlValueColumnName = "lwo.lastworkorderserial" + }); + + FieldDefinitions.Add(new DataListFieldDefinition + { + TKey = "LastCompletedWorkOrderServiceDate", + FieldKey = "LastCompletedWorkOrderServiceDate", + UiFieldDataType = (int)UiFieldDataType.DateTime, + SqlValueColumnName = "lwo.lastworkorderservicedate" + }); + FieldDefinitions.Add(new DataListFieldDefinition { TKey = "CustomerName", diff --git a/server/AyaNova/DataList/UnitDataList.cs b/server/AyaNova/DataList/UnitDataList.cs index 7b6e0323..73999480 100644 --- a/server/AyaNova/DataList/UnitDataList.cs +++ b/server/AyaNova/DataList/UnitDataList.cs @@ -9,21 +9,54 @@ namespace AyaNova.DataList { public UnitDataList() { - DefaultListAType = AyaType.Unit; - SQLFrom = "from aunit as amainunit " - + "left join acustomer on (amainunit.customerid=acustomer.id) " - + "left join aunit as aparentunit on (amainunit.parentunitid=aparentunit.id) " - + "left join aunitmodel on (amainunit.unitmodelid=aunitmodel.id) " - + "left join avendor on (amainunit.purchasedfromvendorid=avendor.id) " - + "left join aunit as areplacedbyunit on (amainunit.replacedbyunitid=areplacedbyunit.id) " - + "left join acontract on (amainunit.contractid=acontract.id)"; + DefaultListAType = AyaType.Unit; + SQLFrom = @"FROM AUNIT AS AMAINUNIT +LEFT JOIN ACUSTOMER ON (AMAINUNIT.CUSTOMERID = ACUSTOMER.ID) +LEFT JOIN AUNIT AS APARENTUNIT ON (AMAINUNIT.PARENTUNITID = APARENTUNIT.ID) +LEFT JOIN AUNITMODEL ON (AMAINUNIT.UNITMODELID = AUNITMODEL.ID) +LEFT JOIN AVENDOR ON (AMAINUNIT.PURCHASEDFROMVENDORID = AVENDOR.ID) +LEFT JOIN AUNIT AS AREPLACEDBYUNIT ON (AMAINUNIT.REPLACEDBYUNITID = AREPLACEDBYUNIT.ID) +LEFT JOIN ACONTRACT ON (AMAINUNIT.CONTRACTID = ACONTRACT.ID) +LEFT JOIN LATERAL + (SELECT serial AS LASTWORKORDERSERIAL, + SERVICEDATE AS LASTWORKORDERSERVICEDATE, + AWORKORDERITEMUNIT.ID AS LASTWORKORDERITEMUNITID + FROM AWORKORDER + LEFT JOIN AWORKORDERITEM ON AWORKORDER.ID = AWORKORDERITEM.WORKORDERID + LEFT JOIN AWORKORDERSTATUS ON AWORKORDER.LASTSTATUSID = AWORKORDERSTATUS.ID + LEFT JOIN AWORKORDERITEMUNIT ON AWORKORDERITEM.ID = AWORKORDERITEMUNIT.WORKORDERITEMID + WHERE AWORKORDERITEMUNIT.ID = AMAINUNIT.ID + AND AWORKORDERSTATUS.COMPLETED = TRUE + ORDER BY AWORKORDER.ID DESC + LIMIT 1) AS LWO ON TRUE"; + var RoleSet = BizRoles.GetRoleSet(DefaultListAType); AllowedRoles = RoleSet.ReadFullRecord | RoleSet.Change; DefaultColumns = new List() { "UnitSerial", "UnitModel", "Customer", "Active" }; DefaultSortBy = new Dictionary() { { "UnitSerial", "+" } }; FieldDefinitions = new List(); + + FieldDefinitions.Add(new DataListFieldDefinition + { + FieldKey = "LastCompletedWorkOrder", + TKey = "LastCompletedWorkOrder", + AType = (int)AyaType.WorkOrderItemUnit, + UiFieldDataType = (int)UiFieldDataType.Integer, + SqlIdColumnName = "lwo.lastworkorderitemunitid", + SqlValueColumnName = "lwo.lastworkorderserial" + }); + + FieldDefinitions.Add(new DataListFieldDefinition + { + TKey = "LastCompletedWorkOrderServiceDate", + FieldKey = "LastCompletedWorkOrderServiceDate", + UiFieldDataType = (int)UiFieldDataType.DateTime, + SqlValueColumnName = "lwo.lastworkorderservicedate" + }); + + FieldDefinitions.Add(new DataListFieldDefinition { TKey = "UnitSerial", diff --git a/server/AyaNova/biz/CustomerBiz.cs b/server/AyaNova/biz/CustomerBiz.cs index 1614fbf1..17d71eaa 100644 --- a/server/AyaNova/biz/CustomerBiz.cs +++ b/server/AyaNova/biz/CustomerBiz.cs @@ -373,6 +373,40 @@ namespace AyaNova.Biz o.HeadOfficeViz = await ct.HeadOffice.AsNoTracking().Where(x => x.Id == o.HeadOfficeId).Select(x => x.Name).FirstOrDefaultAsync(); if (o.ContractId != null) o.ContractViz = await ct.Contract.AsNoTracking().Where(x => x.Id == o.ContractId).Select(x => x.Name).FirstOrDefaultAsync(); + + + /* + last completed work order stuff, way to complex to fetch via EF Core so dropping to raw sql + SELECT serial AS LASTWORKORDERSERIAL, + SERVICEDATE AS LASTWORKORDERSERVICEDATE, + AWORKORDER.ID AS LASTWORKORDERID + FROM AWORKORDER + LEFT JOIN AWORKORDERSTATUS ON AWORKORDER.LASTSTATUSID = AWORKORDERSTATUS.ID + WHERE AWORKORDERSTATUS.COMPLETED = TRUE + AND AWORKORDER.CUSTOMERID = ACUSTOMER.ID + ORDER BY AWORKORDER.ID DESC + LIMIT 1 + */ + using (var command = ct.Database.GetDbConnection().CreateCommand()) + { + await ct.Database.OpenConnectionAsync(); + command.CommandText = @$"SELECT serial AS LASTWORKORDERSERIAL, + SERVICEDATE AS LASTWORKORDERSERVICEDATE + FROM AWORKORDER + LEFT JOIN AWORKORDERSTATUS ON AWORKORDER.LASTSTATUSID = AWORKORDERSTATUS.ID + WHERE AWORKORDERSTATUS.COMPLETED = TRUE + AND AWORKORDER.CUSTOMERID = {o.Id} + ORDER BY AWORKORDER.ID DESC + LIMIT 1"; + using (var dr = await command.ExecuteReaderAsync()) + if (await dr.ReadAsync()) + { + o.LastCompletedWorkOrderViz = dr.GetInt64(0); + o.LastCompletedServiceDateViz = dr.GetDateTime(1); + } + + await ct.Database.CloseConnectionAsync(); + } } diff --git a/server/AyaNova/biz/UnitBiz.cs b/server/AyaNova/biz/UnitBiz.cs index 27e96d7d..8ce84bd1 100644 --- a/server/AyaNova/biz/UnitBiz.cs +++ b/server/AyaNova/biz/UnitBiz.cs @@ -308,6 +308,45 @@ namespace AyaNova.Biz } } + + /* + last completed work order stuff, way to complex to fetch via EF Core so dropping to raw sql + SELECT serial AS LASTWORKORDERSERIAL, + SERVICEDATE AS LASTWORKORDERSERVICEDATE, + AWORKORDERITEMUNIT.UNITID AS LASTWORKORDERUNITID, + AWORKORDERITEMUNIT.ID AS LASTWORKORDERITEMUNITID + FROM AWORKORDER + LEFT JOIN AWORKORDERITEM ON AWORKORDER.ID = AWORKORDERITEM.WORKORDERID + LEFT JOIN AWORKORDERSTATUS ON AWORKORDER.LASTSTATUSID = AWORKORDERSTATUS.ID + LEFT JOIN AWORKORDERITEMUNIT ON AWORKORDERITEM.ID = AWORKORDERITEMUNIT.WORKORDERITEMID + WHERE AWORKORDERITEMUNIT.ID = AMAINUNIT.ID + AND AWORKORDERSTATUS.COMPLETED = TRUE + ORDER BY AWORKORDER.ID DESC + LIMIT 1 + */ + using (var command = ct.Database.GetDbConnection().CreateCommand()) + { + await ct.Database.OpenConnectionAsync(); + command.CommandText = @$"SELECT serial AS LASTWORKORDERSERIAL, + SERVICEDATE AS LASTWORKORDERSERVICEDATE + FROM AWORKORDER + LEFT JOIN AWORKORDERITEM ON AWORKORDER.ID = AWORKORDERITEM.WORKORDERID + LEFT JOIN AWORKORDERSTATUS ON AWORKORDER.LASTSTATUSID = AWORKORDERSTATUS.ID + LEFT JOIN AWORKORDERITEMUNIT ON AWORKORDERITEM.ID = AWORKORDERITEMUNIT.WORKORDERITEMID + WHERE AWORKORDERITEMUNIT.ID = {o.Id} + AND AWORKORDERSTATUS.COMPLETED = TRUE + ORDER BY AWORKORDER.ID DESC + LIMIT 1"; + using (var dr = await command.ExecuteReaderAsync()) + if (await dr.ReadAsync()) + { + o.LastCompletedWorkOrderViz = dr.GetInt64(0); + o.LastCompletedServiceDateViz = dr.GetDateTime(1); + } + + await ct.Database.CloseConnectionAsync(); + } + } //////////////////////////////////////////////////////////////////////////////////////////////// @@ -558,7 +597,7 @@ namespace AyaNova.Biz } } }//Contract expiry event - + } diff --git a/server/AyaNova/models/Customer.cs b/server/AyaNova/models/Customer.cs index 1b9b4291..58d3f308 100644 --- a/server/AyaNova/models/Customer.cs +++ b/server/AyaNova/models/Customer.cs @@ -39,7 +39,10 @@ namespace AyaNova.Models [NotMapped] public string ContractViz { get; set; } public DateTime? ContractExpires { get; set; } - //public long? DefaultServiceTemplateId { get; set; } + [NotMapped] + public long? LastCompletedWorkOrderViz { get; set; } + [NotMapped] + public DateTime? LastCompletedServiceDateViz { get; set; } public string Phone1 { get; set; } public string Phone2 { get; set; } public string Phone3 { get; set; } diff --git a/server/AyaNova/models/Unit.cs b/server/AyaNova/models/Unit.cs index 2bfa86d2..33469818 100644 --- a/server/AyaNova/models/Unit.cs +++ b/server/AyaNova/models/Unit.cs @@ -58,6 +58,12 @@ namespace AyaNova.Models public long LastMeterViz { get; set; } [NotMapped] public DateTime? LastMeterDateViz { get; set; } + + [NotMapped] + public long? LastCompletedWorkOrderViz { get; set; } + [NotMapped] + public DateTime? LastCompletedServiceDateViz { get; set; } + [NotMapped] public string LastMeterNotesViz { get; set; } public bool LifeTimeWarranty { get; set; } diff --git a/server/AyaNova/resource/de.json b/server/AyaNova/resource/de.json index e8eaa97b..4a38d14c 100644 --- a/server/AyaNova/resource/de.json +++ b/server/AyaNova/resource/de.json @@ -2288,5 +2288,7 @@ "ScheduleWOColorFrom":"Farbquelle für Arbeitsauftrag", "NoColor":"Keine Farbe", "ScheduleOptions":"Zeitplaneinstellungen", - "ScheduleShowTypes":"Elemente zum Anzeigen" + "ScheduleShowTypes":"Elemente zum Anzeigen", + "LastCompletedWorkOrder":"Letzter abgeschlossener Arbeitsauftrag", + "LastCompletedWorkOrderServiceDate":"Letzter abgeschlossener Servicetermin" } \ No newline at end of file diff --git a/server/AyaNova/resource/en.json b/server/AyaNova/resource/en.json index a764d83a..d6e2d2fe 100644 --- a/server/AyaNova/resource/en.json +++ b/server/AyaNova/resource/en.json @@ -2288,7 +2288,9 @@ "ScheduleWOColorFrom":"Work order color source", "NoColor":"No color", "ScheduleOptions":"Schedule settings", - "ScheduleShowTypes":"Show" + "ScheduleShowTypes":"Show", + "LastCompletedWorkOrder":"Last completed work order", + "LastCompletedWorkOrderServiceDate":"Last completed service date" diff --git a/server/AyaNova/resource/es.json b/server/AyaNova/resource/es.json index 5b2d7c7b..78c661d5 100644 --- a/server/AyaNova/resource/es.json +++ b/server/AyaNova/resource/es.json @@ -2288,5 +2288,7 @@ "ScheduleWOColorFrom":"Fuente de color de la orden de trabajo", "NoColor":"Sin color", "ScheduleOptions":"Configuración de programación", - "ScheduleShowTypes":"Elementos para mostrar" + "ScheduleShowTypes":"Elementos para mostrar", + "LastCompletedWorkOrder":"Última orden de trabajo completada", + "LastCompletedWorkOrderServiceDate":"Fecha del último servicio completado" } \ No newline at end of file diff --git a/server/AyaNova/resource/fr.json b/server/AyaNova/resource/fr.json index 8374484f..07f29a63 100644 --- a/server/AyaNova/resource/fr.json +++ b/server/AyaNova/resource/fr.json @@ -2288,5 +2288,7 @@ "ScheduleWOColorFrom":"Source de couleur de l'ordre de travail", "NoColor":"Sans couleur", "ScheduleOptions":"Paramètres de planification", - "ScheduleShowTypes":"Éléments à afficher" + "ScheduleShowTypes":"Éléments à afficher", + "LastCompletedWorkOrder":"Dernier bon de travail terminé", + "LastCompletedWorkOrderServiceDate":"Date du dernier service terminé" } \ No newline at end of file