This commit is contained in:
@@ -1719,69 +1719,97 @@ namespace AyaNova.Biz
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
//BIZ ACTIONS
|
//BIZ ACTIONS
|
||||||
//
|
//
|
||||||
private async Task LaborBizActionsAsync(AyaEvent ayaEvent, WorkOrderItemLabor newObj, WorkOrderItemLabor oldObj, IDbContextTransaction transaction)
|
//automatic actions on record change, called AFTER validation
|
||||||
|
// also called when contract changes
|
||||||
|
//
|
||||||
|
private async Task LaborBizActionsAsync(AyaEvent ayaEvent, WorkOrderItemLabor newObj, WorkOrderItemLabor oldObj, IDbContextTransaction transaction, bool contractChanged=false)
|
||||||
{
|
{
|
||||||
|
//currently no processing required except for created or modified at this time
|
||||||
|
if (ayaEvent != AyaEvent.Created && ayaEvent != AyaEvent.Modified)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//SET COST / TAX / PRICE
|
||||||
|
|
||||||
//automatic actions on record change, called AFTER validation
|
|
||||||
var Contract = await GetCurrentWorkOrderContractFromRelatedAsync(AyaType.WorkOrderItem, newObj.WorkOrderItemId);
|
var Contract = await GetCurrentWorkOrderContractFromRelatedAsync(AyaType.WorkOrderItem, newObj.WorkOrderItemId);
|
||||||
|
|
||||||
switch (ayaEvent)
|
//by default apply all automatic actions with further restrictions possible below
|
||||||
|
bool ApplyTax = true;
|
||||||
|
bool ApplyListPricing = true;
|
||||||
|
bool ApplyContractPrice = true;
|
||||||
|
|
||||||
|
//NOTE: If contract itself was changed, that will trigger this from the header change and forceFullUpdate will be in effect
|
||||||
|
|
||||||
|
//if modifed, see what has changed and should be re-applied
|
||||||
|
if (ayaEvent == AyaEvent.Modified)
|
||||||
{
|
{
|
||||||
case AyaEvent.Created:
|
//If it was a service rate change it's like a new record and list pricing and contract applies
|
||||||
//Tax code
|
//so only potentially restrict what applies if that hasn't changed
|
||||||
if (newObj.TaxCodeSaleId != null)
|
if (newObj.ServiceRateId == oldObj.ServiceRateId)
|
||||||
|
{
|
||||||
|
if (newObj.Price != oldObj.Price)//user manually overrode the price
|
||||||
{
|
{
|
||||||
|
ApplyListPricing = false;
|
||||||
var t = await ct.TaxCode.AsNoTracking().FirstOrDefaultAsync(z => z.Id == newObj.TaxCodeSaleId);
|
ApplyContractPrice = false;
|
||||||
if (t != null)
|
|
||||||
{
|
|
||||||
newObj.TaxAPct = t.TaxAPct;
|
|
||||||
newObj.TaxBPct = t.TaxBPct;
|
|
||||||
newObj.TaxOnTax = t.TaxOnTax;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
newObj.TaxAPct = 0;
|
|
||||||
newObj.TaxBPct = 0;
|
|
||||||
newObj.TaxOnTax = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Pricing
|
//same taxes
|
||||||
if (newObj.ServiceRateId != null)
|
if (newObj.TaxCodeSaleId == oldObj.TaxCodeSaleId)
|
||||||
{
|
ApplyTax = false;
|
||||||
var s = await ct.ServiceRate.AsNoTracking().FirstOrDefaultAsync(z => z.Id == newObj.ServiceRateId);
|
|
||||||
if (s != null)
|
|
||||||
{
|
|
||||||
newObj.Cost = s.Cost;
|
|
||||||
newObj.ListPrice = s.Charge;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
newObj.Cost = 0;
|
|
||||||
newObj.ListPrice = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Contract
|
|
||||||
if (Contract != null)
|
|
||||||
{
|
|
||||||
//update discount pricing
|
|
||||||
if (Contract.ServiceRatesOverridePct != 0)
|
|
||||||
{
|
|
||||||
if (Contract.ServiceRatesOverrideType == ContractOverrideType.CostMarkup)
|
|
||||||
newObj.Price = newObj.Cost + (newObj.Cost * Contract.ServiceRatesOverridePct);
|
|
||||||
else if (Contract.ServiceRatesOverrideType == ContractOverrideType.PriceDiscount)
|
|
||||||
newObj.Price = newObj.ListPrice - (newObj.ListPrice * Contract.ServiceRatesOverridePct);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case AyaEvent.Modified:
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Tax code
|
||||||
|
if (ApplyTax && 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;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newObj.TaxAPct = 0;
|
||||||
|
newObj.TaxBPct = 0;
|
||||||
|
newObj.TaxOnTax = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Pricing
|
||||||
|
if (ApplyListPricing && newObj.ServiceRateId != null)
|
||||||
|
{
|
||||||
|
var s = await ct.ServiceRate.AsNoTracking().FirstOrDefaultAsync(z => z.Id == newObj.ServiceRateId);
|
||||||
|
if (s != null)
|
||||||
|
{
|
||||||
|
newObj.Cost = s.Cost;
|
||||||
|
newObj.ListPrice = s.Charge;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newObj.Cost = 0;
|
||||||
|
newObj.ListPrice = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Contract
|
||||||
|
if (ApplyContractPrice && Contract != null)
|
||||||
|
{
|
||||||
|
//update discount pricing
|
||||||
|
if (Contract.ServiceRatesOverridePct != 0)
|
||||||
|
{
|
||||||
|
if (Contract.ServiceRatesOverrideType == ContractOverrideType.CostMarkup)
|
||||||
|
newObj.Price = newObj.Cost + (newObj.Cost * Contract.ServiceRatesOverridePct);
|
||||||
|
else if (Contract.ServiceRatesOverrideType == ContractOverrideType.PriceDiscount)
|
||||||
|
newObj.Price = newObj.ListPrice - (newObj.ListPrice * Contract.ServiceRatesOverridePct);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -4090,10 +4118,20 @@ namespace AyaNova.Biz
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
//GET CONTRACT FOR WORKORDER FROM RELATIVE
|
//GET CONTRACT FOR WORKORDER FROM RELATIVE
|
||||||
//
|
//
|
||||||
|
|
||||||
|
//cache the contract to save repeatedly fetching it for this operation
|
||||||
|
internal Contract mContractInEffect = null;
|
||||||
|
internal bool mFetchedContractAlready = false;//null contract isn't enough to know it was fetched as it could just not have a contract so this is required
|
||||||
|
|
||||||
internal async Task<Contract> GetCurrentWorkOrderContractFromRelatedAsync(AyaType ayaType, long id)
|
internal async Task<Contract> GetCurrentWorkOrderContractFromRelatedAsync(AyaType ayaType, long id)
|
||||||
{
|
{
|
||||||
//instantiated method to save adding the context
|
//instantiated method to save adding the context
|
||||||
return await GetCurrentWorkOrderContractFromRelatedAsync(ayaType, id, ct);
|
if (mFetchedContractAlready == false)
|
||||||
|
{
|
||||||
|
mContractInEffect = await GetCurrentWorkOrderContractFromRelatedAsync(ayaType, id, ct);
|
||||||
|
mFetchedContractAlready = true;
|
||||||
|
}
|
||||||
|
return mContractInEffect;
|
||||||
}
|
}
|
||||||
internal static async Task<Contract> GetCurrentWorkOrderContractFromRelatedAsync(AyaType ayaType, long id, AyContext ct)
|
internal static async Task<Contract> GetCurrentWorkOrderContractFromRelatedAsync(AyaType ayaType, long id, AyContext ct)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ namespace AyaNova.Models
|
|||||||
//from case 3748
|
//from case 3748
|
||||||
- Cost, this is the entered Cost for the item at time of selection
|
- Cost, this is the entered Cost for the item at time of selection
|
||||||
- ListPrice, [REQUIRED] this is the un-discounted per unit price of the item be it labor, parts, loaner, travel etc. What is normally charged at that moment in time for this item if it wasn't discounted.
|
- ListPrice, [REQUIRED] this is the un-discounted per unit price of the item be it labor, parts, loaner, travel etc. What is normally charged at that moment in time for this item if it wasn't discounted.
|
||||||
- Price, [NULLABLE] this is the EFFECTIVE PRICE either contract determined price calculated from ListPrice, otherwise it's a copy of the list price. User with sufficient rights can can override it to enter a different amount which effectively supports manual discount feature in v7 which was by %. This is the *actual* price used in calculations.
|
- Price, [NULLABLE] this is the EFFECTIVE PER UNIT PRICE either contract determined price calculated from ListPrice, otherwise it's a copy of the list price. User with sufficient rights can can override it to enter a different amount which effectively supports manual discount feature in v7 which was by %. This is the *actual* price used in calculations.
|
||||||
- TaxName copied from selected tax code, not directly editable
|
- TaxName copied from selected tax code, not directly editable
|
||||||
- TaxAPct copied from selected tax code, not directly editable
|
- TaxAPct copied from selected tax code, not directly editable
|
||||||
- TaxBPct copied from selected tax code, not directly editable
|
- TaxBPct copied from selected tax code, not directly editable
|
||||||
|
|||||||
Reference in New Issue
Block a user