This commit is contained in:
2022-07-09 21:12:34 +00:00
parent e4e40a6913
commit 139b804378
4 changed files with 218 additions and 489 deletions

View File

@@ -996,7 +996,7 @@ namespace AyaNovaQBI
#region Workorder item loan charge as
//Validate any existing
if (SetEverything == false && QDat.WorkorderItemLoanChargeAs != null && QDat.WorkorderItemLoanChargeAs != "")
if (SetEverything == false && QDat.WorkOrderItemLoanChargeAs != null && QDat.WorkOrderItemLoanChargeAs != "")
{
goto LOANCHARGEASOK;
}
@@ -1010,14 +1010,14 @@ namespace AyaNovaQBI
"to use when invoicing the AyaNova \"Workorder item loan\" portion of a work order.\r\n\r\n" +
"This setting is mandatory / required.";
s2.QBItems = QBItems;
s2.SelectedQBItem = QDat.WorkorderItemLoanChargeAs;
s2.SelectedQBItem = QDat.WorkOrderItemLoanChargeAs;
if (s2.ShowDialog() == DialogResult.Cancel)
{
return pfstat.Cancel;
}
else
QDat.WorkorderItemLoanChargeAs = s2.SelectedQBItem;
QDat.WorkOrderItemLoanChargeAs = s2.SelectedQBItem;
s2.Dispose();
s2 = null;
@@ -5691,217 +5691,215 @@ namespace AyaNovaQBI
/// and on any error found adds them to the
/// mismatched object array list
/// </summary>
/// <param name="WorkorderID">Id of workorder being scanned</param>
/// <param name="workOrderId">Id of workorder being scanned</param>
/// <param name="MisMatches">An list of mismatch objects</param>
/// <param name="PriceOverrides">An list of id values of workorderitemparts that have been set by
/// user to forcibly use the price set on the workorderitem part even though
/// it differs from the quickbooks price</param>
/// <returns>True if all links ok, false if there are any mismatches at all</returns>
public static bool ScanLinksOK(long WorkorderID, List<MisMatch> MisMatches, List<long> PriceOverrides)
public static async Task<bool> ScanLinksOK(long workOrderId, List<MisMatch> MisMatches, List<long> PriceOverrides)
{
bool bReturn = true;
bool bSomethingToInvoice = false;
//WorkOrder w = Workorder.GetItem(WorkorderID);
////Client ok?
//if (!QBIntegration.Items.Any(z=>z.AType==AyaType.Customer && z.ObjectId==w.CustomerId))
//{
// bReturn = false;
// AddMisMatch(AyaClientList[w.ClientID].Name, w.ClientID, AyaType.Customer, MisMatchReason.NotLinkedToQB, MisMatches);
//}
////Service rates:
//foreach (WorkorderItem wi in w.WorkorderItems)
//{
// #region Labor
// foreach (WorkorderItemLabor wl in wi.Labors)
// {
// //If there's *any* labor then there is something to invoice
// bSomethingToInvoice = true;
// //Check that rate isn't actually guid.empty
// //it's possible that some users have not selected a rate on the workorder
// if (wl.ServiceRateID == Guid.Empty)
// throw new System.ApplicationException("ERROR: Workorder " + w.WorkorderService.ServiceNumber.ToString() + " has a labor item with no rate selected\r\n" +
// "This is a serious problem for QBI and needs to be rectified before QBI can be used.\r\n");
// if (!QBI.Maps.Contains(wl.ServiceRateID))
// {
// bReturn = false;
// AddMisMatch(AyaRateList[wl.ServiceRateID].Name, wl.ServiceRateID, RootObjectTypes.Rate, MisMatchReason.NotLinkedToQB, MisMatches);
// }
// }
// #endregion
// #region Travel
// foreach (WorkorderItemTravel wt in wi.Travels)
// {
// //If there's *any* travel then there is something to invoice
// bSomethingToInvoice = true;
// //Check that rate isn't actually guid.empty
// //it's possible that some users have not selected a rate on the workorder
// if (wt.TravelRateID == Guid.Empty)
// throw new System.ApplicationException("ERROR: Workorder " + w.WorkorderService.ServiceNumber.ToString() + " has a travel item with no rate selected\r\n" +
// "This is a serious problem for QBI and needs to be rectified before QBI can be used.\r\n");
// if (!QBI.Maps.Contains(wt.TravelRateID))
// {
// bReturn = false;
// AddMisMatch(AyaRateList[wt.TravelRateID].Name, wt.TravelRateID, RootObjectTypes.Rate, MisMatchReason.NotLinkedToQB, MisMatches);
// }
// }
// #endregion
// #region Parts
// foreach (WorkorderItemPart wp in wi.Parts)
// {
// //If there's *any* parts then there is something to invoice
// bSomethingToInvoice = true;
// //Changed: 14-Nov-2006 to check that linked item id exists in qb
// if (!QBI.Maps.Contains(wp.PartID) || QBItems.Rows.Find(QBI.Maps[wp.PartID].ForeignID) == null)
// {
// bReturn = false;
// //Changed: 21-June-2006 to use display formatted name
// AddMisMatch(AyaPartList[wp.PartID].DisplayName(Util.GlobalSettings.DefaultPartDisplayFormat), wp.PartID, RootObjectTypes.Part, MisMatchReason.NotLinkedToQB, MisMatches);
// }
// else
// {
// //check the price
// if (!PriceOverrides.Contains(wp.ID))
// {
// decimal qbPrice = (decimal)QBItems.Rows.Find(QBI.Maps[wp.PartID].ForeignID)["Price"];
// //------------DISCOUNT-----------------
// string disco = "";
// //Added:20-July-2006 to incorporate discounts on parts into qb invoice
// decimal charge;
// //Changed: 18-Nov-2006 CASE 158
// //this is all wrong, it was multiplying price by quantity to calculate charge when it shouldn't
// //removed quanty * price in next line to just price
// charge = decimal.Round(wp.Price, 2, MidpointRounding.AwayFromZero);
// charge = charge - (decimal.Round(charge * wp.Discount, 2, MidpointRounding.AwayFromZero));
// if (wp.Discount != 0)
// {
// disco = " (Price " + wp.Price.ToString("c") + " discounted on workorder " + wp.Discount.ToString("p") + ") \r\n";
// }
// //-----------------------------
// //It's a match, let's see if the price matches as well
// if (charge != qbPrice)
// {
// bReturn = false;
// AddMisMatch("WO: " + w.WorkorderService.ServiceNumber.ToString() + disco + " Part: " + AyaPartList[wp.PartID].DisplayName(Util.GlobalSettings.DefaultPartDisplayFormat),//Changed: 21-June-2006 to use display formatted name
// wp.PartID, RootObjectTypes.Part, MisMatchReason.PriceDifferent, MisMatches, qbPrice, charge, wp.ID,
// QBI.Maps[wp.PartID].ForeignID);
// }
// }
// }
// }
// #endregion
// #region Outside service charges
// if (wi.HasOutsideService)
// {
// if (wi.OutsideService.RepairPrice != 0 || wi.OutsideService.ShippingPrice != 0)
// {
// bSomethingToInvoice = true;
// //there is something billable, just need to make sure
// //that there is a QB charge defined for outside service
// if (QDat.OutsideServiceChargeAs == null ||
// QDat.OutsideServiceChargeAs == "" ||
// !QBItems.Rows.Contains(QDat.OutsideServiceChargeAs))
// {
// bReturn = false;
// AddMisMatch("Outside service", Guid.Empty, RootObjectTypes.WorkorderItemOutsideService, MisMatchReason.NotLinkedToQB, MisMatches);
// }
// }
// }
// #endregion
// #region Workorder item loan charges
// if (wi.HasLoans)
// {
// foreach (WorkorderItemLoan wil in wi.Loans)
// {
// if (wil.Charges != 0)
// {
// //case 772
// bSomethingToInvoice = true;
// //there is something billable, just need to make sure
// //that there is a QB charge defined for loaned item charges
// if (QDat.WorkorderItemLoanChargeAs == null ||
// QDat.WorkorderItemLoanChargeAs == "" ||
// !QBItems.Rows.Contains(QDat.WorkorderItemLoanChargeAs))
// {
// bReturn = false;
// AddMisMatch("Workorder item loan", Guid.Empty, RootObjectTypes.WorkorderItemLoan, MisMatchReason.NotLinkedToQB, MisMatches);
// break;
// }
// }
// }
// }
// #endregion
// #region Workorder item misc expenses
// if (wi.HasExpenses)
// {
// foreach (WorkorderItemMiscExpense wie in wi.Expenses)
// {
var a = await GetAsync($"workorder/{workOrderId}");
WorkOrder w = a.ObjectResponse["data"].ToObject<WorkOrder>();
if (w == null)
throw new Exception($"ScanLinksOK: WorkOrder with id {workOrderId} was not found in AyaNova and may have just been deleted.\r\nUnable to proceed.");
// if (wie.ChargeToClient)
// {
// bSomethingToInvoice = true;
// //there is something billable, just need to make sure
// //that there is a QB charge defined for misc expense item charges
// if (QDat.MiscExpenseChargeAs == null ||
// QDat.MiscExpenseChargeAs == "" ||
// !QBItems.Rows.Contains(QDat.MiscExpenseChargeAs))
// {
// bReturn = false;
// AddMisMatch("Workorder item expense", Guid.Empty, RootObjectTypes.WorkorderItemMiscExpense, MisMatchReason.NotLinkedToQB, MisMatches);
// break;
//Client ok?
if (!QBIntegration.Items.Any(z => z.AType == AyaType.Customer && z.ObjectId == w.CustomerId))
{
bReturn = false;
AddMisMatch(AyaClientList.FirstOrDefault(z=>z.Id==w.CustomerId).Name, w.CustomerId, AyaType.Customer, MisMatchReason.NotLinkedToQB, MisMatches);
}
// }
// }
// }
// }
// #endregion
//Service rates:
foreach (WorkOrderItem wi in w.Items)
{
#region Labor
foreach (WorkOrderItemLabor wl in wi.Labors)
{
//If there's *any* labor then there is something to invoice
bSomethingToInvoice = true;
//Check that rate isn't actually guid.empty
//it's possible that some users have not selected a rate on the workorder
if (null== wl.ServiceRateId || wl.ServiceRateId == 0)
throw new System.ApplicationException($"ERROR: Workorder {w.Serial} has a Labor item with no rate selected\r\nThis is a serious problem for QBI and needs to be rectified before QBI can be used.\r\n");
if (!QBIntegration.Items.Any(z => z.AType == AyaType.ServiceRate && z.ObjectId == wl.ServiceRateId))
{
bReturn = false;
AddMisMatch(AyaServiceRateList.FirstOrDefault(z => z.Id == wl.ServiceRateId).Name, (long)wl.ServiceRateId, AyaType.ServiceRate, MisMatchReason.NotLinkedToQB, MisMatches);
}
}
#endregion
#region Travel
foreach (WorkOrderItemTravel wt in wi.Travels)
{
//If there's *any* travel then there is something to invoice
bSomethingToInvoice = true;
//Check that rate isn't actually empty
//it's possible that some users have not selected a rate on the workorder
if (null==wt.TravelRateId || wt.TravelRateId == 0)
throw new System.ApplicationException($"ERROR: Workorder {w.Serial} has a Travel item with no rate selected\r\nThis is a serious problem for QBI and needs to be rectified before QBI can be used.\r\n");
if (!QBIntegration.Items.Any(z => z.AType == AyaType.TravelRate && z.ObjectId == wt.TravelRateId))
{
bReturn = false;
AddMisMatch(AyaTravelRateList.FirstOrDefault(z => z.Id == wt.TravelRateId).Name, (long)wt.TravelRateId, AyaType.TravelRate, MisMatchReason.NotLinkedToQB, MisMatches); ;
}
}
#endregion
#region Parts
foreach (WorkOrderItemPart wp in wi.Parts)
{
//If there's *any* parts then there is something to invoice
bSomethingToInvoice = true;
//Changed: 14-Nov-2006 to check that linked item id exists in qb
if (!QBI.Maps.Contains(wp.PartID) || QBItems.Rows.Find(QBI.Maps[wp.PartID].ForeignID) == null)
{
bReturn = false;
//Changed: 21-June-2006 to use display formatted name
AddMisMatch(AyaPartList[wp.PartID].DisplayName(Util.GlobalSettings.DefaultPartDisplayFormat), wp.PartID, AyaType.Part, MisMatchReason.NotLinkedToQB, MisMatches);
}
else
{
//check the price
if (!PriceOverrides.Contains(wp.ID))
{
decimal qbPrice = (decimal)QBItems.Rows.Find(QBI.Maps[wp.PartID].ForeignID)["Price"];
//------------DISCOUNT-----------------
string disco = "";
//Added:20-July-2006 to incorporate discounts on parts into qb invoice
decimal charge;
//Changed: 18-Nov-2006 CASE 158
//this is all wrong, it was multiplying price by quantity to calculate charge when it shouldn't
//removed quanty * price in next line to just price
charge = decimal.Round(wp.Price, 2, MidpointRounding.AwayFromZero);
charge = charge - (decimal.Round(charge * wp.Discount, 2, MidpointRounding.AwayFromZero));
if (wp.Discount != 0)
{
disco = " (Price " + wp.Price.ToString("c") + " discounted on workorder " + wp.Discount.ToString("p") + ") \r\n";
}
//-----------------------------
//It's a match, let's see if the price matches as well
if (charge != qbPrice)
{
bReturn = false;
AddMisMatch("WO: " + w.WorkorderService.ServiceNumber.ToString() + disco + " Part: " + AyaPartList[wp.PartID].DisplayName(Util.GlobalSettings.DefaultPartDisplayFormat),//Changed: 21-June-2006 to use display formatted name
wp.PartID, AyaType.Part, MisMatchReason.PriceDifferent, MisMatches, qbPrice, charge, wp.ID,
QBI.Maps[wp.PartID].ForeignID);
}
}
}
}
#endregion
#region Outside service charges
if (wi.HasOutsideService)
{
if (wi.OutsideService.RepairPrice != 0 || wi.OutsideService.ShippingPrice != 0)
{
bSomethingToInvoice = true;
//there is something billable, just need to make sure
//that there is a QB charge defined for outside service
if (QDat.OutsideServiceChargeAs == null ||
QDat.OutsideServiceChargeAs == "" ||
!QBItems.Rows.Contains(QDat.OutsideServiceChargeAs))
{
bReturn = false;
AddMisMatch("Outside service", Guid.Empty, AyaType.WorkOrderItemOutsideService, MisMatchReason.NotLinkedToQB, MisMatches);
}
}
}
#endregion
#region Workorder item loan charges
if (wi.HasLoans)
{
foreach (WorkOrderItemLoan wil in wi.Loans)
{
if (wil.Charges != 0)
{
//case 772
bSomethingToInvoice = true;
//there is something billable, just need to make sure
//that there is a QB charge defined for loaned item charges
if (QDat.WorkOrderItemLoanChargeAs == null ||
QDat.WorkOrderItemLoanChargeAs == "" ||
!QBItems.Rows.Contains(QDat.WorkOrderItemLoanChargeAs))
{
bReturn = false;
AddMisMatch("Workorder item loan", Guid.Empty, AyaType.WorkOrderItemLoan, MisMatchReason.NotLinkedToQB, MisMatches);
break;
}
}
}
}
#endregion
#region Workorder item misc expenses
if (wi.HasExpenses)
{
foreach (WorkOrderItemMiscExpense wie in wi.Expenses)
{
//}//workorder items loop
if (wie.ChargeToClient)
{
bSomethingToInvoice = true;
//there is something billable, just need to make sure
//that there is a QB charge defined for misc expense item charges
if (QDat.MiscExpenseChargeAs == null ||
QDat.MiscExpenseChargeAs == "" ||
!QBItems.Rows.Contains(QDat.MiscExpenseChargeAs))
{
bReturn = false;
AddMisMatch("Workorder item expense", Guid.Empty, AyaType.WorkOrderItemMiscExpense, MisMatchReason.NotLinkedToQB, MisMatches);
break;
////If there are no mismatches so far,
////maybe it's because it's got nothing to invoice?
//if (bReturn && !bSomethingToInvoice)
//{
// bReturn = false;
// AddMisMatch("WO: " + w.WorkorderService.ServiceNumber.ToString() + " - Nothing chargeable on it, will not be invoiced",
// Guid.Empty, RootObjectTypes.Nothing, MisMatchReason.NothingToInvoice, MisMatches);
}
}
}
}
#endregion
//}
}//workorder items loop
//If there are no mismatches so far,
//maybe it's because it's got nothing to invoice?
if (bReturn && !bSomethingToInvoice)
{
bReturn = false;
AddMisMatch("WO: " + w.WorkorderService.ServiceNumber.ToString() + " - Nothing chargeable on it, will not be invoiced",
Guid.Empty, AyaType.Nothing, MisMatchReason.NothingToInvoice, MisMatches);
}
return bReturn;
@@ -5910,13 +5908,13 @@ namespace AyaNovaQBI
private static void AddMisMatch(string Name, long ObjectId, AyaType ObjectType, MisMatchReason Reason, ArrayList Mismatches)
private static void AddMisMatch(string Name, long ObjectId, AyaType ObjectType, MisMatchReason Reason, List<MisMatch> Mismatches)
{
AddMisMatch(Name, ObjectId, ObjectType, Reason, Mismatches, 0m, 0m, 0, "");
}
private static void AddMisMatch(string Name, long ObjectId, AyaType ObjectType,
MisMatchReason Reason, ArrayList Mismatches, decimal QBPrice, decimal AyaPrice, long WorkOrderItemPartId, string QBListID)
MisMatchReason Reason, List<MisMatch> Mismatches, decimal QBPrice, decimal AyaPrice, long WorkOrderItemPartId, string QBListID)
{
bool bDuplicate = false;
//scan through list of existing mismatches,
@@ -5927,9 +5925,8 @@ namespace AyaNovaQBI
if (Reason == MisMatchReason.NotLinkedToQB)
{
foreach (object o in Mismatches)
{
MisMatch m = (MisMatch)o;
foreach (var m in Mismatches)
{
//Have to check ID and type here because for outside service
//and loans and misc expenses the id is always empty so type is
//the only way to differentiate