This commit is contained in:
@@ -206,6 +206,9 @@ namespace AyaNova.Biz
|
||||
await CoreJobNotify.DoWorkAsync();
|
||||
await CoreNotificationSweeper.DoWorkAsync();
|
||||
|
||||
//PM GENERATION
|
||||
await CoreJobPMGenerate.DoWorkAsync();
|
||||
|
||||
//JOB SWEEPER / AND USER COUNT CHECK
|
||||
await CoreJobSweeper.DoWorkAsync();
|
||||
|
||||
|
||||
@@ -13,488 +13,488 @@ using System.Collections.Generic;
|
||||
namespace AyaNova.Biz
|
||||
{
|
||||
|
||||
#region v7 code for Generate service workorder from PM
|
||||
/* /// <summary>
|
||||
/// Generates a service workorder from a PM type Workorder
|
||||
/// </summary>
|
||||
/// <param name="SourceWorkorderID">ID of PM</param>
|
||||
/// <returns>A new service workorder</returns>
|
||||
public static Workorder NewServiceWorkorderFromPM(Guid SourceWorkorderID)
|
||||
{
|
||||
//Fetch the source workorder and verify it's a PM
|
||||
Workorder source = Workorder.GetItemNoMRU(SourceWorkorderID);
|
||||
if (source.WorkorderType != WorkorderTypes.PreventiveMaintenance)
|
||||
throw new NotSupportedException(LocalizedTextTable.GetLocalizedTextDirect("Workorder.Label.Error.SourceInvalidType"));
|
||||
|
||||
//if it's inactive then there is nothing to Process
|
||||
//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
|
||||
//expiry date
|
||||
if (source.WorkorderPreventiveMaintenance.Active == false)
|
||||
{
|
||||
throw new System.ApplicationException("NewServiceWorkorderFromPM: source PM workorder is not active");
|
||||
}
|
||||
|
||||
if (source.WorkorderPreventiveMaintenance.StopGeneratingDate != System.DBNull.Value &&
|
||||
source.WorkorderPreventiveMaintenance.dtStopGeneratingDate < DBUtil.CurrentWorkingDateTime)
|
||||
{
|
||||
throw new System.ApplicationException("NewServiceWorkorderFromPM: source PM workorder is past StopGeneratingDate");
|
||||
}
|
||||
|
||||
//Ok, so far so good, create the new one
|
||||
bool bUseInventory = AyaBizUtils.GlobalSettings.UseInventory;
|
||||
|
||||
//case 1387
|
||||
Workorder dest = Workorder.NewItem(WorkorderTypes.Service);
|
||||
|
||||
////NOTE: THIS DOESN'T CALL THE SHARED NEW ITEM METHOD
|
||||
//Workorder dest = new Workorder();
|
||||
//dest.WorkorderType=WorkorderTypes.Service;
|
||||
//dest.mService=WorkorderService.NewItem(dest);
|
||||
|
||||
#region copy workorder data
|
||||
|
||||
//WORKORDER HEADER
|
||||
dest.ClientID = source.ClientID;
|
||||
dest.CustomerContactName = source.CustomerContactName;
|
||||
dest.CustomerReferenceNumber = source.CustomerReferenceNumber;
|
||||
dest.mFromPMID = source.WorkorderPreventiveMaintenance.ID;
|
||||
dest.InternalReferenceNumber = source.InternalReferenceNumber;
|
||||
dest.Onsite = source.Onsite;
|
||||
dest.ProjectID = source.ProjectID;
|
||||
//dest.RegionID=source.RegionID;
|
||||
dest.Summary = source.Summary;
|
||||
dest.WorkorderCategoryID = source.WorkorderCategoryID;
|
||||
|
||||
//PM SPECIFIC
|
||||
dest.WorkorderService.WorkorderStatusID = source.WorkorderPreventiveMaintenance.WorkorderStatusID;
|
||||
//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))
|
||||
dest.WorkorderService.ServiceDate = source.WorkorderPreventiveMaintenance.NextServiceDate;
|
||||
|
||||
|
||||
//WORKORDERITEMS
|
||||
foreach (WorkorderItem wisource in source.WorkorderItems)
|
||||
{
|
||||
WorkorderItem widest = dest.WorkorderItems.Add(dest);
|
||||
widest.Custom0 = wisource.Custom0;
|
||||
widest.Custom1 = wisource.Custom1;
|
||||
widest.Custom2 = wisource.Custom2;
|
||||
widest.Custom3 = wisource.Custom3;
|
||||
widest.Custom4 = wisource.Custom4;
|
||||
widest.Custom5 = wisource.Custom5;
|
||||
widest.Custom6 = wisource.Custom6;
|
||||
widest.Custom7 = wisource.Custom7;
|
||||
widest.Custom8 = wisource.Custom8;
|
||||
widest.Custom9 = wisource.Custom9;
|
||||
widest.PriorityID = wisource.PriorityID;
|
||||
widest.RequestDate = wisource.RequestDate;
|
||||
widest.Summary = wisource.Summary;
|
||||
widest.TechNotes = wisource.TechNotes;
|
||||
widest.TypeID = wisource.TypeID;
|
||||
widest.UnitID = wisource.UnitID;
|
||||
widest.WarrantyService = wisource.WarrantyService;
|
||||
widest.WorkorderItemUnitServiceTypeID = wisource.WorkorderItemUnitServiceTypeID;
|
||||
widest.WorkorderStatusID = wisource.WorkorderStatusID;
|
||||
|
||||
//PARTS
|
||||
foreach (WorkorderItemPart partsource in wisource.Parts)
|
||||
{
|
||||
WorkorderItemPart partdest = widest.Parts.Add(widest);
|
||||
partdest.Cost = partsource.Cost;
|
||||
partdest.Description = partsource.Description;
|
||||
partdest.Discount = partsource.Discount;
|
||||
partdest.DiscountType = partsource.DiscountType;
|
||||
partdest.PartID = partsource.PartID;
|
||||
partdest.PartWarehouseID = partsource.PartWarehouseID;
|
||||
partdest.Price = partsource.Price;
|
||||
if (bUseInventory)
|
||||
{
|
||||
partdest.QuantityReserved = partsource.Quantity;
|
||||
partdest.Quantity = 0;
|
||||
}
|
||||
else
|
||||
partdest.Quantity = partsource.Quantity;
|
||||
partdest.TaxPartSaleID = partsource.TaxPartSaleID;
|
||||
|
||||
|
||||
}
|
||||
|
||||
//**********************************************************
|
||||
//Part requests would be here if copying a service workorder
|
||||
//**********************************************************
|
||||
|
||||
//SCHEDULED USERS
|
||||
foreach (WorkorderItemScheduledUser usersource in wisource.ScheduledUsers)
|
||||
{
|
||||
WorkorderItemScheduledUser userdest = widest.ScheduledUsers.Add(widest);
|
||||
userdest.EstimatedQuantity = usersource.EstimatedQuantity;
|
||||
userdest.ServiceRateID = usersource.ServiceRateID;
|
||||
userdest.StartDate = usersource.StartDate;
|
||||
userdest.StopDate = usersource.StopDate;
|
||||
userdest.UserID = usersource.UserID;
|
||||
|
||||
}
|
||||
|
||||
//LABOR
|
||||
foreach (WorkorderItemLabor laborsource in wisource.Labors)
|
||||
{
|
||||
WorkorderItemLabor labordest = widest.Labors.Add(widest);
|
||||
labordest.NoChargeQuantity = laborsource.NoChargeQuantity;
|
||||
labordest.ServiceDetails = laborsource.ServiceDetails;
|
||||
labordest.ServiceRateID = laborsource.ServiceRateID;
|
||||
labordest.ServiceRateQuantity = laborsource.ServiceRateQuantity;
|
||||
labordest.ServiceStartDate = laborsource.ServiceStartDate;
|
||||
labordest.ServiceStopDate = laborsource.ServiceStopDate;
|
||||
labordest.TaxRateSaleID = laborsource.TaxRateSaleID;
|
||||
labordest.UserID = laborsource.UserID;
|
||||
|
||||
}
|
||||
|
||||
//**********************************************************
|
||||
//Expenses would be here if copying a service workorder
|
||||
//**********************************************************
|
||||
|
||||
|
||||
//**********************************************************
|
||||
//Loans would be here if copying a service workorder
|
||||
//**********************************************************
|
||||
|
||||
//TRAVEL
|
||||
foreach (WorkorderItemTravel travelsource in wisource.Travels)
|
||||
{
|
||||
WorkorderItemTravel traveldest = widest.Travels.Add(widest);
|
||||
traveldest.TravelDetails = travelsource.TravelDetails;
|
||||
traveldest.TravelRateID = travelsource.TravelRateID;
|
||||
traveldest.TravelRateQuantity = travelsource.TravelRateQuantity;
|
||||
traveldest.TravelStartDate = travelsource.TravelStartDate;
|
||||
traveldest.TravelStopDate = travelsource.TravelStopDate;
|
||||
traveldest.TaxRateSaleID = travelsource.TaxRateSaleID;
|
||||
traveldest.UserID = travelsource.UserID;
|
||||
traveldest.Distance = travelsource.Distance;
|
||||
traveldest.Notes = travelsource.Notes;
|
||||
traveldest.NoChargeQuantity = travelsource.NoChargeQuantity;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//TASKS
|
||||
foreach (WorkorderItemTask tasksource in wisource.Tasks)
|
||||
{
|
||||
WorkorderItemTask taskdest = widest.Tasks.Add(widest);
|
||||
taskdest.TaskGroupID = tasksource.TaskGroupID;
|
||||
taskdest.TaskID = tasksource.TaskID;
|
||||
|
||||
}
|
||||
|
||||
//**********************************************************
|
||||
//Outside service would be here if copying a service workorder
|
||||
//**********************************************************
|
||||
|
||||
}//foreach workorderitem loop
|
||||
#region v7 code for Generate service workorder from PM
|
||||
/* /// <summary>
|
||||
/// Generates a service workorder from a PM type Workorder
|
||||
/// </summary>
|
||||
/// <param name="SourceWorkorderID">ID of PM</param>
|
||||
/// <returns>A new service workorder</returns>
|
||||
public static Workorder NewServiceWorkorderFromPM(Guid SourceWorkorderID)
|
||||
{
|
||||
//Fetch the source workorder and verify it's a PM
|
||||
Workorder source = Workorder.GetItemNoMRU(SourceWorkorderID);
|
||||
if (source.WorkorderType != WorkorderTypes.PreventiveMaintenance)
|
||||
throw new NotSupportedException(LocalizedTextTable.GetLocalizedTextDirect("Workorder.Label.Error.SourceInvalidType"));
|
||||
|
||||
//if it's inactive then there is nothing to Process
|
||||
//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
|
||||
//expiry date
|
||||
if (source.WorkorderPreventiveMaintenance.Active == false)
|
||||
{
|
||||
throw new System.ApplicationException("NewServiceWorkorderFromPM: source PM workorder is not active");
|
||||
}
|
||||
|
||||
if (source.WorkorderPreventiveMaintenance.StopGeneratingDate != System.DBNull.Value &&
|
||||
source.WorkorderPreventiveMaintenance.dtStopGeneratingDate < DBUtil.CurrentWorkingDateTime)
|
||||
{
|
||||
throw new System.ApplicationException("NewServiceWorkorderFromPM: source PM workorder is past StopGeneratingDate");
|
||||
}
|
||||
|
||||
//Ok, so far so good, create the new one
|
||||
bool bUseInventory = AyaBizUtils.GlobalSettings.UseInventory;
|
||||
|
||||
//case 1387
|
||||
Workorder dest = Workorder.NewItem(WorkorderTypes.Service);
|
||||
|
||||
////NOTE: THIS DOESN'T CALL THE SHARED NEW ITEM METHOD
|
||||
//Workorder dest = new Workorder();
|
||||
//dest.WorkorderType=WorkorderTypes.Service;
|
||||
//dest.mService=WorkorderService.NewItem(dest);
|
||||
|
||||
#region copy workorder data
|
||||
|
||||
//WORKORDER HEADER
|
||||
dest.ClientID = source.ClientID;
|
||||
dest.CustomerContactName = source.CustomerContactName;
|
||||
dest.CustomerReferenceNumber = source.CustomerReferenceNumber;
|
||||
dest.mFromPMID = source.WorkorderPreventiveMaintenance.ID;
|
||||
dest.InternalReferenceNumber = source.InternalReferenceNumber;
|
||||
dest.Onsite = source.Onsite;
|
||||
dest.ProjectID = source.ProjectID;
|
||||
//dest.RegionID=source.RegionID;
|
||||
dest.Summary = source.Summary;
|
||||
dest.WorkorderCategoryID = source.WorkorderCategoryID;
|
||||
|
||||
//PM SPECIFIC
|
||||
dest.WorkorderService.WorkorderStatusID = source.WorkorderPreventiveMaintenance.WorkorderStatusID;
|
||||
//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))
|
||||
dest.WorkorderService.ServiceDate = source.WorkorderPreventiveMaintenance.NextServiceDate;
|
||||
|
||||
|
||||
//WORKORDERITEMS
|
||||
foreach (WorkorderItem wisource in source.WorkorderItems)
|
||||
{
|
||||
WorkorderItem widest = dest.WorkorderItems.Add(dest);
|
||||
widest.Custom0 = wisource.Custom0;
|
||||
widest.Custom1 = wisource.Custom1;
|
||||
widest.Custom2 = wisource.Custom2;
|
||||
widest.Custom3 = wisource.Custom3;
|
||||
widest.Custom4 = wisource.Custom4;
|
||||
widest.Custom5 = wisource.Custom5;
|
||||
widest.Custom6 = wisource.Custom6;
|
||||
widest.Custom7 = wisource.Custom7;
|
||||
widest.Custom8 = wisource.Custom8;
|
||||
widest.Custom9 = wisource.Custom9;
|
||||
widest.PriorityID = wisource.PriorityID;
|
||||
widest.RequestDate = wisource.RequestDate;
|
||||
widest.Summary = wisource.Summary;
|
||||
widest.TechNotes = wisource.TechNotes;
|
||||
widest.TypeID = wisource.TypeID;
|
||||
widest.UnitID = wisource.UnitID;
|
||||
widest.WarrantyService = wisource.WarrantyService;
|
||||
widest.WorkorderItemUnitServiceTypeID = wisource.WorkorderItemUnitServiceTypeID;
|
||||
widest.WorkorderStatusID = wisource.WorkorderStatusID;
|
||||
|
||||
//PARTS
|
||||
foreach (WorkorderItemPart partsource in wisource.Parts)
|
||||
{
|
||||
WorkorderItemPart partdest = widest.Parts.Add(widest);
|
||||
partdest.Cost = partsource.Cost;
|
||||
partdest.Description = partsource.Description;
|
||||
partdest.Discount = partsource.Discount;
|
||||
partdest.DiscountType = partsource.DiscountType;
|
||||
partdest.PartID = partsource.PartID;
|
||||
partdest.PartWarehouseID = partsource.PartWarehouseID;
|
||||
partdest.Price = partsource.Price;
|
||||
if (bUseInventory)
|
||||
{
|
||||
partdest.QuantityReserved = partsource.Quantity;
|
||||
partdest.Quantity = 0;
|
||||
}
|
||||
else
|
||||
partdest.Quantity = partsource.Quantity;
|
||||
partdest.TaxPartSaleID = partsource.TaxPartSaleID;
|
||||
|
||||
|
||||
}
|
||||
|
||||
//**********************************************************
|
||||
//Part requests would be here if copying a service workorder
|
||||
//**********************************************************
|
||||
|
||||
//SCHEDULED USERS
|
||||
foreach (WorkorderItemScheduledUser usersource in wisource.ScheduledUsers)
|
||||
{
|
||||
WorkorderItemScheduledUser userdest = widest.ScheduledUsers.Add(widest);
|
||||
userdest.EstimatedQuantity = usersource.EstimatedQuantity;
|
||||
userdest.ServiceRateID = usersource.ServiceRateID;
|
||||
userdest.StartDate = usersource.StartDate;
|
||||
userdest.StopDate = usersource.StopDate;
|
||||
userdest.UserID = usersource.UserID;
|
||||
|
||||
}
|
||||
|
||||
//LABOR
|
||||
foreach (WorkorderItemLabor laborsource in wisource.Labors)
|
||||
{
|
||||
WorkorderItemLabor labordest = widest.Labors.Add(widest);
|
||||
labordest.NoChargeQuantity = laborsource.NoChargeQuantity;
|
||||
labordest.ServiceDetails = laborsource.ServiceDetails;
|
||||
labordest.ServiceRateID = laborsource.ServiceRateID;
|
||||
labordest.ServiceRateQuantity = laborsource.ServiceRateQuantity;
|
||||
labordest.ServiceStartDate = laborsource.ServiceStartDate;
|
||||
labordest.ServiceStopDate = laborsource.ServiceStopDate;
|
||||
labordest.TaxRateSaleID = laborsource.TaxRateSaleID;
|
||||
labordest.UserID = laborsource.UserID;
|
||||
|
||||
}
|
||||
|
||||
//**********************************************************
|
||||
//Expenses would be here if copying a service workorder
|
||||
//**********************************************************
|
||||
|
||||
|
||||
//**********************************************************
|
||||
//Loans would be here if copying a service workorder
|
||||
//**********************************************************
|
||||
|
||||
//TRAVEL
|
||||
foreach (WorkorderItemTravel travelsource in wisource.Travels)
|
||||
{
|
||||
WorkorderItemTravel traveldest = widest.Travels.Add(widest);
|
||||
traveldest.TravelDetails = travelsource.TravelDetails;
|
||||
traveldest.TravelRateID = travelsource.TravelRateID;
|
||||
traveldest.TravelRateQuantity = travelsource.TravelRateQuantity;
|
||||
traveldest.TravelStartDate = travelsource.TravelStartDate;
|
||||
traveldest.TravelStopDate = travelsource.TravelStopDate;
|
||||
traveldest.TaxRateSaleID = travelsource.TaxRateSaleID;
|
||||
traveldest.UserID = travelsource.UserID;
|
||||
traveldest.Distance = travelsource.Distance;
|
||||
traveldest.Notes = travelsource.Notes;
|
||||
traveldest.NoChargeQuantity = travelsource.NoChargeQuantity;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//TASKS
|
||||
foreach (WorkorderItemTask tasksource in wisource.Tasks)
|
||||
{
|
||||
WorkorderItemTask taskdest = widest.Tasks.Add(widest);
|
||||
taskdest.TaskGroupID = tasksource.TaskGroupID;
|
||||
taskdest.TaskID = tasksource.TaskID;
|
||||
|
||||
}
|
||||
|
||||
//**********************************************************
|
||||
//Outside service would be here if copying a service workorder
|
||||
//**********************************************************
|
||||
|
||||
}//foreach workorderitem loop
|
||||
|
||||
//case 1387
|
||||
//case 1387
|
||||
|
||||
//Delete the auto-created dummy workorder item
|
||||
//if there are more than it present
|
||||
if (dest.WorkorderItems.Count > 1)
|
||||
dest.WorkorderItems.RemoveAt(0);
|
||||
//Delete the auto-created dummy workorder item
|
||||
//if there are more than it present
|
||||
if (dest.WorkorderItems.Count > 1)
|
||||
dest.WorkorderItems.RemoveAt(0);
|
||||
|
||||
#endregion copy workorder data
|
||||
#endregion copy workorder data
|
||||
|
||||
//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
|
||||
//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
|
||||
|
||||
//case 868 previously didn't set dest to result of save causing it to be a copy
|
||||
dest = (Workorder)dest.Save();
|
||||
//case 868 previously didn't set dest to result of save causing it to be a copy
|
||||
dest = (Workorder)dest.Save();
|
||||
|
||||
|
||||
|
||||
|
||||
#region Calculate reschedule dates
|
||||
//Get the current next service date for calcs
|
||||
DateTime dtNext = GetDateFromSpanAndUnit(source.WorkorderPreventiveMaintenance.dtNextServiceDate,
|
||||
source.WorkorderPreventiveMaintenance.GenerateSpanUnit,
|
||||
source.WorkorderPreventiveMaintenance.GenerateSpan);
|
||||
#region Calculate reschedule dates
|
||||
//Get the current next service date for calcs
|
||||
DateTime dtNext = GetDateFromSpanAndUnit(source.WorkorderPreventiveMaintenance.dtNextServiceDate,
|
||||
source.WorkorderPreventiveMaintenance.GenerateSpanUnit,
|
||||
source.WorkorderPreventiveMaintenance.GenerateSpan);
|
||||
|
||||
//Get to the desired day of the week if necessary...
|
||||
if (source.mWorkorderPreventiveMaintenance.DayOfTheWeek != AyaDayOfWeek.AnyDayOfWeek)
|
||||
{
|
||||
DayOfWeek desired = AyaToSystemDayOfWeek(source.mWorkorderPreventiveMaintenance.DayOfTheWeek);
|
||||
while (dtNext.DayOfWeek != desired)
|
||||
{
|
||||
dtNext = dtNext.AddDays(1);
|
||||
}
|
||||
//Get to the desired day of the week if necessary...
|
||||
if (source.mWorkorderPreventiveMaintenance.DayOfTheWeek != AyaDayOfWeek.AnyDayOfWeek)
|
||||
{
|
||||
DayOfWeek desired = AyaToSystemDayOfWeek(source.mWorkorderPreventiveMaintenance.DayOfTheWeek);
|
||||
while (dtNext.DayOfWeek != desired)
|
||||
{
|
||||
dtNext = dtNext.AddDays(1);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//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
|
||||
System.TimeSpan tsToNext = dtNext - source.WorkorderPreventiveMaintenance.dtNextServiceDate;
|
||||
//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
|
||||
System.TimeSpan tsToNext = dtNext - source.WorkorderPreventiveMaintenance.dtNextServiceDate;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
//Will the next workorder service date fall after the
|
||||
//stop generating date?
|
||||
if (source.WorkorderPreventiveMaintenance.StopGeneratingDate != System.DBNull.Value &&
|
||||
source.WorkorderPreventiveMaintenance.dtStopGeneratingDate < dtNext)
|
||||
{
|
||||
//Yes it will, so set it to inactive and bail out
|
||||
source.WorkorderPreventiveMaintenance.Active = false;
|
||||
source.Save();
|
||||
return dest;
|
||||
}
|
||||
//Will the next workorder service date fall after the
|
||||
//stop generating date?
|
||||
if (source.WorkorderPreventiveMaintenance.StopGeneratingDate != System.DBNull.Value &&
|
||||
source.WorkorderPreventiveMaintenance.dtStopGeneratingDate < dtNext)
|
||||
{
|
||||
//Yes it will, so set it to inactive and bail out
|
||||
source.WorkorderPreventiveMaintenance.Active = false;
|
||||
source.Save();
|
||||
return dest;
|
||||
}
|
||||
|
||||
#region Reschedule PM
|
||||
#region Reschedule PM
|
||||
|
||||
source.WorkorderPreventiveMaintenance.dtNextServiceDate = dtNext;
|
||||
//Calcs the generate date (threshold date)
|
||||
source.WorkorderPreventiveMaintenance.SetGenerateDate();
|
||||
//WORKORDERITEMS
|
||||
foreach (WorkorderItem wisource in source.WorkorderItems)
|
||||
{
|
||||
source.WorkorderPreventiveMaintenance.dtNextServiceDate = dtNext;
|
||||
//Calcs the generate date (threshold date)
|
||||
source.WorkorderPreventiveMaintenance.SetGenerateDate();
|
||||
//WORKORDERITEMS
|
||||
foreach (WorkorderItem wisource in source.WorkorderItems)
|
||||
{
|
||||
|
||||
wisource.RequestDate = wisource.RequestDate;
|
||||
wisource.RequestDate = wisource.RequestDate;
|
||||
|
||||
|
||||
//PARTS
|
||||
//no date changes required
|
||||
//PARTS
|
||||
//no date changes required
|
||||
|
||||
|
||||
//SCHEDULED USERS
|
||||
foreach (WorkorderItemScheduledUser usersource in wisource.ScheduledUsers)
|
||||
{
|
||||
//Changed: 2-Oct-2006
|
||||
//check to not add a date if the original date was empty
|
||||
if (usersource.StartDate != System.DBNull.Value)
|
||||
usersource.dtStartDate = usersource.dtStartDate.Add(tsToNext);
|
||||
//SCHEDULED USERS
|
||||
foreach (WorkorderItemScheduledUser usersource in wisource.ScheduledUsers)
|
||||
{
|
||||
//Changed: 2-Oct-2006
|
||||
//check to not add a date if the original date was empty
|
||||
if (usersource.StartDate != System.DBNull.Value)
|
||||
usersource.dtStartDate = usersource.dtStartDate.Add(tsToNext);
|
||||
|
||||
if (usersource.StopDate != System.DBNull.Value)
|
||||
usersource.dtStopDate = usersource.dtStopDate.Add(tsToNext);
|
||||
if (usersource.StopDate != System.DBNull.Value)
|
||||
usersource.dtStopDate = usersource.dtStopDate.Add(tsToNext);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//LABOR
|
||||
foreach (WorkorderItemLabor laborsource in wisource.Labors)
|
||||
{
|
||||
//Changed: 2-Oct-2006
|
||||
//check to not add a date if the original date was empty
|
||||
if (laborsource.ServiceStartDate != System.DBNull.Value)
|
||||
laborsource.dtServiceStartDate = laborsource.dtServiceStartDate.Add(tsToNext);
|
||||
//LABOR
|
||||
foreach (WorkorderItemLabor laborsource in wisource.Labors)
|
||||
{
|
||||
//Changed: 2-Oct-2006
|
||||
//check to not add a date if the original date was empty
|
||||
if (laborsource.ServiceStartDate != System.DBNull.Value)
|
||||
laborsource.dtServiceStartDate = laborsource.dtServiceStartDate.Add(tsToNext);
|
||||
|
||||
if (laborsource.ServiceStopDate != System.DBNull.Value)
|
||||
laborsource.dtServiceStopDate = laborsource.dtServiceStopDate.Add(tsToNext);
|
||||
if (laborsource.ServiceStopDate != System.DBNull.Value)
|
||||
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
|
||||
foreach (WorkorderItemTravel travelsource in wisource.Travels)
|
||||
{
|
||||
//Changed: 2-Oct-2006
|
||||
//check to not add a date if the original date was empty
|
||||
if (travelsource.TravelStartDate != DBNull.Value)
|
||||
travelsource.dtTravelStartDate = travelsource.dtTravelStartDate.Add(tsToNext);
|
||||
//TRAVEL
|
||||
foreach (WorkorderItemTravel travelsource in wisource.Travels)
|
||||
{
|
||||
//Changed: 2-Oct-2006
|
||||
//check to not add a date if the original date was empty
|
||||
if (travelsource.TravelStartDate != DBNull.Value)
|
||||
travelsource.dtTravelStartDate = travelsource.dtTravelStartDate.Add(tsToNext);
|
||||
|
||||
if (travelsource.TravelStopDate != DBNull.Value)
|
||||
travelsource.dtTravelStopDate = travelsource.dtTravelStopDate.Add(tsToNext);
|
||||
if (travelsource.TravelStopDate != DBNull.Value)
|
||||
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
|
||||
#endregion reschedule pm
|
||||
}//foreach workorderitem loop
|
||||
#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
|
||||
try
|
||||
{
|
||||
source = (Workorder)source.Save();
|
||||
}
|
||||
catch (Exception exx)
|
||||
{
|
||||
dest.Delete();
|
||||
dest.Save();
|
||||
//crack the exception
|
||||
while (exx.InnerException != null)
|
||||
exx = exx.InnerException;
|
||||
|
||||
Memo mwarn = Memo.NewItem();
|
||||
mwarn.ToID = User.AdministratorID;
|
||||
|
||||
//case 3826
|
||||
if (User.CurrentUserType == UserTypes.Utility)
|
||||
{
|
||||
//Utility accounts should not be sending memos, it fucks up downstream
|
||||
//trying to view the memo, also it's confusing
|
||||
mwarn.FromID = User.AdministratorID;
|
||||
}
|
||||
else
|
||||
{
|
||||
mwarn.FromID = User.CurrentThreadUserID;
|
||||
}
|
||||
|
||||
|
||||
mwarn.Subject = "SYSTEM WARNING: Preventive Maintenance WO PROBLEM";
|
||||
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 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("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("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("=================================");
|
||||
sb.AppendLine("Exception saving source PM:");
|
||||
sb.AppendLine(exx.Message);
|
||||
sb.AppendLine("=================================");
|
||||
string sSourceErr = source.GetBrokenRulesString();
|
||||
if (!string.IsNullOrWhiteSpace(sSourceErr))
|
||||
{
|
||||
sb.AppendLine("Broken business rules on PM object:");
|
||||
sb.AppendLine(sSourceErr);
|
||||
sb.AppendLine("==============================");
|
||||
}
|
||||
mwarn.Message = sb.ToString();
|
||||
mwarn.Save();
|
||||
throw new System.ApplicationException("Workorder->NewServiceWorkorderFromPM: Error during service workorder generation. Memo with details sent to Administrator account.");
|
||||
|
||||
|
||||
|
||||
}
|
||||
//case 1959 try catch block added to prevent infinite generation issue
|
||||
try
|
||||
{
|
||||
source = (Workorder)source.Save();
|
||||
}
|
||||
catch (Exception exx)
|
||||
{
|
||||
dest.Delete();
|
||||
dest.Save();
|
||||
//crack the exception
|
||||
while (exx.InnerException != null)
|
||||
exx = exx.InnerException;
|
||||
|
||||
Memo mwarn = Memo.NewItem();
|
||||
mwarn.ToID = User.AdministratorID;
|
||||
|
||||
//case 3826
|
||||
if (User.CurrentUserType == UserTypes.Utility)
|
||||
{
|
||||
//Utility accounts should not be sending memos, it fucks up downstream
|
||||
//trying to view the memo, also it's confusing
|
||||
mwarn.FromID = User.AdministratorID;
|
||||
}
|
||||
else
|
||||
{
|
||||
mwarn.FromID = User.CurrentThreadUserID;
|
||||
}
|
||||
|
||||
//case 1630
|
||||
//copy wikipage from pm to service workorder
|
||||
if (dest.CanWiki && source.HasWiki)
|
||||
{
|
||||
try
|
||||
{
|
||||
WikiPage wpSource = WikiPage.GetItem(new TypeAndID(RootObjectTypes.WorkorderPreventiveMaintenance, source.ID));
|
||||
WikiPage wpDest = WikiPage.GetItem(new TypeAndID(RootObjectTypes.WorkorderService, dest.ID));
|
||||
wpDest.SetContent(wpSource.GetContent());
|
||||
wpDest.Save();
|
||||
}
|
||||
catch { };
|
||||
|
||||
}
|
||||
|
||||
return dest;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Calculate generate date based on service date and
|
||||
/// threshold span and unit
|
||||
/// </summary>
|
||||
internal void SetGenerateDate()
|
||||
{
|
||||
if (this.mNextServiceDate.IsEmpty) return;
|
||||
if (this.mThresholdSpan == 0)
|
||||
{
|
||||
this.mGenerateDate = this.mNextServiceDate;
|
||||
MarkDirty();
|
||||
return;
|
||||
}
|
||||
mGenerateDate = new SmartDate(Workorder.GetDateFromSpanAndUnit(mNextServiceDate.Date, this.mThresholdSpanUnit, -mThresholdSpan));
|
||||
MarkDirty();
|
||||
}
|
||||
|
||||
|
||||
#region Date time calcs helpers
|
||||
//Takes an AyaNova day of week and returns
|
||||
//a System.DayOfWeek
|
||||
//Assumes that AyaDayOfWeek is NOT "AnyDay"
|
||||
internal static System.DayOfWeek AyaToSystemDayOfWeek(AyaDayOfWeek day)
|
||||
{
|
||||
switch (day)
|
||||
{
|
||||
case AyaDayOfWeek.Monday:
|
||||
return DayOfWeek.Monday;
|
||||
case AyaDayOfWeek.Tuesday:
|
||||
return DayOfWeek.Tuesday;
|
||||
case AyaDayOfWeek.Wednesday:
|
||||
return DayOfWeek.Wednesday;
|
||||
case AyaDayOfWeek.Thursday:
|
||||
return DayOfWeek.Thursday;
|
||||
case AyaDayOfWeek.Friday:
|
||||
return DayOfWeek.Friday;
|
||||
case AyaDayOfWeek.Saturday:
|
||||
return DayOfWeek.Saturday;
|
||||
case AyaDayOfWeek.Sunday:
|
||||
return DayOfWeek.Sunday;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
throw new System.ArgumentOutOfRangeException("DayOfWeekConverter: AyaDayOfWeek.AnyDayOfWeek is not supported");
|
||||
}
|
||||
|
||||
|
||||
internal static DateTime GetDateFromSpanAndUnit(DateTime StartDate, AyaUnitsOfTime unit, int multiple)
|
||||
{
|
||||
switch (unit)
|
||||
{
|
||||
case AyaUnitsOfTime.Seconds:
|
||||
return StartDate.AddSeconds(multiple);
|
||||
|
||||
case AyaUnitsOfTime.Minutes:
|
||||
return StartDate.AddMinutes(multiple);
|
||||
|
||||
case AyaUnitsOfTime.Hours:
|
||||
return StartDate.AddHours(multiple);
|
||||
mwarn.Subject = "SYSTEM WARNING: Preventive Maintenance WO PROBLEM";
|
||||
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 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("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("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("=================================");
|
||||
sb.AppendLine("Exception saving source PM:");
|
||||
sb.AppendLine(exx.Message);
|
||||
sb.AppendLine("=================================");
|
||||
string sSourceErr = source.GetBrokenRulesString();
|
||||
if (!string.IsNullOrWhiteSpace(sSourceErr))
|
||||
{
|
||||
sb.AppendLine("Broken business rules on PM object:");
|
||||
sb.AppendLine(sSourceErr);
|
||||
sb.AppendLine("==============================");
|
||||
}
|
||||
mwarn.Message = sb.ToString();
|
||||
mwarn.Save();
|
||||
throw new System.ApplicationException("Workorder->NewServiceWorkorderFromPM: Error during service workorder generation. Memo with details sent to Administrator account.");
|
||||
|
||||
case AyaUnitsOfTime.Days:
|
||||
return StartDate.AddDays(multiple);
|
||||
|
||||
case AyaUnitsOfTime.Weeks:
|
||||
throw new System.NotSupportedException("GetDateFromSpanAndUnit: Weeks not supported");
|
||||
|
||||
case AyaUnitsOfTime.Months:
|
||||
return StartDate.AddMonths(multiple);
|
||||
}
|
||||
|
||||
case AyaUnitsOfTime.Years:
|
||||
return StartDate.AddYears(multiple);
|
||||
//case 1630
|
||||
//copy wikipage from pm to service workorder
|
||||
if (dest.CanWiki && source.HasWiki)
|
||||
{
|
||||
try
|
||||
{
|
||||
WikiPage wpSource = WikiPage.GetItem(new TypeAndID(RootObjectTypes.WorkorderPreventiveMaintenance, source.ID));
|
||||
WikiPage wpDest = WikiPage.GetItem(new TypeAndID(RootObjectTypes.WorkorderService, dest.ID));
|
||||
wpDest.SetContent(wpSource.GetContent());
|
||||
wpDest.Save();
|
||||
}
|
||||
catch { };
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
return dest;
|
||||
|
||||
//fail safe:
|
||||
return StartDate;
|
||||
}
|
||||
|
||||
*/
|
||||
#endregion gen service wo from pm
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Calculate generate date based on service date and
|
||||
/// threshold span and unit
|
||||
/// </summary>
|
||||
internal void SetGenerateDate()
|
||||
{
|
||||
if (this.mNextServiceDate.IsEmpty) return;
|
||||
if (this.mThresholdSpan == 0)
|
||||
{
|
||||
this.mGenerateDate = this.mNextServiceDate;
|
||||
MarkDirty();
|
||||
return;
|
||||
}
|
||||
mGenerateDate = new SmartDate(Workorder.GetDateFromSpanAndUnit(mNextServiceDate.Date, this.mThresholdSpanUnit, -mThresholdSpan));
|
||||
MarkDirty();
|
||||
}
|
||||
|
||||
|
||||
#region Date time calcs helpers
|
||||
//Takes an AyaNova day of week and returns
|
||||
//a System.DayOfWeek
|
||||
//Assumes that AyaDayOfWeek is NOT "AnyDay"
|
||||
internal static System.DayOfWeek AyaToSystemDayOfWeek(AyaDayOfWeek day)
|
||||
{
|
||||
switch (day)
|
||||
{
|
||||
case AyaDayOfWeek.Monday:
|
||||
return DayOfWeek.Monday;
|
||||
case AyaDayOfWeek.Tuesday:
|
||||
return DayOfWeek.Tuesday;
|
||||
case AyaDayOfWeek.Wednesday:
|
||||
return DayOfWeek.Wednesday;
|
||||
case AyaDayOfWeek.Thursday:
|
||||
return DayOfWeek.Thursday;
|
||||
case AyaDayOfWeek.Friday:
|
||||
return DayOfWeek.Friday;
|
||||
case AyaDayOfWeek.Saturday:
|
||||
return DayOfWeek.Saturday;
|
||||
case AyaDayOfWeek.Sunday:
|
||||
return DayOfWeek.Sunday;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
throw new System.ArgumentOutOfRangeException("DayOfWeekConverter: AyaDayOfWeek.AnyDayOfWeek is not supported");
|
||||
}
|
||||
|
||||
|
||||
internal static DateTime GetDateFromSpanAndUnit(DateTime StartDate, AyaUnitsOfTime unit, int multiple)
|
||||
{
|
||||
switch (unit)
|
||||
{
|
||||
case AyaUnitsOfTime.Seconds:
|
||||
return StartDate.AddSeconds(multiple);
|
||||
|
||||
case AyaUnitsOfTime.Minutes:
|
||||
return StartDate.AddMinutes(multiple);
|
||||
|
||||
case AyaUnitsOfTime.Hours:
|
||||
return StartDate.AddHours(multiple);
|
||||
|
||||
case AyaUnitsOfTime.Days:
|
||||
return StartDate.AddDays(multiple);
|
||||
|
||||
case AyaUnitsOfTime.Weeks:
|
||||
throw new System.NotSupportedException("GetDateFromSpanAndUnit: Weeks not supported");
|
||||
|
||||
case AyaUnitsOfTime.Months:
|
||||
return StartDate.AddMonths(multiple);
|
||||
|
||||
case AyaUnitsOfTime.Years:
|
||||
return StartDate.AddYears(multiple);
|
||||
|
||||
|
||||
}
|
||||
|
||||
//fail safe:
|
||||
return StartDate;
|
||||
}
|
||||
|
||||
*/
|
||||
#endregion gen service wo from pm
|
||||
|
||||
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();
|
||||
// }
|
||||
|
||||
|
||||
|
||||
@@ -1156,7 +1146,7 @@ namespace AyaNova.Biz
|
||||
return;//this is a completely disqualifying error
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
todo: quote status list first, it's a table of created items, keep properties from v7 but add the following properties:
|
||||
@@ -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
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
80
server/AyaNova/generator/CoreJobPMGenerate.cs
Normal file
80
server/AyaNova/generator/CoreJobPMGenerate.cs
Normal 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
|
||||
|
||||
Reference in New Issue
Block a user