|
|
|
|
@@ -684,42 +684,6 @@ namespace AyaNova.Biz
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
|
|
todo: quote status list first, it's a table of created items, keep properties from v7 but add the following properties:
|
|
|
|
|
SelectRoles - who can select the status (still shows if they can't select but that's the current status, like active does)
|
|
|
|
|
This is best handled at the client. It prefetches all the status out of the normal picklist process, more like how other things are separately handled now without a picklist
|
|
|
|
|
client then knows if a status is available or not and can process to only present available ones
|
|
|
|
|
#### Server can use a biz rule to ensure that it can't be circumvented
|
|
|
|
|
UI defaults to any role
|
|
|
|
|
DeselectRoles - who can unset this status (important for process control)
|
|
|
|
|
UI defaults to any role
|
|
|
|
|
CompletedStatus bool - this is a final status indicating all work on the quote is completed, affects notification etc
|
|
|
|
|
UI defaults to false but when set to true auto sets lockworkorder to true (but user can just unset lockworkorder)
|
|
|
|
|
LockWorkorder - this status is considered read only and the quote is locked
|
|
|
|
|
Just a read only thing, can just change status to "unlock" it
|
|
|
|
|
to support states where no one should work on a wo for whatever reason but it's not necessarily completed
|
|
|
|
|
e.g. "Hold for inspection", "On hold" generally etc
|
|
|
|
|
*/
|
|
|
|
|
// //Name required
|
|
|
|
|
// if (string.IsNullOrWhiteSpace(proposedObj.Name))
|
|
|
|
|
// AddError(ApiErrorCode.VALIDATION_REQUIRED, "Name");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// //If name is otherwise OK, check that name is unique
|
|
|
|
|
// if (!PropertyHasErrors("Name"))
|
|
|
|
|
// {
|
|
|
|
|
// //Use Any command is efficient way to check existance, it doesn't return the record, just a true or false
|
|
|
|
|
// if (await ct.Quote.AnyAsync(z => z.Name == proposedObj.Name && z.Id != proposedObj.Id))
|
|
|
|
|
// {
|
|
|
|
|
// AddError(ApiErrorCode.VALIDATION_NOT_UNIQUE, "Name");
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//Any form customizations to validate?
|
|
|
|
|
var FormCustomization = await ct.FormCustom.AsNoTracking().SingleOrDefaultAsync(z => z.FormKey == AyaType.Quote.ToString());
|
|
|
|
|
if (FormCustomization != null)
|
|
|
|
|
@@ -732,11 +696,9 @@ namespace AyaNova.Biz
|
|
|
|
|
//validate custom fields
|
|
|
|
|
CustomFieldsValidator.Validate(this, FormCustomization, proposedObj.CustomFields);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private async Task QuoteValidateCanDelete(Quote dbObject)
|
|
|
|
|
{
|
|
|
|
|
//Check restricted role preventing create
|
|
|
|
|
@@ -747,35 +709,9 @@ namespace AyaNova.Biz
|
|
|
|
|
}
|
|
|
|
|
if (await ct.WorkOrder.AnyAsync(m => m.FromQuoteId == dbObject.Id))
|
|
|
|
|
AddError(ApiErrorCode.VALIDATION_REFERENTIAL_INTEGRITY, "generalerror", await Translate("Quote"));
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//############### NOTIFICATION TODO
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
|
|
todo: quote notifications remove #30 and #32 as redundant
|
|
|
|
|
WorkorderStatusChange = 4,//* Workorder object, any *change* of status including from no status (new) to a specific conditional status ID value
|
|
|
|
|
|
|
|
|
|
WorkorderStatusAge = 24,//* Workorder object Created / Updated, conditional on exact status selected IdValue, Tags conditional, advance notice can be set
|
|
|
|
|
|
|
|
|
|
//THESE TWO ARE REDUNDANT:
|
|
|
|
|
|
|
|
|
|
this is actually workorderstatuschange because can just pick any status under workorderstatuschange to be notified about
|
|
|
|
|
WorkorderCompleted = 30, //*travel work order is set to any status that is flagged as a "Completed" type of status. Customer & User
|
|
|
|
|
|
|
|
|
|
//This one could be accomplished with WorkorderStatusAge, just pick a Completed status and set a time frame and wala!
|
|
|
|
|
WorkorderCompletedFollowUp = 32, //* travel quote closed status follow up again after this many TIMESPAN
|
|
|
|
|
|
|
|
|
|
todo: CHANGE WorkorderCompletedStatusOverdue = 15,//* Workorder object not set to a "Completed" flagged quote status type in selected time span from creation of quote
|
|
|
|
|
Change this to a new type that is based on so many days *without* being set to a particular status
|
|
|
|
|
but first check if tied to contract response time stuff, how that's handled
|
|
|
|
|
that's closeby date in v7 but isn't that deprecated now without a "close"?
|
|
|
|
|
maybe I do need the Completed status bool thing above
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// GET PARTIAL WORKORDER FOR REPORTING
|
|
|
|
|
// (returns quote consisting only of the path from child or grandchild up to header populated
|
|
|
|
|
@@ -883,64 +819,6 @@ namespace AyaNova.Biz
|
|
|
|
|
foreach (long batchId in batch)
|
|
|
|
|
batchResults.Add(await QuoteGetPartialAsync(dataListSelectedRequest.AType, batchId, dataListSelectedRequest.IncludeWoItemDescendants, true));
|
|
|
|
|
|
|
|
|
|
#region unnecessary shit removed
|
|
|
|
|
//This is unnecessary because the re-ordering bit is only needed when the records are fetched in batches directly from the sql server as they
|
|
|
|
|
//return in db natural order and need to be put back into the same order as the ID List
|
|
|
|
|
//Here in the quote however, this code is fetching individually one at a time so they are always going to be in the correct order so this re-ordering is unnecessary
|
|
|
|
|
//I'm keeping this here for future reference when I ineveitably wonder what the hell is happening here :)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//order the results back into original
|
|
|
|
|
//IEnumerable<Quote> orderedList = null;
|
|
|
|
|
|
|
|
|
|
//TODO: WHAT IS THIS BATCH RESULT ORDERING CODE REALLY DOING AND CAN IT BE REMOVED / CHANGED????
|
|
|
|
|
//isn't it alredy working in order? If not maybe simply reversed so reverse it again before querying above or...??
|
|
|
|
|
|
|
|
|
|
//todo: can't assume the grandchild item is index 0 anymore as we might have multiple of them if includedescendants is true
|
|
|
|
|
//so need to find index first then do this
|
|
|
|
|
// switch (dataListSelectedRequest.AType)
|
|
|
|
|
// {
|
|
|
|
|
// case AyaType.Quote:
|
|
|
|
|
// orderedList = from id in batch join z in batchResults on id equals z.Id select z;
|
|
|
|
|
// break;
|
|
|
|
|
// case AyaType.QuoteItem:
|
|
|
|
|
// orderedList = from id in batch join z in batchResults on id equals z.Items[0].Id select z;
|
|
|
|
|
// break;
|
|
|
|
|
// case AyaType.QuoteItemExpense:
|
|
|
|
|
// orderedList = from id in batch join z in batchResults on id equals z.Items[0].Expenses[0].Id select z;
|
|
|
|
|
// break;
|
|
|
|
|
// case AyaType.QuoteItemLabor:
|
|
|
|
|
// orderedList = from id in batch join z in batchResults on id equals z.Items[0].Labors[0].Id select z;
|
|
|
|
|
// break;
|
|
|
|
|
// case AyaType.QuoteItemLoan:
|
|
|
|
|
// orderedList = from id in batch join z in batchResults on id equals z.Items[0].Loans[0].Id select z;
|
|
|
|
|
// break;
|
|
|
|
|
// case AyaType.QuoteItemPart:
|
|
|
|
|
// orderedList = from id in batch join z in batchResults on id equals z.Items[0].Parts[0].Id select z;
|
|
|
|
|
// break;
|
|
|
|
|
// case AyaType.QuoteItemPartRequest:
|
|
|
|
|
// orderedList = from id in batch join z in batchResults on id equals z.Items[0].PartRequests[0].Id select z;
|
|
|
|
|
// break;
|
|
|
|
|
// case AyaType.QuoteItemScheduledUser:
|
|
|
|
|
// orderedList = from id in batch join z in batchResults on id equals z.Items[0].ScheduledUsers[0].Id select z;
|
|
|
|
|
// break;
|
|
|
|
|
// case AyaType.QuoteItemTask:
|
|
|
|
|
// orderedList = from id in batch join z in batchResults on id equals z.Items[0].Tasks[0].Id select z;
|
|
|
|
|
// break;
|
|
|
|
|
// case AyaType.QuoteItemTravel:
|
|
|
|
|
// orderedList = from id in batch join z in batchResults on id equals z.Items[0].Travels[0].Id select z;
|
|
|
|
|
// break;
|
|
|
|
|
// case AyaType.QuoteItemOutsideService:
|
|
|
|
|
// orderedList = from id in batch join z in batchResults on id equals z.Items[0].OutsideServices[0].Id select z;
|
|
|
|
|
// break;
|
|
|
|
|
// case AyaType.QuoteItemUnit:
|
|
|
|
|
// orderedList = from id in batch join z in batchResults on id equals z.Items[0].Units[0].Id select z;
|
|
|
|
|
// break;
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
//foreach (Quote w in orderedList)
|
|
|
|
|
#endregion unnecessary shit
|
|
|
|
|
|
|
|
|
|
foreach (Quote w in batchResults)
|
|
|
|
|
{
|
|
|
|
|
var jo = JObject.FromObject(w);
|
|
|
|
|
@@ -1159,7 +1037,7 @@ namespace AyaNova.Biz
|
|
|
|
|
bool isNew = currentObj == null;
|
|
|
|
|
|
|
|
|
|
Quote oProposed = (Quote)proposedObj;
|
|
|
|
|
proposedObj.Name = oProposed.Serial.ToString();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//STANDARD EVENTS FOR ALL OBJECTS
|
|
|
|
|
await NotifyEventHelper.ProcessStandardObjectEvents(ayaEvent, proposedObj, ct);//Note: will properly handle all delete events and event removal if deleted
|
|
|
|
|
|