This commit is contained in:
2021-05-21 22:25:37 +00:00
parent 3f761e64ca
commit 18ab6fd343
2 changed files with 182 additions and 84 deletions

View File

@@ -4117,7 +4117,7 @@ namespace AyaNova.Biz
return null; return null;
else else
{ {
await TravelBizActionsAsync(AyaEvent.Created, newObject, null, null); //await TravelBizActionsAsync(AyaEvent.Created, newObject, null, null);
//newObject.Tags = TagBiz.NormalizeTags(newObject.Tags); //newObject.Tags = TagBiz.NormalizeTags(newObject.Tags);
//newObject.CustomFields = JsonUtil.CompactJson(newObject.CustomFields); //newObject.CustomFields = JsonUtil.CompactJson(newObject.CustomFields);
await ct.WorkOrderItemTravel.AddAsync(newObject); await ct.WorkOrderItemTravel.AddAsync(newObject);
@@ -4163,7 +4163,7 @@ namespace AyaNova.Biz
// dbObject.CustomFields = JsonUtil.CompactJson(dbObject.CustomFields); // dbObject.CustomFields = JsonUtil.CompactJson(dbObject.CustomFields);
await TravelValidateAsync(putObject, dbObject); await TravelValidateAsync(putObject, dbObject);
if (HasErrors) return null; if (HasErrors) return null;
await TravelBizActionsAsync(AyaEvent.Modified, putObject, dbObject, null); // await TravelBizActionsAsync(AyaEvent.Modified, putObject, dbObject, null);
ct.Replace(dbObject, putObject); ct.Replace(dbObject, putObject);
try try
{ {
@@ -4248,103 +4248,195 @@ namespace AyaNova.Biz
// //
private async Task TravelPopulateVizFields(WorkOrderItemTravel o) private async Task TravelPopulateVizFields(WorkOrderItemTravel o)
{ {
await Task.CompletedTask; if (o.UserId != null)
// if (o.WorkOrderOverseerId != null) o.UserViz = await ct.User.AsNoTracking().Where(x => x.Id == o.UserId).Select(x => x.Name).FirstOrDefaultAsync();
// o.WorkOrderOverseerViz = await ct.User.AsNoTracking().Where(x => x.Id == o.WorkOrderOverseerId).Select(x => x.Name).FirstOrDefaultAsync(); TravelRate Rate = null;
if (o.TravelRateId != null)
Rate = await ct.TravelRate.AsNoTracking().FirstOrDefaultAsync(x => x.Id == o.TravelRateId);
TaxCode Tax = null;
if (o.TaxCodeSaleId != null)
Tax = await ct.TaxCode.AsNoTracking().FirstOrDefaultAsync(z => z.Id == o.TaxCodeSaleId);
if (Tax != null)
o.TaxCodeSaleViz = Tax.Name;
o.PriceViz = 0;
if (Rate != null)
{
o.CostViz = Rate.Cost;
o.ListPriceViz = Rate.Charge;
o.UnitOfMeasureViz = Rate.Unit;
o.PriceViz = Rate.Charge;//default price used if not manual or contract override
} }
//manual price overrides anything
//////////////////////////////////////////////////////////////////////////////////////////////// if (o.PriceOverride != null)
//BIZ ACTIONS o.PriceViz = (decimal)o.PriceOverride;
// else
//
private async Task TravelBizActionsAsync(AyaEvent ayaEvent, WorkOrderItemTravel newObj, WorkOrderItemTravel oldObj, IDbContextTransaction transaction)
{ {
//automatic actions on record change, called AFTER validation //not manual so could potentially have a contract adjustment
var c = await GetCurrentWorkOrderContractFromRelatedAsync(AyaType.WorkOrderItem, o.WorkOrderItemId);
//currently no processing required except for created or modified at this time if (c != null)
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 ApplyPricingUpdate = true;
//if modifed, see what has changed and should be re-applied
if (ayaEvent == AyaEvent.Modified)
{ {
//If it wasn't a service rate change there is no need to set pricing decimal pct = 0;
if (newObj.TravelRateId == oldObj.TravelRateId) ContractOverrideType cot = ContractOverrideType.PriceDiscount;
{
ApplyPricingUpdate = false;
}
//If taxes haven't change then no need to update taxes
if (newObj.TaxCodeSaleId == oldObj.TaxCodeSaleId)
ApplyTax = false;
}
//Tax code bool TaggedAdjustmentInEffect = false;
if (ApplyTax)
{
//Default in case nothing to apply
newObj.TaxAPct = 0;
newObj.TaxBPct = 0;
newObj.TaxOnTax = false;
if (newObj.TaxCodeSaleId != null) //POTENTIAL CONTRACT ADJUSTMENTS
//First check if there is a matching tagged Travel rate contract discount, that takes precedence
if (c.ContractTravelRateOverrideItems.Count > 0)
{ {
var t = await ct.TaxCode.AsNoTracking().FirstOrDefaultAsync(z => z.Id == newObj.TaxCodeSaleId); //Iterate all contract tagged items in order of ones with the most tags first
if (t != null) foreach (var csr in c.ContractTravelRateOverrideItems.OrderByDescending(z => z.Tags.Count))
if (csr.Tags.All(z => Rate.Tags.Any(x => x == z)))
{ {
newObj.TaxAPct = t.TaxAPct; if (csr.OverridePct != 0)
newObj.TaxBPct = t.TaxBPct; {
newObj.TaxOnTax = t.TaxOnTax; pct = csr.OverridePct / 100;
cot = csr.OverrideType;
TaggedAdjustmentInEffect = true;
} }
} }
} }
//Pricing //Generic discount?
if (ApplyPricingUpdate) if (!TaggedAdjustmentInEffect && c.TravelRatesOverridePct != 0)
{ {
//default in case nothing to apply pct = c.TravelRatesOverridePct / 100;
newObj.Cost = 0; cot = c.TravelRatesOverrideType;
newObj.ListPrice = 0;
newObj.Price = 0;
//in v7 it was ok to have no service rate selected
//not sure why but carried forward to v8 so..
if (newObj.TravelRateId != null)
{
var s = await ct.TravelRate.AsNoTracking().FirstOrDefaultAsync(z => z.Id == newObj.TravelRateId);
if (s != null)
{
newObj.Cost = s.Cost;
newObj.ListPrice = s.Charge;
var Contract = await GetCurrentWorkOrderContractFromRelatedAsync(AyaType.WorkOrderItem, newObj.WorkOrderItemId);
TravelSetListPrice(newObj, Contract);
} }
//apply if discount found
if (pct != 0)
{
if (cot == ContractOverrideType.CostMarkup)
o.PriceViz = o.CostViz + (o.CostViz * pct);
else if (cot == ContractOverrideType.PriceDiscount)
o.PriceViz = o.ListPriceViz - (o.ListPriceViz * pct);
} }
} }
} }
//////////////////////////////////////////////////////////////////////////////////////////////// //Calculate totals and taxes
// SET PER UNIT LIST PRICE //NET
// o.NetViz = o.PriceViz * o.TravelRateQuantity;
//(called by woitemtravel save and also by header save on change of contract)
private static void TravelSetListPrice(WorkOrderItemTravel o, Contract c) //TAX
o.TaxAViz = 0;
o.TaxBViz = 0;
if (Tax != null)
{ {
if (c == null || c.ServiceRatesOverridePct == 0) if (Tax.TaxAPct != 0)
{ {
o.Price = o.ListPrice;//default with no contract o.TaxAViz = o.NetViz * (Tax.TaxAPct / 100);
return;
} }
if (c.ServiceRatesOverrideType == ContractOverrideType.CostMarkup) if (Tax.TaxBPct != 0)
o.Price = o.Cost + (o.Cost * c.ServiceRatesOverridePct); {
else if (c.ServiceRatesOverrideType == ContractOverrideType.PriceDiscount) if (Tax.TaxOnTax)
o.Price = o.ListPrice - (o.ListPrice * c.ServiceRatesOverridePct); {
o.TaxBViz = (o.NetViz + o.TaxAViz) * (Tax.TaxBPct / 100);
} }
else
{
o.TaxBViz = o.NetViz * (Tax.TaxBPct / 100);
}
}
}
o.LineTotalViz = o.NetViz + o.TaxAViz + o.TaxBViz;
}
// ////////////////////////////////////////////////////////////////////////////////////////////////
// //BIZ ACTIONS
// //
// //
// private async Task TravelBizActionsAsync(AyaEvent ayaEvent, WorkOrderItemTravel newObj, WorkOrderItemTravel 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 ApplyPricingUpdate = true;
// //if modifed, see what has changed and should be re-applied
// if (ayaEvent == AyaEvent.Modified)
// {
// //If it wasn't a service rate change there is no need to set pricing
// if (newObj.TravelRateId == oldObj.TravelRateId)
// {
// ApplyPricingUpdate = 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;
// 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;
// }
// }
// }
// //Pricing
// if (ApplyPricingUpdate)
// {
// //default in case nothing to apply
// newObj.Cost = 0;
// newObj.ListPrice = 0;
// newObj.Price = 0;
// //in v7 it was ok to have no service rate selected
// //not sure why but carried forward to v8 so..
// if (newObj.TravelRateId != null)
// {
// var s = await ct.TravelRate.AsNoTracking().FirstOrDefaultAsync(z => z.Id == newObj.TravelRateId);
// if (s != null)
// {
// newObj.Cost = s.Cost;
// newObj.ListPrice = s.Charge;
// var Contract = await GetCurrentWorkOrderContractFromRelatedAsync(AyaType.WorkOrderItem, newObj.WorkOrderItemId);
// TravelSetListPrice(newObj, Contract);
// }
// }
// }
// }
// ////////////////////////////////////////////////////////////////////////////////////////////////
// // SET PER UNIT LIST PRICE
// //
// //(called by woitemtravel save and also by header save on change of contract)
// private static void TravelSetListPrice(WorkOrderItemTravel o, Contract c)
// {
// if (c == null || c.ServiceRatesOverridePct == 0)
// {
// o.Price = o.ListPrice;//default with no contract
// return;
// }
// if (c.ServiceRatesOverrideType == ContractOverrideType.CostMarkup)
// o.Price = o.Cost + (o.Cost * c.ServiceRatesOverridePct);
// else if (c.ServiceRatesOverrideType == ContractOverrideType.PriceDiscount)
// o.Price = o.ListPrice - (o.ListPrice * c.ServiceRatesOverridePct);
// }

View File

@@ -12,14 +12,20 @@ namespace AyaNova.Models
public uint Concurrency { get; set; } public uint Concurrency { get; set; }
public long? UserId { get; set; } public long? UserId { get; set; }
[NotMapped]
public string UserViz { get; set; }
public DateTime? TravelStartDate { get; set; } public DateTime? TravelStartDate { get; set; }
public DateTime? TravelStopDate { get; set; } public DateTime? TravelStopDate { get; set; }
public long? TravelRateId { get; set; } public long? TravelRateId { get; set; }
[NotMapped]
public string TravelRateViz { get; set; }
public string TravelDetails { get; set; } public string TravelDetails { get; set; }
public decimal TravelRateQuantity { get; set; } public decimal TravelRateQuantity { get; set; }
public decimal NoChargeQuantity { get; set; } public decimal NoChargeQuantity { get; set; }
public long? ServiceBankId { get; set; } public long? ServiceBankId { get; set; }
public long? TaxCodeSaleId { get; set; } public long? TaxCodeSaleId { get; set; }
[NotMapped]
public string TaxCodeSaleViz { get; set; }
public decimal Distance { get; set; } public decimal Distance { get; set; }