This commit is contained in:
2021-07-29 15:20:39 +00:00
parent 7bf025144a
commit 5af58d63e6
3 changed files with 533 additions and 437 deletions

View File

@@ -206,6 +206,9 @@ namespace AyaNova.Biz
await CoreJobNotify.DoWorkAsync(); await CoreJobNotify.DoWorkAsync();
await CoreNotificationSweeper.DoWorkAsync(); await CoreNotificationSweeper.DoWorkAsync();
//PM GENERATION
await CoreJobPMGenerate.DoWorkAsync();
//JOB SWEEPER / AND USER COUNT CHECK //JOB SWEEPER / AND USER COUNT CHECK
await CoreJobSweeper.DoWorkAsync(); await CoreJobSweeper.DoWorkAsync();

View File

@@ -13,488 +13,488 @@ using System.Collections.Generic;
namespace AyaNova.Biz namespace AyaNova.Biz
{ {
#region v7 code for Generate service workorder from PM #region v7 code for Generate service workorder from PM
/* /// <summary> /* /// <summary>
/// Generates a service workorder from a PM type Workorder /// Generates a service workorder from a PM type Workorder
/// </summary> /// </summary>
/// <param name="SourceWorkorderID">ID of PM</param> /// <param name="SourceWorkorderID">ID of PM</param>
/// <returns>A new service workorder</returns> /// <returns>A new service workorder</returns>
public static Workorder NewServiceWorkorderFromPM(Guid SourceWorkorderID) public static Workorder NewServiceWorkorderFromPM(Guid SourceWorkorderID)
{ {
//Fetch the source workorder and verify it's a PM //Fetch the source workorder and verify it's a PM
Workorder source = Workorder.GetItemNoMRU(SourceWorkorderID); Workorder source = Workorder.GetItemNoMRU(SourceWorkorderID);
if (source.WorkorderType != WorkorderTypes.PreventiveMaintenance) if (source.WorkorderType != WorkorderTypes.PreventiveMaintenance)
throw new NotSupportedException(LocalizedTextTable.GetLocalizedTextDirect("Workorder.Label.Error.SourceInvalidType")); throw new NotSupportedException(LocalizedTextTable.GetLocalizedTextDirect("Workorder.Label.Error.SourceInvalidType"));
//if it's inactive then there is nothing to Process //if it's inactive then there is nothing to Process
//this is a backstop, the list the pm is being generated off of //this is a backstop, the list the pm is being generated off of
//should have already selected only active items that have not reached their //should have already selected only active items that have not reached their
//expiry date //expiry date
if (source.WorkorderPreventiveMaintenance.Active == false) if (source.WorkorderPreventiveMaintenance.Active == false)
{ {
throw new System.ApplicationException("NewServiceWorkorderFromPM: source PM workorder is not active"); throw new System.ApplicationException("NewServiceWorkorderFromPM: source PM workorder is not active");
} }
if (source.WorkorderPreventiveMaintenance.StopGeneratingDate != System.DBNull.Value && if (source.WorkorderPreventiveMaintenance.StopGeneratingDate != System.DBNull.Value &&
source.WorkorderPreventiveMaintenance.dtStopGeneratingDate < DBUtil.CurrentWorkingDateTime) source.WorkorderPreventiveMaintenance.dtStopGeneratingDate < DBUtil.CurrentWorkingDateTime)
{ {
throw new System.ApplicationException("NewServiceWorkorderFromPM: source PM workorder is past StopGeneratingDate"); throw new System.ApplicationException("NewServiceWorkorderFromPM: source PM workorder is past StopGeneratingDate");
} }
//Ok, so far so good, create the new one //Ok, so far so good, create the new one
bool bUseInventory = AyaBizUtils.GlobalSettings.UseInventory; bool bUseInventory = AyaBizUtils.GlobalSettings.UseInventory;
//case 1387 //case 1387
Workorder dest = Workorder.NewItem(WorkorderTypes.Service); Workorder dest = Workorder.NewItem(WorkorderTypes.Service);
////NOTE: THIS DOESN'T CALL THE SHARED NEW ITEM METHOD ////NOTE: THIS DOESN'T CALL THE SHARED NEW ITEM METHOD
//Workorder dest = new Workorder(); //Workorder dest = new Workorder();
//dest.WorkorderType=WorkorderTypes.Service; //dest.WorkorderType=WorkorderTypes.Service;
//dest.mService=WorkorderService.NewItem(dest); //dest.mService=WorkorderService.NewItem(dest);
#region copy workorder data #region copy workorder data
//WORKORDER HEADER //WORKORDER HEADER
dest.ClientID = source.ClientID; dest.ClientID = source.ClientID;
dest.CustomerContactName = source.CustomerContactName; dest.CustomerContactName = source.CustomerContactName;
dest.CustomerReferenceNumber = source.CustomerReferenceNumber; dest.CustomerReferenceNumber = source.CustomerReferenceNumber;
dest.mFromPMID = source.WorkorderPreventiveMaintenance.ID; dest.mFromPMID = source.WorkorderPreventiveMaintenance.ID;
dest.InternalReferenceNumber = source.InternalReferenceNumber; dest.InternalReferenceNumber = source.InternalReferenceNumber;
dest.Onsite = source.Onsite; dest.Onsite = source.Onsite;
dest.ProjectID = source.ProjectID; dest.ProjectID = source.ProjectID;
//dest.RegionID=source.RegionID; //dest.RegionID=source.RegionID;
dest.Summary = source.Summary; dest.Summary = source.Summary;
dest.WorkorderCategoryID = source.WorkorderCategoryID; dest.WorkorderCategoryID = source.WorkorderCategoryID;
//PM SPECIFIC //PM SPECIFIC
dest.WorkorderService.WorkorderStatusID = source.WorkorderPreventiveMaintenance.WorkorderStatusID; dest.WorkorderService.WorkorderStatusID = source.WorkorderPreventiveMaintenance.WorkorderStatusID;
//Date stuff (note that date is assumed to have been advanced the last time a workorder was //Date stuff (note that date is assumed to have been advanced the last time a workorder was
//generated off the pm (see bottom of this method for that)) //generated off the pm (see bottom of this method for that))
dest.WorkorderService.ServiceDate = source.WorkorderPreventiveMaintenance.NextServiceDate; dest.WorkorderService.ServiceDate = source.WorkorderPreventiveMaintenance.NextServiceDate;
//WORKORDERITEMS //WORKORDERITEMS
foreach (WorkorderItem wisource in source.WorkorderItems) foreach (WorkorderItem wisource in source.WorkorderItems)
{ {
WorkorderItem widest = dest.WorkorderItems.Add(dest); WorkorderItem widest = dest.WorkorderItems.Add(dest);
widest.Custom0 = wisource.Custom0; widest.Custom0 = wisource.Custom0;
widest.Custom1 = wisource.Custom1; widest.Custom1 = wisource.Custom1;
widest.Custom2 = wisource.Custom2; widest.Custom2 = wisource.Custom2;
widest.Custom3 = wisource.Custom3; widest.Custom3 = wisource.Custom3;
widest.Custom4 = wisource.Custom4; widest.Custom4 = wisource.Custom4;
widest.Custom5 = wisource.Custom5; widest.Custom5 = wisource.Custom5;
widest.Custom6 = wisource.Custom6; widest.Custom6 = wisource.Custom6;
widest.Custom7 = wisource.Custom7; widest.Custom7 = wisource.Custom7;
widest.Custom8 = wisource.Custom8; widest.Custom8 = wisource.Custom8;
widest.Custom9 = wisource.Custom9; widest.Custom9 = wisource.Custom9;
widest.PriorityID = wisource.PriorityID; widest.PriorityID = wisource.PriorityID;
widest.RequestDate = wisource.RequestDate; widest.RequestDate = wisource.RequestDate;
widest.Summary = wisource.Summary; widest.Summary = wisource.Summary;
widest.TechNotes = wisource.TechNotes; widest.TechNotes = wisource.TechNotes;
widest.TypeID = wisource.TypeID; widest.TypeID = wisource.TypeID;
widest.UnitID = wisource.UnitID; widest.UnitID = wisource.UnitID;
widest.WarrantyService = wisource.WarrantyService; widest.WarrantyService = wisource.WarrantyService;
widest.WorkorderItemUnitServiceTypeID = wisource.WorkorderItemUnitServiceTypeID; widest.WorkorderItemUnitServiceTypeID = wisource.WorkorderItemUnitServiceTypeID;
widest.WorkorderStatusID = wisource.WorkorderStatusID; widest.WorkorderStatusID = wisource.WorkorderStatusID;
//PARTS //PARTS
foreach (WorkorderItemPart partsource in wisource.Parts) foreach (WorkorderItemPart partsource in wisource.Parts)
{ {
WorkorderItemPart partdest = widest.Parts.Add(widest); WorkorderItemPart partdest = widest.Parts.Add(widest);
partdest.Cost = partsource.Cost; partdest.Cost = partsource.Cost;
partdest.Description = partsource.Description; partdest.Description = partsource.Description;
partdest.Discount = partsource.Discount; partdest.Discount = partsource.Discount;
partdest.DiscountType = partsource.DiscountType; partdest.DiscountType = partsource.DiscountType;
partdest.PartID = partsource.PartID; partdest.PartID = partsource.PartID;
partdest.PartWarehouseID = partsource.PartWarehouseID; partdest.PartWarehouseID = partsource.PartWarehouseID;
partdest.Price = partsource.Price; partdest.Price = partsource.Price;
if (bUseInventory) if (bUseInventory)
{ {
partdest.QuantityReserved = partsource.Quantity; partdest.QuantityReserved = partsource.Quantity;
partdest.Quantity = 0; partdest.Quantity = 0;
} }
else else
partdest.Quantity = partsource.Quantity; partdest.Quantity = partsource.Quantity;
partdest.TaxPartSaleID = partsource.TaxPartSaleID; partdest.TaxPartSaleID = partsource.TaxPartSaleID;
} }
//********************************************************** //**********************************************************
//Part requests would be here if copying a service workorder //Part requests would be here if copying a service workorder
//********************************************************** //**********************************************************
//SCHEDULED USERS //SCHEDULED USERS
foreach (WorkorderItemScheduledUser usersource in wisource.ScheduledUsers) foreach (WorkorderItemScheduledUser usersource in wisource.ScheduledUsers)
{ {
WorkorderItemScheduledUser userdest = widest.ScheduledUsers.Add(widest); WorkorderItemScheduledUser userdest = widest.ScheduledUsers.Add(widest);
userdest.EstimatedQuantity = usersource.EstimatedQuantity; userdest.EstimatedQuantity = usersource.EstimatedQuantity;
userdest.ServiceRateID = usersource.ServiceRateID; userdest.ServiceRateID = usersource.ServiceRateID;
userdest.StartDate = usersource.StartDate; userdest.StartDate = usersource.StartDate;
userdest.StopDate = usersource.StopDate; userdest.StopDate = usersource.StopDate;
userdest.UserID = usersource.UserID; userdest.UserID = usersource.UserID;
} }
//LABOR //LABOR
foreach (WorkorderItemLabor laborsource in wisource.Labors) foreach (WorkorderItemLabor laborsource in wisource.Labors)
{ {
WorkorderItemLabor labordest = widest.Labors.Add(widest); WorkorderItemLabor labordest = widest.Labors.Add(widest);
labordest.NoChargeQuantity = laborsource.NoChargeQuantity; labordest.NoChargeQuantity = laborsource.NoChargeQuantity;
labordest.ServiceDetails = laborsource.ServiceDetails; labordest.ServiceDetails = laborsource.ServiceDetails;
labordest.ServiceRateID = laborsource.ServiceRateID; labordest.ServiceRateID = laborsource.ServiceRateID;
labordest.ServiceRateQuantity = laborsource.ServiceRateQuantity; labordest.ServiceRateQuantity = laborsource.ServiceRateQuantity;
labordest.ServiceStartDate = laborsource.ServiceStartDate; labordest.ServiceStartDate = laborsource.ServiceStartDate;
labordest.ServiceStopDate = laborsource.ServiceStopDate; labordest.ServiceStopDate = laborsource.ServiceStopDate;
labordest.TaxRateSaleID = laborsource.TaxRateSaleID; labordest.TaxRateSaleID = laborsource.TaxRateSaleID;
labordest.UserID = laborsource.UserID; labordest.UserID = laborsource.UserID;
} }
//********************************************************** //**********************************************************
//Expenses would be here if copying a service workorder //Expenses would be here if copying a service workorder
//********************************************************** //**********************************************************
//********************************************************** //**********************************************************
//Loans would be here if copying a service workorder //Loans would be here if copying a service workorder
//********************************************************** //**********************************************************
//TRAVEL //TRAVEL
foreach (WorkorderItemTravel travelsource in wisource.Travels) foreach (WorkorderItemTravel travelsource in wisource.Travels)
{ {
WorkorderItemTravel traveldest = widest.Travels.Add(widest); WorkorderItemTravel traveldest = widest.Travels.Add(widest);
traveldest.TravelDetails = travelsource.TravelDetails; traveldest.TravelDetails = travelsource.TravelDetails;
traveldest.TravelRateID = travelsource.TravelRateID; traveldest.TravelRateID = travelsource.TravelRateID;
traveldest.TravelRateQuantity = travelsource.TravelRateQuantity; traveldest.TravelRateQuantity = travelsource.TravelRateQuantity;
traveldest.TravelStartDate = travelsource.TravelStartDate; traveldest.TravelStartDate = travelsource.TravelStartDate;
traveldest.TravelStopDate = travelsource.TravelStopDate; traveldest.TravelStopDate = travelsource.TravelStopDate;
traveldest.TaxRateSaleID = travelsource.TaxRateSaleID; traveldest.TaxRateSaleID = travelsource.TaxRateSaleID;
traveldest.UserID = travelsource.UserID; traveldest.UserID = travelsource.UserID;
traveldest.Distance = travelsource.Distance; traveldest.Distance = travelsource.Distance;
traveldest.Notes = travelsource.Notes; traveldest.Notes = travelsource.Notes;
traveldest.NoChargeQuantity = travelsource.NoChargeQuantity; traveldest.NoChargeQuantity = travelsource.NoChargeQuantity;
} }
//TASKS //TASKS
foreach (WorkorderItemTask tasksource in wisource.Tasks) foreach (WorkorderItemTask tasksource in wisource.Tasks)
{ {
WorkorderItemTask taskdest = widest.Tasks.Add(widest); WorkorderItemTask taskdest = widest.Tasks.Add(widest);
taskdest.TaskGroupID = tasksource.TaskGroupID; taskdest.TaskGroupID = tasksource.TaskGroupID;
taskdest.TaskID = tasksource.TaskID; taskdest.TaskID = tasksource.TaskID;
} }
//********************************************************** //**********************************************************
//Outside service would be here if copying a service workorder //Outside service would be here if copying a service workorder
//********************************************************** //**********************************************************
}//foreach workorderitem loop }//foreach workorderitem loop
//case 1387 //case 1387
//Delete the auto-created dummy workorder item //Delete the auto-created dummy workorder item
//if there are more than it present //if there are more than it present
if (dest.WorkorderItems.Count > 1) if (dest.WorkorderItems.Count > 1)
dest.WorkorderItems.RemoveAt(0); dest.WorkorderItems.RemoveAt(0);
#endregion copy workorder data #endregion copy workorder data
//Now save it to ensure it was created properly so //Now save it to ensure it was created properly so
//that we know it's now safe to advance the next service date and all others //that we know it's now safe to advance the next service date and all others
//case 868 previously didn't set dest to result of save causing it to be a copy //case 868 previously didn't set dest to result of save causing it to be a copy
dest = (Workorder)dest.Save(); dest = (Workorder)dest.Save();
#region Calculate reschedule dates #region Calculate reschedule dates
//Get the current next service date for calcs //Get the current next service date for calcs
DateTime dtNext = GetDateFromSpanAndUnit(source.WorkorderPreventiveMaintenance.dtNextServiceDate, DateTime dtNext = GetDateFromSpanAndUnit(source.WorkorderPreventiveMaintenance.dtNextServiceDate,
source.WorkorderPreventiveMaintenance.GenerateSpanUnit, source.WorkorderPreventiveMaintenance.GenerateSpanUnit,
source.WorkorderPreventiveMaintenance.GenerateSpan); source.WorkorderPreventiveMaintenance.GenerateSpan);
//Get to the desired day of the week if necessary... //Get to the desired day of the week if necessary...
if (source.mWorkorderPreventiveMaintenance.DayOfTheWeek != AyaDayOfWeek.AnyDayOfWeek) if (source.mWorkorderPreventiveMaintenance.DayOfTheWeek != AyaDayOfWeek.AnyDayOfWeek)
{ {
DayOfWeek desired = AyaToSystemDayOfWeek(source.mWorkorderPreventiveMaintenance.DayOfTheWeek); DayOfWeek desired = AyaToSystemDayOfWeek(source.mWorkorderPreventiveMaintenance.DayOfTheWeek);
while (dtNext.DayOfWeek != desired) while (dtNext.DayOfWeek != desired)
{ {
dtNext = dtNext.AddDays(1); dtNext = dtNext.AddDays(1);
} }
} }
//Get the time span to add to all the other relevant dates on teh workorder to match //Get the time span to add to all the other relevant dates on teh workorder to match
//the amount the next service date has been advanced //the amount the next service date has been advanced
System.TimeSpan tsToNext = dtNext - source.WorkorderPreventiveMaintenance.dtNextServiceDate; System.TimeSpan tsToNext = dtNext - source.WorkorderPreventiveMaintenance.dtNextServiceDate;
#endregion #endregion
//Will the next workorder service date fall after the //Will the next workorder service date fall after the
//stop generating date? //stop generating date?
if (source.WorkorderPreventiveMaintenance.StopGeneratingDate != System.DBNull.Value && if (source.WorkorderPreventiveMaintenance.StopGeneratingDate != System.DBNull.Value &&
source.WorkorderPreventiveMaintenance.dtStopGeneratingDate < dtNext) source.WorkorderPreventiveMaintenance.dtStopGeneratingDate < dtNext)
{ {
//Yes it will, so set it to inactive and bail out //Yes it will, so set it to inactive and bail out
source.WorkorderPreventiveMaintenance.Active = false; source.WorkorderPreventiveMaintenance.Active = false;
source.Save(); source.Save();
return dest; return dest;
} }
#region Reschedule PM #region Reschedule PM
source.WorkorderPreventiveMaintenance.dtNextServiceDate = dtNext; source.WorkorderPreventiveMaintenance.dtNextServiceDate = dtNext;
//Calcs the generate date (threshold date) //Calcs the generate date (threshold date)
source.WorkorderPreventiveMaintenance.SetGenerateDate(); source.WorkorderPreventiveMaintenance.SetGenerateDate();
//WORKORDERITEMS //WORKORDERITEMS
foreach (WorkorderItem wisource in source.WorkorderItems) foreach (WorkorderItem wisource in source.WorkorderItems)
{ {
wisource.RequestDate = wisource.RequestDate; wisource.RequestDate = wisource.RequestDate;
//PARTS //PARTS
//no date changes required //no date changes required
//SCHEDULED USERS //SCHEDULED USERS
foreach (WorkorderItemScheduledUser usersource in wisource.ScheduledUsers) foreach (WorkorderItemScheduledUser usersource in wisource.ScheduledUsers)
{ {
//Changed: 2-Oct-2006 //Changed: 2-Oct-2006
//check to not add a date if the original date was empty //check to not add a date if the original date was empty
if (usersource.StartDate != System.DBNull.Value) if (usersource.StartDate != System.DBNull.Value)
usersource.dtStartDate = usersource.dtStartDate.Add(tsToNext); usersource.dtStartDate = usersource.dtStartDate.Add(tsToNext);
if (usersource.StopDate != System.DBNull.Value) if (usersource.StopDate != System.DBNull.Value)
usersource.dtStopDate = usersource.dtStopDate.Add(tsToNext); usersource.dtStopDate = usersource.dtStopDate.Add(tsToNext);
} }
//LABOR //LABOR
foreach (WorkorderItemLabor laborsource in wisource.Labors) foreach (WorkorderItemLabor laborsource in wisource.Labors)
{ {
//Changed: 2-Oct-2006 //Changed: 2-Oct-2006
//check to not add a date if the original date was empty //check to not add a date if the original date was empty
if (laborsource.ServiceStartDate != System.DBNull.Value) if (laborsource.ServiceStartDate != System.DBNull.Value)
laborsource.dtServiceStartDate = laborsource.dtServiceStartDate.Add(tsToNext); laborsource.dtServiceStartDate = laborsource.dtServiceStartDate.Add(tsToNext);
if (laborsource.ServiceStopDate != System.DBNull.Value) if (laborsource.ServiceStopDate != System.DBNull.Value)
laborsource.dtServiceStopDate = laborsource.dtServiceStopDate.Add(tsToNext); laborsource.dtServiceStopDate = laborsource.dtServiceStopDate.Add(tsToNext);
} }
//********************************************************** //**********************************************************
//Expenses would be here if copying a service workorder //Expenses would be here if copying a service workorder
//********************************************************** //**********************************************************
//********************************************************** //**********************************************************
//Loans would be here if copying a service workorder //Loans would be here if copying a service workorder
//********************************************************** //**********************************************************
//TRAVEL //TRAVEL
foreach (WorkorderItemTravel travelsource in wisource.Travels) foreach (WorkorderItemTravel travelsource in wisource.Travels)
{ {
//Changed: 2-Oct-2006 //Changed: 2-Oct-2006
//check to not add a date if the original date was empty //check to not add a date if the original date was empty
if (travelsource.TravelStartDate != DBNull.Value) if (travelsource.TravelStartDate != DBNull.Value)
travelsource.dtTravelStartDate = travelsource.dtTravelStartDate.Add(tsToNext); travelsource.dtTravelStartDate = travelsource.dtTravelStartDate.Add(tsToNext);
if (travelsource.TravelStopDate != DBNull.Value) if (travelsource.TravelStopDate != DBNull.Value)
travelsource.dtTravelStopDate = travelsource.dtTravelStopDate.Add(tsToNext); travelsource.dtTravelStopDate = travelsource.dtTravelStopDate.Add(tsToNext);
} }
//TASKS //TASKS
//********************************************************** //**********************************************************
//Outside service would be here if copying a service workorder //Outside service would be here if copying a service workorder
//********************************************************** //**********************************************************
}//foreach workorderitem loop }//foreach workorderitem loop
#endregion reschedule pm #endregion reschedule pm
//Ok, Source PM is now rescheduled, save it //Ok, Source PM is now rescheduled, save it
//case 1959 try catch block added to prevent infinite generation issue //case 1959 try catch block added to prevent infinite generation issue
try try
{ {
source = (Workorder)source.Save(); source = (Workorder)source.Save();
} }
catch (Exception exx) catch (Exception exx)
{ {
dest.Delete(); dest.Delete();
dest.Save(); dest.Save();
//crack the exception //crack the exception
while (exx.InnerException != null) while (exx.InnerException != null)
exx = exx.InnerException; exx = exx.InnerException;
Memo mwarn = Memo.NewItem(); Memo mwarn = Memo.NewItem();
mwarn.ToID = User.AdministratorID; mwarn.ToID = User.AdministratorID;
//case 3826 //case 3826
if (User.CurrentUserType == UserTypes.Utility) if (User.CurrentUserType == UserTypes.Utility)
{ {
//Utility accounts should not be sending memos, it fucks up downstream //Utility accounts should not be sending memos, it fucks up downstream
//trying to view the memo, also it's confusing //trying to view the memo, also it's confusing
mwarn.FromID = User.AdministratorID; mwarn.FromID = User.AdministratorID;
} }
else else
{ {
mwarn.FromID = User.CurrentThreadUserID; mwarn.FromID = User.CurrentThreadUserID;
} }
mwarn.Subject = "SYSTEM WARNING: Preventive Maintenance WO PROBLEM"; mwarn.Subject = "SYSTEM WARNING: Preventive Maintenance WO PROBLEM";
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.AppendLine("This is an automated message sent on behalf of the current user from the \"NewServiceWorkorderFromPM\" module."); sb.AppendLine("This is an automated message sent on behalf of the current user from the \"NewServiceWorkorderFromPM\" module.");
sb.AppendLine("This message concerns Preventive Maintenance workorder number " + source.WorkorderPreventiveMaintenance.PreventiveMaintenanceNumber.ToString()); sb.AppendLine("This message concerns Preventive Maintenance workorder number " + source.WorkorderPreventiveMaintenance.PreventiveMaintenanceNumber.ToString());
sb.AppendLine("The Preventive Maintenance workorder had an error when trying to save it during generation of a service workorder."); sb.AppendLine("The Preventive Maintenance workorder had an error when trying to save it during generation of a service workorder.");
sb.AppendLine("This kind of problem could result in loop which generates a very large number of identical service workorders."); sb.AppendLine("This kind of problem could result in loop which generates a very large number of identical service workorders.");
sb.AppendLine("In order to prevent this the operation has been stopped and this message generated so you can fix the problem with the source PM workorder."); sb.AppendLine("In order to prevent this the operation has been stopped and this message generated so you can fix the problem with the source PM workorder.");
sb.AppendLine("See below for details and examine the PM workorder for problems or contact support@ayanova.com for help with the information in this message."); sb.AppendLine("See below for details and examine the PM workorder for problems or contact support@ayanova.com for help with the information in this message.");
sb.AppendLine("Here are the details of the error preventing save:"); sb.AppendLine("Here are the details of the error preventing save:");
sb.AppendLine("================================="); sb.AppendLine("=================================");
sb.AppendLine("Exception saving source PM:"); sb.AppendLine("Exception saving source PM:");
sb.AppendLine(exx.Message); sb.AppendLine(exx.Message);
sb.AppendLine("================================="); sb.AppendLine("=================================");
string sSourceErr = source.GetBrokenRulesString(); string sSourceErr = source.GetBrokenRulesString();
if (!string.IsNullOrWhiteSpace(sSourceErr)) if (!string.IsNullOrWhiteSpace(sSourceErr))
{ {
sb.AppendLine("Broken business rules on PM object:"); sb.AppendLine("Broken business rules on PM object:");
sb.AppendLine(sSourceErr); sb.AppendLine(sSourceErr);
sb.AppendLine("=============================="); sb.AppendLine("==============================");
} }
mwarn.Message = sb.ToString(); mwarn.Message = sb.ToString();
mwarn.Save(); mwarn.Save();
throw new System.ApplicationException("Workorder->NewServiceWorkorderFromPM: Error during service workorder generation. Memo with details sent to Administrator account."); throw new System.ApplicationException("Workorder->NewServiceWorkorderFromPM: Error during service workorder generation. Memo with details sent to Administrator account.");
} }
//case 1630 //case 1630
//copy wikipage from pm to service workorder //copy wikipage from pm to service workorder
if (dest.CanWiki && source.HasWiki) if (dest.CanWiki && source.HasWiki)
{ {
try try
{ {
WikiPage wpSource = WikiPage.GetItem(new TypeAndID(RootObjectTypes.WorkorderPreventiveMaintenance, source.ID)); WikiPage wpSource = WikiPage.GetItem(new TypeAndID(RootObjectTypes.WorkorderPreventiveMaintenance, source.ID));
WikiPage wpDest = WikiPage.GetItem(new TypeAndID(RootObjectTypes.WorkorderService, dest.ID)); WikiPage wpDest = WikiPage.GetItem(new TypeAndID(RootObjectTypes.WorkorderService, dest.ID));
wpDest.SetContent(wpSource.GetContent()); wpDest.SetContent(wpSource.GetContent());
wpDest.Save(); wpDest.Save();
} }
catch { }; catch { };
} }
return dest; return dest;
} }
/// <summary> /// <summary>
/// Calculate generate date based on service date and /// Calculate generate date based on service date and
/// threshold span and unit /// threshold span and unit
/// </summary> /// </summary>
internal void SetGenerateDate() internal void SetGenerateDate()
{ {
if (this.mNextServiceDate.IsEmpty) return; if (this.mNextServiceDate.IsEmpty) return;
if (this.mThresholdSpan == 0) if (this.mThresholdSpan == 0)
{ {
this.mGenerateDate = this.mNextServiceDate; this.mGenerateDate = this.mNextServiceDate;
MarkDirty(); MarkDirty();
return; return;
} }
mGenerateDate = new SmartDate(Workorder.GetDateFromSpanAndUnit(mNextServiceDate.Date, this.mThresholdSpanUnit, -mThresholdSpan)); mGenerateDate = new SmartDate(Workorder.GetDateFromSpanAndUnit(mNextServiceDate.Date, this.mThresholdSpanUnit, -mThresholdSpan));
MarkDirty(); MarkDirty();
} }
#region Date time calcs helpers #region Date time calcs helpers
//Takes an AyaNova day of week and returns //Takes an AyaNova day of week and returns
//a System.DayOfWeek //a System.DayOfWeek
//Assumes that AyaDayOfWeek is NOT "AnyDay" //Assumes that AyaDayOfWeek is NOT "AnyDay"
internal static System.DayOfWeek AyaToSystemDayOfWeek(AyaDayOfWeek day) internal static System.DayOfWeek AyaToSystemDayOfWeek(AyaDayOfWeek day)
{ {
switch (day) switch (day)
{ {
case AyaDayOfWeek.Monday: case AyaDayOfWeek.Monday:
return DayOfWeek.Monday; return DayOfWeek.Monday;
case AyaDayOfWeek.Tuesday: case AyaDayOfWeek.Tuesday:
return DayOfWeek.Tuesday; return DayOfWeek.Tuesday;
case AyaDayOfWeek.Wednesday: case AyaDayOfWeek.Wednesday:
return DayOfWeek.Wednesday; return DayOfWeek.Wednesday;
case AyaDayOfWeek.Thursday: case AyaDayOfWeek.Thursday:
return DayOfWeek.Thursday; return DayOfWeek.Thursday;
case AyaDayOfWeek.Friday: case AyaDayOfWeek.Friday:
return DayOfWeek.Friday; return DayOfWeek.Friday;
case AyaDayOfWeek.Saturday: case AyaDayOfWeek.Saturday:
return DayOfWeek.Saturday; return DayOfWeek.Saturday;
case AyaDayOfWeek.Sunday: case AyaDayOfWeek.Sunday:
return DayOfWeek.Sunday; return DayOfWeek.Sunday;
} }
throw new System.ArgumentOutOfRangeException("DayOfWeekConverter: AyaDayOfWeek.AnyDayOfWeek is not supported"); throw new System.ArgumentOutOfRangeException("DayOfWeekConverter: AyaDayOfWeek.AnyDayOfWeek is not supported");
} }
internal static DateTime GetDateFromSpanAndUnit(DateTime StartDate, AyaUnitsOfTime unit, int multiple) internal static DateTime GetDateFromSpanAndUnit(DateTime StartDate, AyaUnitsOfTime unit, int multiple)
{ {
switch (unit) switch (unit)
{ {
case AyaUnitsOfTime.Seconds: case AyaUnitsOfTime.Seconds:
return StartDate.AddSeconds(multiple); return StartDate.AddSeconds(multiple);
case AyaUnitsOfTime.Minutes: case AyaUnitsOfTime.Minutes:
return StartDate.AddMinutes(multiple); return StartDate.AddMinutes(multiple);
case AyaUnitsOfTime.Hours: case AyaUnitsOfTime.Hours:
return StartDate.AddHours(multiple); return StartDate.AddHours(multiple);
case AyaUnitsOfTime.Days: case AyaUnitsOfTime.Days:
return StartDate.AddDays(multiple); return StartDate.AddDays(multiple);
case AyaUnitsOfTime.Weeks: case AyaUnitsOfTime.Weeks:
throw new System.NotSupportedException("GetDateFromSpanAndUnit: Weeks not supported"); throw new System.NotSupportedException("GetDateFromSpanAndUnit: Weeks not supported");
case AyaUnitsOfTime.Months: case AyaUnitsOfTime.Months:
return StartDate.AddMonths(multiple); return StartDate.AddMonths(multiple);
case AyaUnitsOfTime.Years: case AyaUnitsOfTime.Years:
return StartDate.AddYears(multiple); return StartDate.AddYears(multiple);
} }
//fail safe: //fail safe:
return StartDate; return StartDate;
} }
*/ */
#endregion gen service wo from pm #endregion gen service wo from pm
internal class PMBiz : BizObject, IJobObject, ISearchAbleObject, IReportAbleObject, IExportAbleObject internal class PMBiz : BizObject, IJobObject, ISearchAbleObject, IReportAbleObject, IExportAbleObject
{ {
@@ -1027,16 +1027,6 @@ namespace AyaNova.Biz
// ////////////////////////////////////////////////////////////////////////////////////////////////
// //GET WORKORDER ID FOR WORK ORDER NUMBER
// //
// internal static async Task<long> GetPMIdForNumberAsync(long woNumber, AyContext ct)
// {
// return await ct.PM.AsNoTracking()
// .Where(z => z.Serial == woNumber)
// .Select(z => z.Id)
// .SingleOrDefaultAsync();
// }
@@ -5644,7 +5634,30 @@ namespace AyaNova.Biz
#region GENERATION
////////////////////////////////////////////////////////////////////////////////////////////////
// Process generation of pms to workorders
//
internal static async Task Generate(AyContext ct, ILogger log)
{
#if (DEBUG)
log.LogInformation("PMBiz - Generating");
#endif
//Get a list of items
//process those items
//make new workorder
//fixup dates and update pm
//dummy query to turn off errors
var v = await ct.PM.AsNoTracking()
.Where(z => z.Serial == 1)
.Select(z => z.Id)
.SingleOrDefaultAsync();
}
#endregion
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,80 @@
using System;
using System.Linq;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using AyaNova.Models;
using AyaNova.Util;
namespace AyaNova.Biz
{
/// <summary>
/// Preventive maintenance generator
/// turn PMs into Work orders
///
/// </summary>
internal static class CoreJobPMGenerate
{
private static bool IsRunning = false;
private static ILogger log = AyaNova.Util.ApplicationLogging.CreateLogger("CoreJobPMGenerate");
private static DateTime lastRun = DateTime.MinValue;
#if (DEBUG)
private static TimeSpan RUN_EVERY_INTERVAL = new TimeSpan(0, 0, 20);//no more frequently than once every 20 seconds
#else
private static TimeSpan RUN_EVERY_INTERVAL = new TimeSpan(0, 5, 0);//no more frequently than once every 5 minutes
#endif
public static async Task DoWorkAsync()
{
log.LogTrace("Checking if PMGenerate should run");
if (IsRunning)
{
log.LogTrace("PMGenerate is running already exiting this cycle");
return;
}
//This will get triggered roughly every minute, but we don't want to deliver that frequently
if (DateTime.UtcNow - lastRun < RUN_EVERY_INTERVAL)
{
log.LogTrace($"PMGenerate ran less than {RUN_EVERY_INTERVAL} ago, exiting this cycle");
return;
}
try
{
IsRunning = true;
log.LogTrace("PMGenerate set to RUNNING state and starting now");
using (AyContext ct = AyaNova.Util.ServiceProviderProvider.DBContext)
{
await PMBiz.Generate(ct, log);
}
}
catch (Exception ex)
{
log.LogError(ex, $"Error processing PMGenerate ");
}
finally
{
log.LogTrace("PMGenerate has completed; setting to not running state and tagging lastRun timestamp");
lastRun = DateTime.UtcNow;
IsRunning = false;
}
}
/////////////////////////////////////////////////////////////////////
}//eoc
}//eons