From f222c9d4e2265cd2c724da92d862539ad859d69f Mon Sep 17 00:00:00 2001 From: John Cardinal Date: Thu, 1 Apr 2021 18:24:27 +0000 Subject: [PATCH] --- server/AyaNova/biz/WorkOrderBiz.cs | 174 ++++++++++++++++++++++++++--- server/AyaNova/resource/de.json | 3 +- server/AyaNova/resource/en.json | 31 ++--- server/AyaNova/resource/es.json | 3 +- server/AyaNova/resource/fr.json | 3 +- 5 files changed, 178 insertions(+), 36 deletions(-) diff --git a/server/AyaNova/biz/WorkOrderBiz.cs b/server/AyaNova/biz/WorkOrderBiz.cs index fd557228..8d67d43b 100644 --- a/server/AyaNova/biz/WorkOrderBiz.cs +++ b/server/AyaNova/biz/WorkOrderBiz.cs @@ -12,21 +12,11 @@ using System.Collections.Generic; namespace AyaNova.Biz { /* - ############### - MUST be able to update any section at any level independantly - Fetch must be able to get entire graph or from any level down or single header only as required - probably need a woheaderfetch route separately - - TODO: Routes then front end stuff can start and may god have mercy on my soul! ;) - - - - todo: Don't all *child items require a transaction to be passed for *any* crud op, i.e. including put and etc? - As they might be called from a parent transaction? - (wait until front end to decide this and do some testing etc grok it out) - - - */ + ############### + todo: Don't all *child items require a transaction to be passed for *any* crud op, i.e. including put and etc? + As they might be called from a parent transaction? + (wait until front end to decide this and do some testing etc grok it out) + */ internal class WorkOrderBiz : BizObject, IJobObject, ISearchAbleObject, IReportAbleObject, IExportAbleObject { @@ -173,6 +163,8 @@ namespace AyaNova.Biz return null; } + + putObject.Tags = TagBiz.NormalizeTags(putObject.Tags); putObject.CustomFields = JsonUtil.CompactJson(putObject.CustomFields); await WorkOrderValidateAsync(putObject, dbObject); @@ -350,6 +342,19 @@ namespace AyaNova.Biz //Check state if updatable right now + if (!isNew) + { + //Front end is coded to save the state first before any other updates if it has changed and it would not be + //a part of this header update so it's safe to check it here as it will be most up to date + var CurrentWoStatus = await GetCurrentWorkOrderStatusFromRelatedAsync(proposedObj.AyaType, proposedObj.Id); + if (CurrentWoStatus.Locked) + { + AddError(ApiErrorCode.VALIDATION_NOT_CHANGEABLE, "generalerror", await Translate("WorkOrderErrorLocked")); + return;//this is a completely disqualifying error + } + + } + /* @@ -1056,6 +1061,19 @@ namespace AyaNova.Biz AddError(ApiErrorCode.VALIDATION_INVALID_VALUE, "WorkOrderId"); } + //Check state if updatable right now + if (!isNew) + { + //Front end is coded to save the state first before any other updates if it has changed and it would not be + //a part of this header update so it's safe to check it here as it will be most up to date + var CurrentWoStatus = await GetCurrentWorkOrderStatusFromRelatedAsync(proposedObj.AyaType, proposedObj.Id); + if (CurrentWoStatus.Locked) + { + AddError(ApiErrorCode.VALIDATION_NOT_CHANGEABLE, "generalerror", await Translate("WorkOrderErrorLocked")); + return;//this is a completely disqualifying error + } + } + //Any form customizations to validate? var FormCustomization = await ct.FormCustom.AsNoTracking().SingleOrDefaultAsync(z => z.FormKey == AyaType.WorkOrderItem.ToString()); if (FormCustomization != null) @@ -1293,6 +1311,20 @@ namespace AyaNova.Biz else if (!await ItemExistsAsync(proposedObj.WorkOrderItemId)) AddError(ApiErrorCode.VALIDATION_INVALID_VALUE, "WorkOrderItemId"); + //Check state if updatable right now + if (!isNew) + { + //Front end is coded to save the state first before any other updates if it has changed and it would not be + //a part of this header update so it's safe to check it here as it will be most up to date + var CurrentWoStatus = await GetCurrentWorkOrderStatusFromRelatedAsync(proposedObj.AyaType, proposedObj.Id); + if (CurrentWoStatus.Locked) + { + AddError(ApiErrorCode.VALIDATION_NOT_CHANGEABLE, "generalerror", await Translate("WorkOrderErrorLocked")); + return;//this is a completely disqualifying error + } + + } + //Any form customizations to validate? var FormCustomization = await ct.FormCustom.AsNoTracking().SingleOrDefaultAsync(z => z.FormKey == AyaType.WorkOrderItemExpense.ToString()); if (FormCustomization != null) @@ -1530,6 +1562,17 @@ namespace AyaNova.Biz else if (!await ItemExistsAsync(proposedObj.WorkOrderItemId)) { AddError(ApiErrorCode.VALIDATION_INVALID_VALUE, "WorkOrderItemId"); + } + //Check state if updatable right now + if(!isNew){ + //Front end is coded to save the state first before any other updates if it has changed and it would not be + //a part of this header update so it's safe to check it here as it will be most up to date + var CurrentWoStatus = await GetCurrentWorkOrderStatusFromRelatedAsync(proposedObj.AyaType, proposedObj.Id); + if(CurrentWoStatus.Locked){ + AddError(ApiErrorCode.VALIDATION_NOT_CHANGEABLE, "generalerror", await Translate("WorkOrderErrorLocked")); + return;//this is a completely disqualifying error + } + } //Any form customizations to validate? @@ -1769,6 +1812,17 @@ namespace AyaNova.Biz else if (!await ItemExistsAsync(proposedObj.WorkOrderItemId)) { AddError(ApiErrorCode.VALIDATION_INVALID_VALUE, "WorkOrderItemId"); + } + //Check state if updatable right now + if(!isNew){ + //Front end is coded to save the state first before any other updates if it has changed and it would not be + //a part of this header update so it's safe to check it here as it will be most up to date + var CurrentWoStatus = await GetCurrentWorkOrderStatusFromRelatedAsync(proposedObj.AyaType, proposedObj.Id); + if(CurrentWoStatus.Locked){ + AddError(ApiErrorCode.VALIDATION_NOT_CHANGEABLE, "generalerror", await Translate("WorkOrderErrorLocked")); + return;//this is a completely disqualifying error + } + } //Any form customizations to validate? @@ -2020,6 +2074,17 @@ namespace AyaNova.Biz else if (!await ItemExistsAsync(proposedObj.WorkOrderItemId)) { AddError(ApiErrorCode.VALIDATION_INVALID_VALUE, "WorkOrderItemId"); + } + //Check state if updatable right now + if(!isNew){ + //Front end is coded to save the state first before any other updates if it has changed and it would not be + //a part of this header update so it's safe to check it here as it will be most up to date + var CurrentWoStatus = await GetCurrentWorkOrderStatusFromRelatedAsync(proposedObj.AyaType, proposedObj.Id); + if(CurrentWoStatus.Locked){ + AddError(ApiErrorCode.VALIDATION_NOT_CHANGEABLE, "generalerror", await Translate("WorkOrderErrorLocked")); + return;//this is a completely disqualifying error + } + } //Any form customizations to validate? @@ -2261,6 +2326,17 @@ namespace AyaNova.Biz else if (!await ItemExistsAsync(proposedObj.WorkOrderItemId)) { AddError(ApiErrorCode.VALIDATION_INVALID_VALUE, "WorkOrderItemId"); + } + //Check state if updatable right now + if(!isNew){ + //Front end is coded to save the state first before any other updates if it has changed and it would not be + //a part of this header update so it's safe to check it here as it will be most up to date + var CurrentWoStatus = await GetCurrentWorkOrderStatusFromRelatedAsync(proposedObj.AyaType, proposedObj.Id); + if(CurrentWoStatus.Locked){ + AddError(ApiErrorCode.VALIDATION_NOT_CHANGEABLE, "generalerror", await Translate("WorkOrderErrorLocked")); + return;//this is a completely disqualifying error + } + } //Any form customizations to validate? @@ -2476,6 +2552,17 @@ namespace AyaNova.Biz else if (!await ItemExistsAsync(proposedObj.WorkOrderItemId)) { AddError(ApiErrorCode.VALIDATION_INVALID_VALUE, "WorkOrderItemId"); + } + //Check state if updatable right now + if(!isNew){ + //Front end is coded to save the state first before any other updates if it has changed and it would not be + //a part of this header update so it's safe to check it here as it will be most up to date + var CurrentWoStatus = await GetCurrentWorkOrderStatusFromRelatedAsync(proposedObj.AyaType, proposedObj.Id); + if(CurrentWoStatus.Locked){ + AddError(ApiErrorCode.VALIDATION_NOT_CHANGEABLE, "generalerror", await Translate("WorkOrderErrorLocked")); + return;//this is a completely disqualifying error + } + } //Any form customizations to validate? @@ -2692,6 +2779,17 @@ namespace AyaNova.Biz else if (!await ItemExistsAsync(proposedObj.WorkOrderItemId)) { AddError(ApiErrorCode.VALIDATION_INVALID_VALUE, "WorkOrderItemId"); + } + //Check state if updatable right now + if(!isNew){ + //Front end is coded to save the state first before any other updates if it has changed and it would not be + //a part of this header update so it's safe to check it here as it will be most up to date + var CurrentWoStatus = await GetCurrentWorkOrderStatusFromRelatedAsync(proposedObj.AyaType, proposedObj.Id); + if(CurrentWoStatus.Locked){ + AddError(ApiErrorCode.VALIDATION_NOT_CHANGEABLE, "generalerror", await Translate("WorkOrderErrorLocked")); + return;//this is a completely disqualifying error + } + } //Any form customizations to validate? @@ -2932,6 +3030,17 @@ namespace AyaNova.Biz else if (!await ItemExistsAsync(proposedObj.WorkOrderItemId)) { AddError(ApiErrorCode.VALIDATION_INVALID_VALUE, "WorkOrderItemId"); + } + //Check state if updatable right now + if(!isNew){ + //Front end is coded to save the state first before any other updates if it has changed and it would not be + //a part of this header update so it's safe to check it here as it will be most up to date + var CurrentWoStatus = await GetCurrentWorkOrderStatusFromRelatedAsync(proposedObj.AyaType, proposedObj.Id); + if(CurrentWoStatus.Locked){ + AddError(ApiErrorCode.VALIDATION_NOT_CHANGEABLE, "generalerror", await Translate("WorkOrderErrorLocked")); + return;//this is a completely disqualifying error + } + } //Any form customizations to validate? @@ -3173,6 +3282,17 @@ namespace AyaNova.Biz else if (!await ItemExistsAsync(proposedObj.WorkOrderItemId)) { AddError(ApiErrorCode.VALIDATION_INVALID_VALUE, "WorkOrderItemId"); + } + //Check state if updatable right now + if(!isNew){ + //Front end is coded to save the state first before any other updates if it has changed and it would not be + //a part of this header update so it's safe to check it here as it will be most up to date + var CurrentWoStatus = await GetCurrentWorkOrderStatusFromRelatedAsync(proposedObj.AyaType, proposedObj.Id); + if(CurrentWoStatus.Locked){ + AddError(ApiErrorCode.VALIDATION_NOT_CHANGEABLE, "generalerror", await Translate("WorkOrderErrorLocked")); + return;//this is a completely disqualifying error + } + } //Any form customizations to validate? @@ -3414,6 +3534,17 @@ namespace AyaNova.Biz else if (!await ItemExistsAsync(proposedObj.WorkOrderItemId)) { AddError(ApiErrorCode.VALIDATION_INVALID_VALUE, "WorkOrderItemId"); + } + //Check state if updatable right now + if(!isNew){ + //Front end is coded to save the state first before any other updates if it has changed and it would not be + //a part of this header update so it's safe to check it here as it will be most up to date + var CurrentWoStatus = await GetCurrentWorkOrderStatusFromRelatedAsync(proposedObj.AyaType, proposedObj.Id); + if(CurrentWoStatus.Locked){ + AddError(ApiErrorCode.VALIDATION_NOT_CHANGEABLE, "generalerror", await Translate("WorkOrderErrorLocked")); + return;//this is a completely disqualifying error + } + } //Any form customizations to validate? @@ -3606,12 +3737,17 @@ namespace AyaNova.Biz //////////////////////////////////////////////////////////////////////////////////////////////// - //GET UPDATEABLE STATUS FOR WORKORDER FROM DESCENDANT + //GET CURRENT STATUS FOR WORKORDER FROM RELATIVE // + internal async Task GetCurrentWorkOrderStatusFromRelatedAsync(AyaType ayaType, long id) + { + //instantiated method to save adding the context + return await GetCurrentWorkOrderStatusFromRelatedAsync(ayaType, id, ct); + } internal static async Task GetCurrentWorkOrderStatusFromRelatedAsync(AyaType ayaType, long id, AyContext ct) { + //static method long WoId = await GetWorkOrderIdFromRelativeAsync(ayaType, id, ct); - return await ct.WorkOrderState.AsNoTracking() .Include(z => z.WorkOrderStatus) .Where(z => z.WorkOrderId == WoId) @@ -3619,8 +3755,10 @@ namespace AyaNova.Biz .Select(z => z.WorkOrderStatus) .Take(1) .FirstOrDefaultAsync(); - } + + + #endregion utility diff --git a/server/AyaNova/resource/de.json b/server/AyaNova/resource/de.json index 22b9d1b8..b1cc3c3a 100644 --- a/server/AyaNova/resource/de.json +++ b/server/AyaNova/resource/de.json @@ -2184,5 +2184,6 @@ "NextPONumber":"Nächste Bestellung", "NextQuoteNumber":"Nächste Angebotsnummer", "NextWorkorderNumber":"Nächster Arbeitsauftrag", - "NextPMNumber":"Nächste vorbeugende Wartung" + "NextPMNumber":"Nächste vorbeugende Wartung", + "WorkOrderErrorLocked": "Der Arbeitsauftrag ist derzeit gesperrt und kann nicht geändert werden" } \ No newline at end of file diff --git a/server/AyaNova/resource/en.json b/server/AyaNova/resource/en.json index 0c124196..8882b34f 100644 --- a/server/AyaNova/resource/en.json +++ b/server/AyaNova/resource/en.json @@ -1625,8 +1625,8 @@ "WorkOrderStatusColor": "Color", "WorkOrderStatusSelectRoles": "Who can select", "WorkOrderStatusRemoveRoles": "Who can remove", - "WorkOrderStatusCompleted":"Is a completed status", - "WorkOrderStatusLocked":"Is a locking status", + "WorkOrderStatusCompleted": "Is a completed status", + "WorkOrderStatusLocked": "Is a locking status", "WorkOrderStatusUnderlined": "Underlined", "WorkOrderSummaryTemplate": "WorkOrder Item Summary Template", "WorkOrderSummaryWorkOrderItem": "WorkOrder Item Info To Display", @@ -2170,19 +2170,20 @@ "SaveACopy": "Save a copy", "ConfirmUpdatePartCost": "Update part cost from received cost?", "AlertNotes": "Alert notes", - "AuthTwoFactor":"Two-Factor Authentication", + "AuthTwoFactor": "Two-Factor Authentication", "AuthConnectAppTitle": "Connect your app", "AuthConnectAppSubTitle": "Using an authenticator app such as Google Authenticator, Duo, Microsoft Authenticator, Authy etc, scan the QR code. It will display a 6 digit pass code which you need to enter below.", - "AuthConnectAppManualEntry":"Having trouble scanning the code? Enter the following manually into your authenticator app:", - "AuthEnterPin":"Enter 6-digit code", - "AuthPinInvalid":"Code not valid", - "AuthConnectCompleted":"Two-Factor authentication is now enabled", - "AuthDisableTwoFactor":"Disable Two-Factor authentication", - "AuthTwoFactorDisabled":"Two-Factor authentication is now disabled", - "AuthVerifyCode":"Verify code", - "GlobalNextSeeds":"Set next seed number", - "NextPONumber":"Next purchase order", - "NextQuoteNumber":"Next quote", - "NextWorkorderNumber":"Next work order", - "NextPMNumber":"Next preventive maintenance" + "AuthConnectAppManualEntry": "Having trouble scanning the code? Enter the following manually into your authenticator app:", + "AuthEnterPin": "Enter 6-digit code", + "AuthPinInvalid": "Code not valid", + "AuthConnectCompleted": "Two-Factor authentication is now enabled", + "AuthDisableTwoFactor": "Disable Two-Factor authentication", + "AuthTwoFactorDisabled": "Two-Factor authentication is now disabled", + "AuthVerifyCode": "Verify code", + "GlobalNextSeeds": "Set next seed number", + "NextPONumber": "Next purchase order", + "NextQuoteNumber": "Next quote", + "NextWorkorderNumber": "Next work order", + "NextPMNumber": "Next preventive maintenance", + "WorkOrderErrorLocked": "Work order is set to a locked status and can't be changed" } \ No newline at end of file diff --git a/server/AyaNova/resource/es.json b/server/AyaNova/resource/es.json index 50d6f298..6e47369b 100644 --- a/server/AyaNova/resource/es.json +++ b/server/AyaNova/resource/es.json @@ -2184,5 +2184,6 @@ "NextPONumber":"Siguiente orden de compra", "NextQuoteNumber":"Próxima cotización", "NextWorkorderNumber":"Siguiente orden de trabajo", - "NextPMNumber":"Siguiente mantenimiento preventivo" + "NextPMNumber":"Siguiente mantenimiento preventivo", + "WorkOrderErrorLocked": "La orden de trabajo está actualmente configurada en un estado bloqueado y no se puede cambiar" } \ No newline at end of file diff --git a/server/AyaNova/resource/fr.json b/server/AyaNova/resource/fr.json index 03216b93..4e7e8cf3 100644 --- a/server/AyaNova/resource/fr.json +++ b/server/AyaNova/resource/fr.json @@ -2184,5 +2184,6 @@ "NextPONumber":"Prochaine commande d'achat", "NextQuoteNumber":"Numéro de devis suivant", "NextWorkorderNumber":"Bon de travail suivant", - "NextPMNumber":"Prochaine maintenance préventive" + "NextPMNumber":"Prochaine maintenance préventive", + "WorkOrderErrorLocked": "Le bon de travail est actuellement défini sur un statut verrouillé et ne peut pas être modifié" } \ No newline at end of file