This commit is contained in:
@@ -53,7 +53,7 @@ docs / sections required
|
|||||||
* All restrictions listed above in Work order *Item* restrictions plus:
|
* All restrictions listed above in Work order *Item* restrictions plus:
|
||||||
* All work order header fields visible but not editable other than work order status which has a separately configurable role restriction setting (including attachments, wiki and tags)
|
* All work order header fields visible but not editable other than work order status which has a separately configurable role restriction setting (including attachments, wiki and tags)
|
||||||
* Form main menu items available: none except for Report which has a separately configurable role restriction setting
|
* Form main menu items available: none except for Report which has a separately configurable role restriction setting
|
||||||
* Tasks: view and edit existing tasks only, no add or remove or changing task text
|
* Tasks: view and edit existing tasks, set completion type and date only, no add or remove or changing other fields
|
||||||
* Scheduled Users: view only where they are the selected User and convert to labor record
|
* Scheduled Users: view only where they are the selected User and convert to labor record
|
||||||
* Labors: add (no user selection defaults to themselves), remove, view and edit only when they are the selected User
|
* Labors: add (no user selection defaults to themselves), remove, view and edit only when they are the selected User
|
||||||
* Travels: add (no user selection defaults to themselves), remove, view and edit only when they are the selected User
|
* Travels: add (no user selection defaults to themselves), remove, view and edit only when they are the selected User
|
||||||
@@ -68,7 +68,7 @@ docs / sections required
|
|||||||
* All restrictions listed above in Work order *Item* restrictions plus:
|
* All restrictions listed above in Work order *Item* restrictions plus:
|
||||||
* No work order header fields visible except for Customer name and service address
|
* No work order header fields visible except for Customer name and service address
|
||||||
* Form main menu items available: none except for Report which has a separately configurable role restriction setting
|
* Form main menu items available: none except for Report which has a separately configurable role restriction setting
|
||||||
* Tasks: view and edit existing tasks only, no add or remove or changing task text
|
* Tasks: view and edit existing tasks, set completion type and date only, no add or remove or changing other fields
|
||||||
* Scheduled Users: view only where they are the selected User and convert to labor record
|
* Scheduled Users: view only where they are the selected User and convert to labor record
|
||||||
* Labors: add (no user selection defaults to themselves), remove, view and edit only when they are the selected User
|
* Labors: add (no user selection defaults to themselves), remove, view and edit only when they are the selected User
|
||||||
* Travels: add (no user selection defaults to themselves), remove, view and edit only when they are the selected User
|
* Travels: add (no user selection defaults to themselves), remove, view and edit only when they are the selected User
|
||||||
@@ -83,7 +83,7 @@ docs / sections required
|
|||||||
* All restrictions listed above in Work order *Item* restrictions plus:
|
* All restrictions listed above in Work order *Item* restrictions plus:
|
||||||
* No work order header fields visible except for Customer name
|
* No work order header fields visible except for Customer name
|
||||||
* Form main menu items available: none except for Report which has a separately configurable role restriction setting
|
* Form main menu items available: none except for Report which has a separately configurable role restriction setting
|
||||||
* Tasks: view and edit existing tasks only, no add or remove or changing task text
|
* Tasks: view and edit existing tasks, set completion type and date only, no add or remove or changing other fields
|
||||||
* Scheduled Users: view only where they are the selected User and convert to labor record
|
* Scheduled Users: view only where they are the selected User and convert to labor record
|
||||||
* Labors: add (no user selection defaults to themselves), remove, view and edit only when they are the selected User
|
* Labors: add (no user selection defaults to themselves), remove, view and edit only when they are the selected User
|
||||||
* Travels: add (no user selection defaults to themselves), remove, view and edit only when they are the selected User
|
* Travels: add (no user selection defaults to themselves), remove, view and edit only when they are the selected User
|
||||||
|
|||||||
@@ -2983,136 +2983,6 @@ namespace AyaNova.Biz
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// //BIZ ACTIONS
|
|
||||||
// //
|
|
||||||
// //
|
|
||||||
// private async Task LaborBizActionsAsync(AyaEvent ayaEvent, WorkOrderItemLabor newObj, WorkOrderItemLabor 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;
|
|
||||||
// bool SetPrice = true;
|
|
||||||
|
|
||||||
// //if modifed, see what has changed and should be re-applied
|
|
||||||
// if (ayaEvent == AyaEvent.Modified)
|
|
||||||
// {
|
|
||||||
// //If it wasn't a service rate or quantity change there is no need to set pricing
|
|
||||||
// if (newObj.ServiceRateId == oldObj.ServiceRateId && newObj.ServiceRateQuantity == oldObj.ServiceRateQuantity)
|
|
||||||
// {
|
|
||||||
// SetPrice = false;
|
|
||||||
// }
|
|
||||||
// //If taxes haven't change then no need to update taxes
|
|
||||||
// if (newObj.TaxCodeSaleId == oldObj.TaxCodeSaleId)
|
|
||||||
// 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.TaxCodeSaleId != null)
|
|
||||||
// {
|
|
||||||
// var t = await ct.TaxCode.AsNoTracking().FirstOrDefaultAsync(z => z.Id == newObj.TaxCodeSaleId);
|
|
||||||
// if (t != null)
|
|
||||||
// {
|
|
||||||
// newObj.TaxAPct = t.TaxAPct;
|
|
||||||
// newObj.TaxBPct = t.TaxBPct;
|
|
||||||
// newObj.TaxOnTax = t.TaxOnTax;
|
|
||||||
// newObj.TaxName = t.Name;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// //Pricing
|
|
||||||
// if (SetPrice)
|
|
||||||
// {
|
|
||||||
// var Contract = await GetCurrentWorkOrderContractFromRelatedAsync(AyaType.WorkOrderItem, newObj.WorkOrderItemId);
|
|
||||||
// await LaborSetPrice(newObj, Contract);
|
|
||||||
|
|
||||||
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// ////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// // SET PER UNIT LIST PRICE
|
|
||||||
// //
|
|
||||||
// //(called by woitemlabor save and also by header save on change of contract)
|
|
||||||
// private async Task LaborSetPrice(WorkOrderItemLabor o, Contract c)
|
|
||||||
// {
|
|
||||||
// //default in case nothing to apply
|
|
||||||
// o.Cost = 0;
|
|
||||||
// o.ListPrice = 0;
|
|
||||||
// o.Price = 0;
|
|
||||||
|
|
||||||
// //in v7 it was ok to have no service rate selected
|
|
||||||
// //not sure why but carried forward to v8 so..
|
|
||||||
// if (o.ServiceRateId == null)
|
|
||||||
// return;
|
|
||||||
|
|
||||||
// var Rate = await ct.ServiceRate.AsNoTracking().FirstOrDefaultAsync(z => z.Id == o.ServiceRateId);
|
|
||||||
// if (Rate == null)
|
|
||||||
// {
|
|
||||||
// AddError(ApiErrorCode.NOT_FOUND, "generalerror", "Service rate not found");//this should never happen, no point in localizing
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// o.Cost = Rate.Cost;
|
|
||||||
// o.ListPrice = Rate.Charge;
|
|
||||||
// o.Price = o.ListPrice;//default is list price unless a contract overrides it
|
|
||||||
|
|
||||||
// if (c == null)
|
|
||||||
// return;//No contract so bail out now, it's done
|
|
||||||
|
|
||||||
|
|
||||||
// //POTENTIAL CONTRACT ADJUSTMENTS
|
|
||||||
// //First check if there is a matching tagged service rate contract discount, that takes precedence
|
|
||||||
// if (c.ContractServiceRateOverrideItems.Count > 0)
|
|
||||||
// {
|
|
||||||
// //Iterate all contract tagged items in order of ones with the most tags first
|
|
||||||
// foreach (var csr in c.ContractServiceRateOverrideItems.OrderByDescending(z => z.Tags.Count))
|
|
||||||
// if (csr.Tags.All(z => Rate.Tags.Any(x => x == z)))
|
|
||||||
// {
|
|
||||||
// if (csr.OverridePct != 0)
|
|
||||||
// {
|
|
||||||
// var pct = csr.OverridePct / 100;
|
|
||||||
// //found a match, apply the discount and return
|
|
||||||
// if (csr.OverrideType == ContractOverrideType.CostMarkup)
|
|
||||||
// o.Price = o.Cost + (o.Cost * pct);
|
|
||||||
// else if (csr.OverrideType == ContractOverrideType.PriceDiscount)
|
|
||||||
// o.Price = o.ListPrice - (o.ListPrice * pct);
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// //No tag discounts, so check for a generic one
|
|
||||||
// if (c.ServiceRatesOverridePct == 0)
|
|
||||||
// return;// no generic discount for all items so bail now
|
|
||||||
|
|
||||||
// {
|
|
||||||
// var pct = c.ServiceRatesOverridePct / 100;
|
|
||||||
|
|
||||||
// //Contract has a generic override so apply it
|
|
||||||
// if (c.ServiceRatesOverrideType == ContractOverrideType.CostMarkup)
|
|
||||||
// o.Price = o.Cost + (o.Cost * pct);
|
|
||||||
// else if (c.ServiceRatesOverrideType == ContractOverrideType.PriceDiscount)
|
|
||||||
// o.Price = o.ListPrice - (o.ListPrice * pct);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -3147,7 +3017,13 @@ namespace AyaNova.Biz
|
|||||||
AddError(ApiErrorCode.VALIDATION_NOT_CHANGEABLE, "generalerror", await Translate("WorkOrderErrorLocked"));
|
AddError(ApiErrorCode.VALIDATION_NOT_CHANGEABLE, "generalerror", await Translate("WorkOrderErrorLocked"));
|
||||||
return;//this is a completely disqualifying error
|
return;//this is a completely disqualifying error
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UserIsRestrictedType
|
||||||
|
{
|
||||||
|
//Scheduled Users: view only where they are the selected User and convert to labor record
|
||||||
|
AddError(ApiErrorCode.NOT_AUTHORIZED, "generalerror");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Start date AND end date must both be null or both contain values
|
//Start date AND end date must both be null or both contain values
|
||||||
@@ -5099,12 +4975,12 @@ namespace AyaNova.Biz
|
|||||||
return;//this is a completely disqualifying error
|
return;//this is a completely disqualifying error
|
||||||
}
|
}
|
||||||
|
|
||||||
// //TEST TEST TEST
|
if (UserIsRestrictedType)
|
||||||
// if (proposedObj.EstimatedQuantity == 69)
|
{
|
||||||
// {
|
//Scheduled Users: view only where they are the selected User and convert to labor record
|
||||||
// AddError(ApiErrorCode.VALIDATION_INVALID_VALUE, $"EstimatedQuantity", "◈◈ TEST SAVE ERROR ◈◈");
|
AddError(ApiErrorCode.NOT_AUTHORIZED, "generalerror");
|
||||||
// }
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
//Check state if updatable right now
|
//Check state if updatable right now
|
||||||
if (!isNew)
|
if (!isNew)
|
||||||
@@ -5180,12 +5056,12 @@ namespace AyaNova.Biz
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// //TEST TEST TEST
|
if (UserIsRestrictedType)
|
||||||
// if (obj.EstimatedQuantity == 69)
|
{
|
||||||
// {
|
//Scheduled Users: view only where they are the selected User and convert to labor record
|
||||||
// AddError(ApiErrorCode.VALIDATION_INVALID_VALUE, $"EstimatedQuantity", "◈◈ TEST DELETE ERROR ◈◈");
|
AddError(ApiErrorCode.NOT_AUTHORIZED, "generalerror");
|
||||||
// }
|
return;
|
||||||
|
}
|
||||||
//re-check rights here necessary due to traversal delete from Principle object
|
//re-check rights here necessary due to traversal delete from Principle object
|
||||||
if (!Authorized.HasDeleteRole(CurrentUserRoles, AyaType.WorkOrderItemScheduledUser))
|
if (!Authorized.HasDeleteRole(CurrentUserRoles, AyaType.WorkOrderItemScheduledUser))
|
||||||
{
|
{
|
||||||
@@ -5527,6 +5403,8 @@ namespace AyaNova.Biz
|
|||||||
AddError(ApiErrorCode.VALIDATION_INVALID_VALUE, "WorkOrderItemId");
|
AddError(ApiErrorCode.VALIDATION_INVALID_VALUE, "WorkOrderItemId");
|
||||||
return;//this is a completely disqualifying error
|
return;//this is a completely disqualifying error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//Check state if updatable right now
|
//Check state if updatable right now
|
||||||
if (!isNew)
|
if (!isNew)
|
||||||
{
|
{
|
||||||
@@ -5540,12 +5418,26 @@ namespace AyaNova.Biz
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isNew && UserIsRestrictedType)
|
||||||
|
{
|
||||||
|
//restricted users are not allowed to make new task entries only fill them out
|
||||||
|
AddError(ApiErrorCode.NOT_AUTHORIZED, "generalerror");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isNew && UserIsRestrictedType)
|
||||||
|
{
|
||||||
|
//* 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");
|
||||||
|
if (currentObj.CompletedByUserId != UserId) AddError(ApiErrorCode.VALIDATION_INVALID_VALUE, "CompletedByUserId");
|
||||||
|
if (currentObj.Sequence != proposedObj.Sequence) AddError(ApiErrorCode.VALIDATION_NOT_CHANGEABLE, "Sequence");
|
||||||
|
}
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(proposedObj.Task))
|
if (string.IsNullOrWhiteSpace(proposedObj.Task))
|
||||||
AddError(ApiErrorCode.VALIDATION_REQUIRED, "Task");
|
AddError(ApiErrorCode.VALIDATION_REQUIRED, "Task");
|
||||||
|
|
||||||
//TEST TEST TEST ERROR
|
|
||||||
if (proposedObj.Sequence == 999)
|
|
||||||
AddError(ApiErrorCode.VALIDATION_INVALID_VALUE, "Sequence");
|
|
||||||
|
|
||||||
//Any form customizations to validate?
|
//Any form customizations to validate?
|
||||||
var FormCustomization = await ct.FormCustom.AsNoTracking().SingleOrDefaultAsync(z => z.FormKey == AyaType.WorkOrderItemTask.ToString());
|
var FormCustomization = await ct.FormCustom.AsNoTracking().SingleOrDefaultAsync(z => z.FormKey == AyaType.WorkOrderItemTask.ToString());
|
||||||
@@ -5570,6 +5462,13 @@ namespace AyaNova.Biz
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (UserIsRestrictedType)
|
||||||
|
{
|
||||||
|
//restricted users are not allowed to delete a task only fill them out
|
||||||
|
AddError(ApiErrorCode.NOT_AUTHORIZED, "generalerror");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
//re-check rights here necessary due to traversal delete from Principle object
|
//re-check rights here necessary due to traversal delete from Principle object
|
||||||
if (!Authorized.HasDeleteRole(CurrentUserRoles, AyaType.WorkOrderItemTask))
|
if (!Authorized.HasDeleteRole(CurrentUserRoles, AyaType.WorkOrderItemTask))
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user