diff --git a/server/AyaNova/Controllers/UnitController.cs b/server/AyaNova/Controllers/UnitController.cs index b10b11b3..0709f838 100644 --- a/server/AyaNova/Controllers/UnitController.cs +++ b/server/AyaNova/Controllers/UnitController.cs @@ -61,31 +61,7 @@ namespace AyaNova.Api.Controllers else return CreatedAtAction(nameof(UnitController.GetUnit), new { id = o.Id, version = apiVersion.ToString() }, new ApiCreatedResponse(o)); } - - // /// - // /// Duplicate Unit - // /// (Wiki and Attachments are not duplicated) - // /// - // /// Source object id - // /// From route path - // /// Unit - // [HttpPost("duplicate/{id}")] - // public async Task DuplicateUnit([FromRoute] long id, ApiVersion apiVersion) - // { - // if (!serverState.IsOpen) - // return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); - // UnitBiz biz = UnitBiz.GetBiz(ct, HttpContext); - // if (!Authorized.HasCreateRole(HttpContext.Items, biz.BizType)) - // return StatusCode(403, new ApiNotAuthorizedResponse()); - // if (!ModelState.IsValid) - // return BadRequest(new ApiErrorResponse(ModelState)); - // Unit o = await biz.DuplicateAsync(id); - // if (o == null) - // return BadRequest(new ApiErrorResponse(biz.Errors)); - // else - // return CreatedAtAction(nameof(UnitController.GetUnit), new { id = o.Id, version = apiVersion.ToString() }, new ApiCreatedResponse(o)); - // } - + /// /// Get Unit /// @@ -375,5 +351,29 @@ namespace AyaNova.Api.Controllers } + /// + /// Create Unit Meter Reading entry + /// + /// + /// From route path + /// + [HttpPost("meter-reading")] + public async Task PostUnitMeterReading([FromBody] UnitMeterReading newObject, ApiVersion apiVersion) + { + if (!serverState.IsOpen) + return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); + UnitBiz biz = UnitBiz.GetBiz(ct, HttpContext); + if (!Authorized.HasCreateRole(HttpContext.Items, biz.BizType)) + return StatusCode(403, new ApiNotAuthorizedResponse()); + if (!ModelState.IsValid) + return BadRequest(new ApiErrorResponse(ModelState)); + UnitMeterReading o = await biz.CreateMeterReadingAsync(newObject); + if (o == null) + return BadRequest(new ApiErrorResponse(biz.Errors)); + else + return CreatedAtAction(nameof(UnitController.GetUnit), new { id = o.UnitId, version = apiVersion.ToString() }, new ApiCreatedResponse(o)); + } + + }//eoc }//eons \ No newline at end of file diff --git a/server/AyaNova/biz/UnitBiz.cs b/server/AyaNova/biz/UnitBiz.cs index 1431c76f..1a40838d 100644 --- a/server/AyaNova/biz/UnitBiz.cs +++ b/server/AyaNova/biz/UnitBiz.cs @@ -60,39 +60,6 @@ namespace AyaNova.Biz } } - // //////////////////////////////////////////////////////////////////////////////////////////////// - // //DUPLICATE - // // - // internal async Task DuplicateAsync(long id) - // { - // var dbObject = await GetAsync(id, false); - // if (dbObject == null) - // { - // AddError(ApiErrorCode.NOT_FOUND, "id"); - // return null; - // } - // var newObject = new Unit(); - // CopyObject.Copy(dbObject, newObject, "Wiki"); - // string newUniqueName = string.Empty; - // bool NotUnique = true; - // long l = 1; - // do - // { - // newUniqueName = Util.StringUtil.UniqueNameBuilder(dbObject.Serial, l++, 255); - // NotUnique = await ct.Unit.AnyAsync(z => z.Serial == newUniqueName); - // } while (NotUnique); - // newObject.Serial = newUniqueName; - // newObject.Id = 0; - // newObject.Concurrency = 0; - // await ct.Unit.AddAsync(newObject); - // await ct.SaveChangesAsync(); - // await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, newObject.Id, BizType, AyaEvent.Created), ct); - // await SearchIndexAsync(newObject, true); - // await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null); - // await HandlePotentialNotificationEvent(AyaEvent.Created, newObject); - // return newObject; - // } - //////////////////////////////////////////////////////////////////////////////////////////////// //GET // @@ -467,7 +434,7 @@ namespace AyaNova.Biz public async Task HandlePotentialNotificationEvent(AyaEvent ayaEvent, ICoreBizObjectModel proposedObj, ICoreBizObjectModel currentObj = null) { ILogger log = AyaNova.Util.ApplicationLogging.CreateLogger(); - if(ServerBootConfig.SEEDING || ServerBootConfig.MIGRATING) return; + if (ServerBootConfig.SEEDING || ServerBootConfig.MIGRATING) return; log.LogDebug($"HandlePotentialNotificationEvent processing: [AyaType:{this.BizType}, AyaEvent:{ayaEvent}]"); bool isNew = currentObj == null; @@ -581,21 +548,123 @@ namespace AyaNova.Biz }//Contract expiry event - //#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 + ////////////////// METER READING ////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////////////// + //CREATE + // + internal async Task CreateMeterReadingAsync(UnitMeterReading newObject) + { + await ValidateMeterReadingAsync(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 TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, newObject.Tags, null); + await MeterReadingHandlePotentialNotificationEvent(AyaEvent.Created, newObject); + return newObject; + } + } + + + + + private async Task ValidateMeterReadingAsync(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.WorkOrderItemId!=null){ + if(!await ct.WorkOrderItem.AnyAsync(z=>z.Id==proposedObj.WorkOrderItemId)){ + AddError(ApiErrorCode.VALIDATION_INVALID_VALUE, "WorkOrderItemId", "work order item id was not found");//api issue not user issue so no need to translate + return; + } + } + + } + + + public async Task MeterReadingHandlePotentialNotificationEvent(AyaEvent ayaEvent, UnitMeterReading proposedObj) + { + ILogger log = AyaNova.Util.ApplicationLogging.CreateLogger(); + if (ServerBootConfig.SEEDING || ServerBootConfig.MIGRATING) return; + log.LogDebug($"HandlePotentialNotificationEvent processing: [AyaType:{AyaType.UnitMeterReading}, AyaEvent:{ayaEvent}]"); + + + + //## CREATED EVENTS (only ever created) + if (ayaEvent == AyaEvent.Created || ayaEvent == AyaEvent.Modified) + { + + // //# CONTRACT EXPIRY + // { + // if (o.ContractId != null && o.ContractExpires != null) + // { + // var ContractExpirydate = (DateTime)o.ContractExpires; + // //notify users about contract expiry (time delayed) + // var subs = await ct.NotifySubscription.Where(z => z.EventType == NotifyEventType.ContractExpiring).ToListAsync(); + // foreach (var sub in subs) + // { + // //not for inactive users + // if (!await UserBiz.UserIsActive(sub.UserId)) continue; + + // //Tag match? (will be true if no sub tags so always safe to call this) + // if (NotifyEventHelper.ObjectHasAllSubscriptionTags(o.Tags, sub.Tags)) + // { + // NotifyEvent n = new NotifyEvent() + // { + // EventType = NotifyEventType.ContractExpiring, + // UserId = sub.UserId, + // AyaType = o.AyaType, + // ObjectId = o.Id, + // NotifySubscriptionId = sub.Id, + // Name = o.Serial, + // EventDate = ContractExpirydate + // }; + // await ct.NotifyEvent.AddAsync(n); + // log.LogDebug($"Adding NotifyEvent: [{n.ToString()}]"); + // await ct.SaveChangesAsync(); + // } + // } + // } + // }//Contract expiry event + + + + } + + + }//end of process notifications + + //#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 + + //} ///////////////////////////////////////////////////////////////////// diff --git a/server/AyaNova/models/AyContext.cs b/server/AyaNova/models/AyContext.cs index 511819b0..06636b91 100644 --- a/server/AyaNova/models/AyContext.cs +++ b/server/AyaNova/models/AyContext.cs @@ -57,6 +57,7 @@ namespace AyaNova.Models public virtual DbSet PurchaseOrderItem { get; set; } public virtual DbSet Unit { get; set; } public virtual DbSet UnitModel { get; set; } + public virtual DbSet UnitMeterReading { get; set; } public virtual DbSet Vendor { get; set; } public virtual DbSet TaxCode { get; set; } public virtual DbSet ServiceRate { get; set; }