using System; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using System.Linq; using AyaNova.Util; using AyaNova.Api.ControllerHelpers; using Microsoft.Extensions.Logging; using AyaNova.Models; using Newtonsoft.Json.Linq; using System.Collections.Generic; using Newtonsoft.Json; namespace AyaNova.Biz { internal class UnitMeterReadingBiz : BizObject, ISearchAbleObject, IReportAbleObject, IExportAbleObject { internal UnitMeterReadingBiz(AyContext dbcontext, long currentUserId, long userTranslationId, AuthorizationRoles UserRoles) { ct = dbcontext; UserId = currentUserId; UserTranslationId = userTranslationId; CurrentUserRoles = UserRoles; BizType = AyaType.UnitMeterReading; } internal static UnitMeterReadingBiz GetBiz(AyContext ct, Microsoft.AspNetCore.Http.HttpContext httpContext = null) { if (httpContext != null) return new UnitMeterReadingBiz(ct, UserIdFromContext.Id(httpContext.Items), UserTranslationIdFromContext.Id(httpContext.Items), UserRolesFromContext.Roles(httpContext.Items)); else return new UnitMeterReadingBiz(ct, 1, ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION_ID, AuthorizationRoles.BizAdmin); } //////////////////////////////////////////////////////////////////////////////////////////////// //EXISTS internal async Task ExistsAsync(long id) { return await ct.UnitMeterReading.AnyAsync(z => z.Id == id); } //////////////////////////////////////////////////////////////////////////////////////////////// //CREATE // internal async Task CreateAsync(UnitMeterReading newObject) { await ValidateAsync(newObject); if (HasErrors) return null; else { await ct.UnitMeterReading.AddAsync(newObject); await ct.SaveChangesAsync(); await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, BizType, AyaEvent.Created), ct); await SearchIndexAsync(newObject, true); await HandlePotentialNotificationEvent(AyaEvent.Created, newObject); return newObject; } } //////////////////////////////////////////////////////////////////////////////////////////////// //GET // internal async Task GetAsync(long id, bool logTheGetEvent = true) { var ret = await ct.UnitMeterReading.AsNoTracking().SingleOrDefaultAsync(m => m.Id == id); if (logTheGetEvent && ret != null) await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, id, BizType, AyaEvent.Retrieved), ct); return ret; } //////////////////////////////////////////////////////////////////////////////////////////////// //SEARCH // private async Task SearchIndexAsync(UnitMeterReading obj, bool isNew) { var SearchParams = new Search.SearchIndexProcessObjectParameters(UserTranslationId, obj.Id, BizType); DigestSearchText(obj, SearchParams); if (isNew) await Search.ProcessNewObjectKeywordsAsync(SearchParams); else await Search.ProcessUpdatedObjectKeywordsAsync(SearchParams); } public async Task GetSearchResultSummary(long id) { var obj = await GetAsync(id, false); var SearchParams = new Search.SearchIndexProcessObjectParameters(); DigestSearchText(obj, SearchParams); return SearchParams; } public void DigestSearchText(UnitMeterReading obj, Search.SearchIndexProcessObjectParameters searchParams) { if (obj != null) searchParams.AddText(obj.Notes) .AddText(obj.Meter); } //////////////////////////////////////////////////////////////////////////////////////////////// //VALIDATION // private async Task ValidateAsync(UnitMeterReading proposedObj) { //Unit required var unit = await ct.Unit.AsNoTracking().FirstOrDefaultAsync(z => z.Id == proposedObj.UnitId); if (unit == null) { AddError(ApiErrorCode.VALIDATION_INVALID_VALUE, "UnitId", "Unit not found with that id");//api issue not user issue so no need to translate return; } if (!unit.Metered) { AddError(ApiErrorCode.VALIDATION_INVALID_VALUE, "UnitId", "This is not a metered unit, reading cannot be saved");//api issue not user issue so no need to translate return; } if (proposedObj.WorkOrderItemUnitId != null) { if (!await ct.WorkOrderItemUnit.AnyAsync(z => z.Id == proposedObj.WorkOrderItemUnitId)) { AddError(ApiErrorCode.VALIDATION_INVALID_VALUE, "WorkOrderItemUnitId", "work order item unit record was not found");//api issue not user issue so no need to translate return; } } } //////////////////////////////////////////////////////////////////////////////////////////////// //REPORTING // public async Task GetReportData(DataListSelectedRequest dataListSelectedRequest) { var idList = dataListSelectedRequest.SelectedRowIds; 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.UnitMeterReading.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 (UnitMeterReading w in orderedList) { await PopulateVizFields(w); var jo = JObject.FromObject(w); ReportData.Add(jo); } } return ReportData; } //populate viz fields from provided object private async Task PopulateVizFields(UnitMeterReading o) { o.UnitViz = await ct.Unit.AsNoTracking().Where(x => x.Id == o.UnitId).Select(x => x.Serial).FirstOrDefaultAsync(); if (o.WorkOrderItemUnitId != null) o.WorkOrderViz = (await WorkOrderBiz.GetWorkOrderSerialFromRelativeAsync(AyaType.WorkOrderItemUnit, (long)o.WorkOrderItemUnitId, ct)).ToString(); } //////////////////////////////////////////////////////////////////////////////////////////////// // IMPORT EXPORT // public async Task GetExportData(DataListSelectedRequest dataListSelectedRequest) { //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(dataListSelectedRequest); } //////////////////////////////////////////////////////////////////////////////////////////////// // NOTIFICATION PROCESSING // public async Task HandlePotentialNotificationEvent(AyaEvent ayaEvent, UnitMeterReading proposedObj) { ILogger log = AyaNova.Util.ApplicationLogging.CreateLogger(); if (ServerBootConfig.SEEDING || ServerBootConfig.MIGRATING) return; log.LogDebug($"HandlePotentialNotificationEvent processing: [AyaType:{this.BizType}, AyaEvent:{ayaEvent}]"); await Task.CompletedTask; //SPECIFIC EVENTS FOR THIS OBJECT //#todo: METER READING EVENT //MIGRATE_OUTSTANDING need meter reading object to complete unit notification for UnitMeterReadingMultipleExceeded //UnitMeterReadingMultipleExceeded = 26,//* UnitMeterReading object, Created, conditional on DecValue as the Multiple threshold, if passed then notifies //{ //first remove any existing, potentially stale notifyevents for this exact object and notifyeventtype //await NotifyEventHelper.ClearPriorEventsForObject(ct, AyaType.Unit, o.Id, NotifyEventType.UnitMeterReadingMultipleExceeded); //then check if unit is still metered etc etc and do the rest once the unit meter reading is coded //} }//end of process notifications ///////////////////////////////////////////////////////////////////// }//eoc }//eons