This commit is contained in:
2021-02-16 15:05:13 +00:00
parent 5905a52493
commit 01cd6d63f0
3 changed files with 139 additions and 6 deletions

View File

@@ -1,13 +1,18 @@
using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging; using System.Linq;
using AyaNova.Util; using AyaNova.Util;
using AyaNova.Api.ControllerHelpers; using AyaNova.Api.ControllerHelpers;
using Microsoft.Extensions.Logging;
using AyaNova.Models; using AyaNova.Models;
using Newtonsoft.Json.Linq;
using System.Collections.Generic;
using Newtonsoft.Json;
namespace AyaNova.Biz namespace AyaNova.Biz
{ {
internal class PurchaseOrderBiz : BizObject, ISearchAbleObject, INotifiableObject internal class PurchaseOrderBiz : BizObject, IJobObject, ISearchAbleObject, IReportAbleObject, IExportAbleObject, INotifiableObject
{ {
internal PurchaseOrderBiz(AyContext dbcontext, long currentUserId, long userTranslationId, AuthorizationRoles UserRoles) internal PurchaseOrderBiz(AyContext dbcontext, long currentUserId, long userTranslationId, AuthorizationRoles UserRoles)
{ {
@@ -256,12 +261,140 @@ namespace AyaNova.Biz
} }
////////////////////////////////////////////////////////////////////////////////////////////////
//REPORTING
//
public async Task<JArray> GetReportData(long[] idList)
{
JArray ReportData = new JArray();
while (idList.Any())
{
var batch = idList.Take(IReportAbleObject.REPORT_DATA_BATCH_SIZE);
idList = idList.Skip(IReportAbleObject.REPORT_DATA_BATCH_SIZE).ToArray();
//query for this batch, comes back in db natural order unfortunately
var batchResults = await ct.Project.AsNoTracking().Where(z => batch.Contains(z.Id)).ToArrayAsync();
//order the results back into original
var orderedList = from id in batch join z in batchResults on id equals z.Id select z;
foreach (Project w in orderedList)
{
var jo = JObject.FromObject(w);
if (!JsonUtil.JTokenIsNullOrEmpty(jo["CustomFields"]))
jo["CustomFields"] = JObject.Parse((string)jo["CustomFields"]);
ReportData.Add(jo);
}
}
return ReportData;
}
////////////////////////////////////////////////////////////////////////////////////////////////
// IMPORT EXPORT
//
public async Task<JArray> GetExportData(long[] idList)
{
//for now just re-use the report data code
//this may turn out to be the pattern for most biz object types but keeping it seperate allows for custom usage from time to time
return await GetReportData(idList);
}
////////////////////////////////////////////////////////////////////////////////////////////////
//JOB / OPERATIONS
//
public async Task HandleJobAsync(OpsJob job)
{
//Hand off the particular job to the corresponding processing code
//NOTE: If this code throws an exception the caller (JobsBiz::ProcessJobsAsync) will automatically set the job to failed and log the exeption so
//basically any error condition during job processing should throw up an exception if it can't be handled
switch (job.JobType)
{
case JobType.BatchCoreObjectOperation:
await ProcessBatchJobAsync(job);
break;
default:
throw new System.ArgumentOutOfRangeException($"PurchaseOrderBiz.HandleJob-> Invalid job type{job.JobType.ToString()}");
}
}
private async Task ProcessBatchJobAsync(OpsJob job)
{
await JobsBiz.UpdateJobStatusAsync(job.GId, JobStatus.Running);
await JobsBiz.LogJobAsync(job.GId, $"LT:StartJob {job.SubType}");
List<long> idList = new List<long>();
long FailedObjectCount = 0;
JObject jobData = JObject.Parse(job.JobInfo);
if (jobData.ContainsKey("idList"))
idList = ((JArray)jobData["idList"]).ToObject<List<long>>();
else
idList = await ct.PurchaseOrder.AsNoTracking().Select(z => z.Id).ToListAsync();
bool SaveIt = false;
foreach (long id in idList)
{
try
{
SaveIt = false;
ClearErrors();
PurchaseOrder o = null;
//save a fetch if it's a delete
if (job.SubType != JobSubType.Delete)
o = await GetAsync(id, false);
switch (job.SubType)
{
case JobSubType.TagAddAny:
case JobSubType.TagAdd:
case JobSubType.TagRemoveAny:
case JobSubType.TagRemove:
case JobSubType.TagReplaceAny:
case JobSubType.TagReplace:
SaveIt = TagBiz.ProcessBatchTagOperation(o.Tags, (string)jobData["tag"], jobData.ContainsKey("toTag") ? (string)jobData["toTag"] : null, job.SubType);
break;
case JobSubType.Delete:
if (!await DeleteAsync(id))
{
await JobsBiz.LogJobAsync(job.GId, $"LT:Errors {GetErrorsAsString()} id {id}");
FailedObjectCount++;
}
break;
default:
throw new System.ArgumentOutOfRangeException($"ProcessBatchJobAsync -> Invalid job Subtype{job.SubType}");
}
if (SaveIt)
{
o = await PutAsync(o);
if (o == null)
{
await JobsBiz.LogJobAsync(job.GId, $"LT:Errors {GetErrorsAsString()} id {id}");
FailedObjectCount++;
}
}
}
catch (Exception ex)
{
await JobsBiz.LogJobAsync(job.GId, $"LT:Errors id({id})");
await JobsBiz.LogJobAsync(job.GId, ExceptionUtil.ExtractAllExceptionMessages(ex));
}
}
await JobsBiz.LogJobAsync(job.GId, $"LT:BatchJob {job.SubType} {idList.Count}{(FailedObjectCount > 0 ? " - LT:Failed " + FailedObjectCount : "")}");
await JobsBiz.UpdateJobStatusAsync(job.GId, JobStatus.Completed);
}
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
// NOTIFICATION PROCESSING // NOTIFICATION PROCESSING
// //
public async Task HandlePotentialNotificationEvent(AyaEvent ayaEvent, ICoreBizObjectModel proposedObj, ICoreBizObjectModel currentObj = null) public async Task HandlePotentialNotificationEvent(AyaEvent ayaEvent, ICoreBizObjectModel proposedObj, ICoreBizObjectModel currentObj = null)
{ {
ILogger log = AyaNova.Util.ApplicationLogging.CreateLogger<PurchaseOrderBiz>(); ILogger log = AyaNova.Util.ApplicationLogging.CreateLogger<ProjectBiz>();
if (ServerBootConfig.SEEDING) return; if (ServerBootConfig.SEEDING) return;
log.LogDebug($"HandlePotentialNotificationEvent processing: [AyaType:{this.BizType}, AyaEvent:{ayaEvent}]"); log.LogDebug($"HandlePotentialNotificationEvent processing: [AyaType:{this.BizType}, AyaEvent:{ayaEvent}]");

View File

@@ -730,8 +730,7 @@ $BODY$ LANGUAGE PLPGSQL STABLE");
"notes TEXT, wiki TEXT, customfields TEXT, tags VARCHAR(255) ARRAY, " + "notes TEXT, wiki TEXT, customfields TEXT, tags VARCHAR(255) ARRAY, " +
"datestarted TIMESTAMP NULL, datecompleted TIMESTAMP NULL, projectoverseerid BIGINT NULL REFERENCES auser(id), accountnumber TEXT)"); "datestarted TIMESTAMP NULL, datecompleted TIMESTAMP NULL, projectoverseerid BIGINT NULL REFERENCES auser(id), accountnumber TEXT)");
//PURCHASEORDER //PURCHASEORDER
//Note don't forget to update name fetcher stored procedure when change this to serial from name
await ExecQueryAsync("CREATE TABLE apurchaseorder (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, serial BIGINT generated by default as identity NOT NULL, " + await ExecQueryAsync("CREATE TABLE apurchaseorder (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, serial BIGINT generated by default as identity NOT NULL, " +
"notes TEXT, wiki TEXT, customfields TEXT, tags VARCHAR(255) ARRAY, " + "notes TEXT, wiki TEXT, customfields TEXT, tags VARCHAR(255) ARRAY, " +
"vendormemo TEXT, dropshiptocustomerid BIGINT REFERENCES acustomer, referencenumber TEXT, vendorid BIGINT NOT NULL REFERENCES avendor, " + "vendormemo TEXT, dropshiptocustomerid BIGINT REFERENCES acustomer, referencenumber TEXT, vendorid BIGINT NOT NULL REFERENCES avendor, " +

View File

@@ -324,6 +324,7 @@ namespace AyaNova.Util
await EraseTableAsync("asearchkey", conn); await EraseTableAsync("asearchkey", conn);
await EraseTableAsync("asearchdictionary", conn); await EraseTableAsync("asearchdictionary", conn);
await EraseTableAsync("atag", conn); await EraseTableAsync("atag", conn);
await EraseTableAsync("apurchaseorder", conn);
await EraseTableAsync("aunit", conn); await EraseTableAsync("aunit", conn);
await EraseTableAsync("acustomernote", conn); await EraseTableAsync("acustomernote", conn);
await EraseTableAsync("acustomer", conn); await EraseTableAsync("acustomer", conn);
@@ -339,7 +340,7 @@ namespace AyaNova.Util
await EraseTableAsync("apmtemplateitem", conn); await EraseTableAsync("apmtemplateitem", conn);
await EraseTableAsync("apmtemplate", conn); await EraseTableAsync("apmtemplate", conn);
await EraseTableAsync("apurchaseorder", conn);
await EraseTableAsync("aquoteitem", conn); await EraseTableAsync("aquoteitem", conn);
await EraseTableAsync("aquote", conn); await EraseTableAsync("aquote", conn);
await EraseTableAsync("aquotetemplateitem", conn); await EraseTableAsync("aquotetemplateitem", conn);