This commit is contained in:
2022-07-12 00:32:03 +00:00
parent 22afcee35f
commit 06b4cc86fa
4 changed files with 177 additions and 21 deletions

View File

@@ -257,6 +257,7 @@
<Compile Include="WorkOrderItemTaskCompletionType.cs" />
<Compile Include="WorkOrderItemTravel.cs" />
<Compile Include="WorkOrderItemUnit.cs" />
<Compile Include="WorkOrderState.cs" />
<Compile Include="WorkOrderStatus.cs" />
<Compile Include="SetQBImportInventoryAccounts.cs">
<SubType>Form</SubType>

View File

@@ -81,7 +81,7 @@ namespace AyaNovaQBI
var wip = w.Items.First(z => z.Id == mm.WorkOrderItemId).Parts.First(z => z.Id == mm.WorkOrderItemPartId);
wip.PriceOverride = mm.QBPrice;
await util.PostAsync("workorder", Newtonsoft.Json.JsonConvert.SerializeObject(w));
await PutAsync("workorder/items/parts", Newtonsoft.Json.JsonConvert.SerializeObject(wip));
}
break;
@@ -98,7 +98,7 @@ namespace AyaNovaQBI
var wip = w.Items.First(z => z.Id == mm.WorkOrderItemId).Parts.First(z => z.Id == mm.WorkOrderItemPartId);
long PartId = wip.PartId;
wip.PriceOverride = mm.QBPrice;
await util.PostAsync("workorder", Newtonsoft.Json.JsonConvert.SerializeObject(w));
await PutAsync("workorder/items/parts", Newtonsoft.Json.JsonConvert.SerializeObject(wip));
if (PartId != 0)
{

View File

@@ -0,0 +1,32 @@
using System;
namespace AyaNovaQBI
{
public class WorkOrderState
{
public long Id { get; set; }
public uint Concurrency { get; set; }
public long WorkOrderId { get; set; }
public long WorkOrderStatusId { get; set; }
public DateTime Created { get; set; } = DateTime.UtcNow;
public long UserId { get; set; }
public string UserViz { get; set; }
public string NameViz { get; set; }
public string ColorViz { get; set; }
public bool CompletedViz { get; set; }
public bool LockedViz { get; set; }
public uint NewWOConcurrency { get; set; }
}//eoc
}

View File

@@ -21,6 +21,9 @@ namespace AyaNovaQBI
{
get { return new Guid("{82CD3609-4601-4C1A-9633-7836F92D2D06}"); }
}
private const string ACCOUNTING_INTEGRATION_WORK_ORDER_STATUS_NAME = "z_ACCOUNTING_INTEGRATION_REQUIRED_STATUS";
public const string TEST_ROUTE = "notify/hello";
public const string API_BASE_ROUTE = "api/v8/";
private const int MAX_TRIES = 3;//max times to retry an api call before giving up
@@ -47,6 +50,9 @@ namespace AyaNovaQBI
internal static bool USE_INVENTORY { get; set; } = false;
internal static long ACCOUNTING_INTEGRATION_WORKORDER_STATUS_ID { get; set; } = 0;
public static void InitClient()
@@ -561,6 +567,8 @@ namespace AyaNovaQBI
return false;
LOG_AVAILABLE = true;
//PFC - get global setttings for use inventory and others await window.$gz.api.get("global-biz-setting/client");
r = await GetAsync("global-biz-setting/client");
USE_INVENTORY = r.ObjectResponse["data"]["useInventory"].Value<bool>();
@@ -608,6 +616,10 @@ namespace AyaNovaQBI
//PFC - verify integration mapped objects still exist in QB
if (!await ValidateQuickBooksHasMappedItems(initErrors))
return false;
if (!await EnsureAccountingIntegrationWorkOrderStatus(initErrors))
return false;
await IntegrationLog("PFC: QBI initialized and ready for use");
return true;
}
@@ -678,6 +690,88 @@ namespace AyaNovaQBI
}
}
/// <summary>
/// Ensure existance of special work order status for accounting integration modification purposes
/// </summary>
/// <param name="initErrors"></param>
/// <returns></returns>
public static async Task<bool> EnsureAccountingIntegrationWorkOrderStatus(StringBuilder initErrors)
{
/*
* var a = await util.GetAsync($"workorder/{mm.WorkOrderId}");
WorkOrder w = a.ObjectResponse["data"].ToObject<WorkOrder>();
if (w == null)
throw new Exception($"FixInvoiceProblems:CHANGEAYA:PRICE: WorkOrder with id {mm.WorkOrderId} was not found in AyaNova and may have just been deleted.\r\nUnable to update wo.");
var wip = w.Items.First(z => z.Id == mm.WorkOrderItemId).Parts.First(z => z.Id == mm.WorkOrderItemPartId);
long PartId = wip.PartId;
wip.PriceOverride = mm.QBPrice;
await PutAsync("workorder/items/parts", Newtonsoft.Json.JsonConvert.SerializeObject(wip));
CREATE STATUS: {"data":{"id":0, "name":"z_ACCOUNTING_INTEGRATION_REQUIRED_STATUS","active":true,
"notes":"Special status required for Accounting integration applications to enable modifying locked work orders.",
"color":"#000000FF","selectRoles":64,"removeRoles":64,"completed":false,"locked":false}}
POST STATE TO WO: {"workOrderId":557,"workOrderStatusId":8,"userId":5,"userViz":"Marian Green - Service","created":"2022-07-11T22:54:11.528Z"}
*/
//see if we already have an integration status set
WorkOrderStatus AccountingStatus = _woStatuslist.FirstOrDefault(z => z.Name == ACCOUNTING_INTEGRATION_WORK_ORDER_STATUS_NAME);
//validate accounting status
if (AccountingStatus != null)
{
ACCOUNTING_INTEGRATION_WORKORDER_STATUS_ID = AccountingStatus.Id;
bool hasError = false;
if (!AccountingStatus.SelectRoles.HasFlag(AuthorizationRoles.Accounting))
{
hasError = true;
initErrors.AppendLine($"Work order Status \"{AccountingStatus.Name}\" SELECT Roles must include Accounting Role");
}
if (!AccountingStatus.RemoveRoles.HasFlag(AuthorizationRoles.Accounting))
{
hasError = true;
initErrors.AppendLine($"Work order Status \"{AccountingStatus.Name}\" REMOVE Roles must include Accounting Role");
}
if (!AccountingStatus.Active)
{
hasError = true;
initErrors.AppendLine($"Work order Status \"{AccountingStatus.Name}\" must be set to Active=true");
}
return !hasError;
}
//Create accounting status
ApiResponse r = null;
try
{
AccountingStatus.Name = ACCOUNTING_INTEGRATION_WORK_ORDER_STATUS_NAME;
AccountingStatus.Active = true;
AccountingStatus.Completed = false;
AccountingStatus.Locked = false;
AccountingStatus.SelectRoles = AuthorizationRoles.Accounting;
AccountingStatus.RemoveRoles = AuthorizationRoles.Accounting;
AccountingStatus.Notes = "DO NOT MODIFY - Special status required for Accounting integration applications to modify locked Work orders.";
AccountingStatus.Color = "#6D3C2176";//ugly transparentish brown
r = await PostAsync($"work-order-status", Newtonsoft.Json.JsonConvert.SerializeObject(AccountingStatus));
ACCOUNTING_INTEGRATION_WORKORDER_STATUS_ID = IdFromResponse(r);
return true;
}
catch (Exception ex)
{
initErrors.AppendLine($"Error creating required Work order Status \"{AccountingStatus.Name}\"");
initErrors.AppendLine(ex.Message);
initErrors.AppendLine(r.CompactResponse);
return false;
}
}
/// <summary>
/// Ensure mapped items still existing in QuickBooks
/// </summary>
@@ -5659,8 +5753,6 @@ namespace AyaNovaQBI
#endregion export to quickbooks
#region Workorder mismatch scanning
public enum MisMatchReason
@@ -6117,7 +6209,6 @@ namespace AyaNovaQBI
if (w == null)
throw new Exception($"util.Invoice: WorkOrder with record id {SelectedWorkOrderId} was not found in AyaNova and may have just been deleted.\r\nUnable to invoice this wo.");
var OrderedWorkOrderItems = w.Items.OrderBy(z => z.Sequence).ToList();
if (bFirstLoop)
@@ -6402,7 +6493,7 @@ namespace AyaNovaQBI
if (s.IndexOf("~SERVICE_START~") != -1)
{
s = s.Replace("~SERVICE_START~",DateToLocalString(wl.ServiceStartDate));
s = s.Replace("~SERVICE_START~", DateToLocalString(wl.ServiceStartDate));
}
if (s.IndexOf("~SERVICE_STOP~") != -1)
@@ -6578,12 +6669,12 @@ namespace AyaNovaQBI
if (s.IndexOf("~ITEM~") != -1)
{
s = s.Replace("~ITEM~",l.LoanUnitViz);
s = s.Replace("~ITEM~", l.LoanUnitViz);
}
if (s.IndexOf("~LOANED~") != -1)
{
s = s.Replace("~LOANED~",DateToLocalString(l.OutDate));
s = s.Replace("~LOANED~", DateToLocalString(l.OutDate));
}
if (s.IndexOf("~LOAN_RETURNED~") != -1)
@@ -6655,22 +6746,54 @@ namespace AyaNovaQBI
//Loop through all workorders again and set their invoice number, status and close them
//Loop through alworkorders
foreach (object o in selectedWorkOrderIdList)
{
Workorder w = Workorder.GetItem((Guid)o);
if (QDat.PostWOStatus != Guid.Empty)
foreach (long WorkOrderId in selectedWorkOrderIdList)
{
/*
* var a = await util.GetAsync($"workorder/{mm.WorkOrderId}");
WorkOrder w = a.ObjectResponse["data"].ToObject<WorkOrder>();
if (w == null)
throw new Exception($"FixInvoiceProblems:CHANGEAYA:PRICE: WorkOrder with id {mm.WorkOrderId} was not found in AyaNova and may have just been deleted.\r\nUnable to update wo.");
w.WorkorderService.WorkorderStatusID = QDat.PostWOStatus;
var wip = w.Items.First(z => z.Id == mm.WorkOrderItemId).Parts.First(z => z.Id == mm.WorkOrderItemPartId);
long PartId = wip.PartId;
wip.PriceOverride = mm.QBPrice;
await PutAsync("workorder/items/parts", Newtonsoft.Json.JsonConvert.SerializeObject(wip));
CREATE STATUS: {"data":{"id":0, "name":"zACCOUNTING_INTEGRATION_REQUIRED_STATUS","active":true,"notes":"Special status required for Accounting integration applications to enable modifying locked work orders.","color":"#000000FF","selectRoles":64,"removeRoles":64,"completed":false,"locked":false}}
POST STATE TO WO: {"workOrderId":557,"workOrderStatusId":8,"userId":5,"userViz":"Marian Green - Service","created":"2022-07-11T22:54:11.528Z"}
*/
//First, set status to editable one and also to show that QBI made changes
var a = await GetAsync($"workorder/{WorkOrderId}");
WorkOrder w = a.ObjectResponse["data"].ToObject<WorkOrder>();
if (w != null)
{
long? StatusOfWorkOrderBeforeModifications = w.LastStatusId;
//set work order state to accounting status
var newState = (await PostAsync("workorder/states", Newtonsoft.Json.JsonConvert.SerializeObject(new WorkOrderState { WorkOrderId = w.Id, UserId = 0, WorkOrderStatusId = ACCOUNTING_INTEGRATION_WORKORDER_STATUS_ID }))).ObjectResponse["data"].ToObject<WorkOrderState>();
w.Concurrency = newState.NewWOConcurrency;
//set invoice number
w.InvoiceNumber = InvoiceNumber;
//only allowed to put header not rest of wo
w.Items.Clear();
await PutAsync("workorder", Newtonsoft.Json.JsonConvert.SerializeObject(w));
if (QDat.PostWOStatus != 0)
{
await PostAsync("workorder/states", Newtonsoft.Json.JsonConvert.SerializeObject(new WorkOrderState { WorkOrderId = w.Id, UserId = 0, WorkOrderStatusId = QDat.PostWOStatus }));
}
else
{
//put it back to the status it was before we modified it as user has selected no status change
if (StatusOfWorkOrderBeforeModifications != null)
await PostAsync("workorder/states", Newtonsoft.Json.JsonConvert.SerializeObject(new WorkOrderState { WorkOrderId = w.Id, UserId = 0, WorkOrderStatusId = (long)StatusOfWorkOrderBeforeModifications }));
}
w.WorkorderService.InvoiceNumber = InvoiceNumber;
//Case 7
if (QDat.AutoClose)
w.Closed = true;
w.Save();
}
}