From ab0c648869cc11c63647217e1cb6d8a42311c3da Mon Sep 17 00:00:00 2001 From: John Cardinal Date: Wed, 14 Jul 2021 17:44:14 +0000 Subject: [PATCH] --- docs/8.0/ayanova/docs/svc-workorders.md | 2 +- server/AyaNova/biz/WorkOrderBiz.cs | 140 +++++++++++++----------- 2 files changed, 77 insertions(+), 65 deletions(-) diff --git a/docs/8.0/ayanova/docs/svc-workorders.md b/docs/8.0/ayanova/docs/svc-workorders.md index 4ac8959e..52853e30 100644 --- a/docs/8.0/ayanova/docs/svc-workorders.md +++ b/docs/8.0/ayanova/docs/svc-workorders.md @@ -60,7 +60,7 @@ docs / sections required * Units: view only and limited to fields to identify unit * Parts: view only and limited to fields to identify part * Part requests: view only - * Expenses: add (no user selection defaults to themselves), view, partial fields available to edit only where they are the selected user and only edit fields Summary, Cost, Tax paid, Description + * Expenses: add (no user selection defaults to themselves), view, partial fields available to edit or delete only where they are the selected user and only edit fields Summary, Cost, Tax paid, Description * Loans: view only and limited fields to identify unit and dates * Outside services: view only, limited fields diff --git a/server/AyaNova/biz/WorkOrderBiz.cs b/server/AyaNova/biz/WorkOrderBiz.cs index 19502e32..e73bd290 100644 --- a/server/AyaNova/biz/WorkOrderBiz.cs +++ b/server/AyaNova/biz/WorkOrderBiz.cs @@ -2402,7 +2402,7 @@ namespace AyaNova.Biz // internal async Task ExpenseGetAsync(long id, bool logTheGetEvent = true) { - if (UserIsSubContractorRestricted) //no access allowed at all + if (UserIsSubContractorFull || UserIsSubContractorRestricted) //no access allowed at all return null; var ret = await ct.WorkOrderItemExpense.AsNoTracking().SingleOrDefaultAsync(z => z.Id == id); if (logTheGetEvent && ret != null) @@ -2558,69 +2558,6 @@ namespace AyaNova.Biz } - /* - As of Alpha.109 "LineTotalViz" is derived incorrectly. It is presently looking like it uses TotalCost and "ChargeToCustomer"=true, instead needs to be based on ChargeAmount - - IF "ChargeToCustomer" = true then do below to get "LineTotalViz": , - If "ChargeTaxCodeId" has a value, then "LineTotalViz": = ( "ChargeAmount" + ((TaxA% * "ChargeAmount") + (TaxB% * "ChargeAmount")) - ELSE - If "ChargeTaxCodeId" does NOT have a value then "LineTotalViz": = ( "ChargeAmount" + "TaxPaid") - ELSE skip and "LineTotalViz" is empty - - */ - - // //////////////////////////////////////////////////////////////////////////////////////////////// - // //BIZ ACTIONS - // // - // // - // private async Task ExpenseBizActionsAsync(AyaEvent ayaEvent, WorkOrderItemExpense newObj, WorkOrderItemExpense oldObj, IDbContextTransaction transaction) - // { - // //automatic actions on record change, called AFTER validation - - // //currently no processing required except for created or modified at this time - // if (ayaEvent != AyaEvent.Created && ayaEvent != AyaEvent.Modified) - // return; - - // //SET TAXES AND PRICING - - // //by default apply all automatic actions with further restrictions possible below - // bool ApplyTax = true; - - - // //if modifed, see what has changed and should be re-applied - // if (ayaEvent == AyaEvent.Modified) - // { - - // //If taxes haven't change then no need to update taxes - // if (newObj.ChargeTaxCodeId == oldObj.ChargeTaxCodeId) - // ApplyTax = false; - // } - - // //Tax code - // if (ApplyTax) - // { - // //Default in case nothing to apply - // newObj.TaxAPct = 0; - // newObj.TaxBPct = 0; - // newObj.TaxOnTax = false; - // newObj.TaxName = ""; - - // if (newObj.ChargeTaxCodeId != null) - // { - // var t = await ct.TaxCode.AsNoTracking().FirstOrDefaultAsync(z => z.Id == newObj.ChargeTaxCodeId); - // if (t != null) - // { - // newObj.TaxAPct = t.TaxAPct; - // newObj.TaxBPct = t.TaxBPct; - // newObj.TaxOnTax = t.TaxOnTax; - // newObj.TaxName = t.Name; - // } - // } - // } - // } - - - //////////////////////////////////////////////////////////////////////////////////////////////// //VALIDATION // @@ -2632,6 +2569,21 @@ namespace AyaNova.Biz //run validation and biz rules bool isNew = currentObj == null; + if (UserIsSubContractorFull || UserIsSubContractorRestricted) + { + //no edits allowed + AddError(ApiErrorCode.NOT_AUTHORIZED, "generalerror"); + return; + } + + if (UserIsTechRestricted && proposedObj.UserId != UserId) + { + //no edits allowed on other people's expenses + AddError(ApiErrorCode.NOT_AUTHORIZED, "generalerror"); + return; + } + + if (proposedObj.WorkOrderItemId == 0) { AddError(ApiErrorCode.VALIDATION_REQUIRED, "WorkOrderItemId"); @@ -2654,6 +2606,44 @@ namespace AyaNova.Biz AddError(ApiErrorCode.VALIDATION_NOT_CHANGEABLE, "generalerror", await Translate("WorkOrderErrorLocked")); return;//this is a completely disqualifying error } + } + + if (!isNew && UserIsTechRestricted) + { + //Existing record so just make sure they haven't changed the not changeable fields from the db version + + //Expenses: add (no user selection defaults to themselves), view, partial fields available + // to edit or delete only where they are the selected user and only edit fields + //Summary, Cost, Tax paid, Description + //note that UI will prevent this, this rule is only backup for 3rd party api users + + if (currentObj.ChargeAmount != proposedObj.ChargeAmount) AddError(ApiErrorCode.VALIDATION_NOT_CHANGEABLE, "ChargeAmount"); + if (currentObj.TaxPaid != proposedObj.TaxPaid) AddError(ApiErrorCode.VALIDATION_NOT_CHANGEABLE, "TaxPaid"); + if (currentObj.ChargeTaxCodeId != proposedObj.ChargeTaxCodeId) AddError(ApiErrorCode.VALIDATION_NOT_CHANGEABLE, "ChargeTaxCodeId"); + if (currentObj.ReimburseUser != proposedObj.ReimburseUser) AddError(ApiErrorCode.VALIDATION_NOT_CHANGEABLE, "ReimburseUser"); + if (currentObj.ChargeToCustomer != proposedObj.ChargeToCustomer) AddError(ApiErrorCode.VALIDATION_NOT_CHANGEABLE, "ChargeToCustomer"); + } + + if (isNew && UserIsTechRestricted) + { + //NEW record, they are not allowed to set several fields so make sure they are still at their defaults + /* + concurrency: 0, + description: null, + name: null, + totalCost: 0, + chargeAmount: 0, + taxPaid: 0, + chargeTaxCodeId: null, + taxCodeViz: null, + reimburseUser: false, + userId: null, + userViz: null, + chargeToCustomer: false, + isDirty: true, + workOrderItemId: this.value.items[this.activeWoItemIndex].id, + uid: Date.now() //used for + */ } @@ -2673,12 +2663,26 @@ namespace AyaNova.Biz private void ExpenseValidateCanDelete(WorkOrderItemExpense obj) { + if (UserIsSubContractorFull || UserIsSubContractorRestricted) + { + //no edits allowed + AddError(ApiErrorCode.NOT_AUTHORIZED, "generalerror"); + return; + } + if (obj == null) { AddError(ApiErrorCode.NOT_FOUND, "id"); return; } + if (UserIsTechRestricted && obj.UserId != UserId) + { + //no edits allowed + AddError(ApiErrorCode.NOT_AUTHORIZED, "generalerror"); + return; + } + //re-check rights here necessary due to traversal delete from Principle object if (!Authorized.HasDeleteRole(CurrentUserRoles, AyaType.WorkOrderItemExpense)) { @@ -5477,6 +5481,8 @@ namespace AyaNova.Biz if (!isNew && UserIsRestrictedType) { + //Existing record so just make sure they haven't changed the not changeable fields from the db version + //* Tasks: view and edit existing tasks, set completion type and date only, no add or remove or changing other fields //note that UI will prevent this, this rule is only backup for 3rd party api users if (currentObj.Task != proposedObj.Task) AddError(ApiErrorCode.VALIDATION_NOT_CHANGEABLE, "Task"); @@ -5484,6 +5490,12 @@ namespace AyaNova.Biz if (currentObj.Sequence != proposedObj.Sequence) AddError(ApiErrorCode.VALIDATION_NOT_CHANGEABLE, "Sequence"); } + if (isNew && UserIsTechRestricted) + { + //NEW record, they are not allowed to set several fields so make sure they are still at their defaults + todo + } + if (string.IsNullOrWhiteSpace(proposedObj.Task)) AddError(ApiErrorCode.VALIDATION_REQUIRED, "Task");