diff --git a/server/AyaNova/Controllers/PMController.cs b/server/AyaNova/Controllers/PMController.cs
index 148d7d66..f66768cc 100644
--- a/server/AyaNova/Controllers/PMController.cs
+++ b/server/AyaNova/Controllers/PMController.cs
@@ -3,7 +3,6 @@ using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization;
-using Microsoft.AspNetCore.JsonPatch;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using AyaNova.Models;
@@ -115,59 +114,19 @@ namespace AyaNova.Api.Controllers
- ///
- /// Patch (update) PM
- ///
- ///
- ///
- ///
- ///
- [HttpPatch("{id}/{concurrencyToken}")]
- public async Task PatchPM([FromRoute] long id, [FromRoute] uint concurrencyToken, [FromBody]JsonPatchDocument objectPatch)
- {
- //https://dotnetcoretutorials.com/2017/11/29/json-patch-asp-net-core/
- if (!serverState.IsOpen)
- return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));
-
- if (!ModelState.IsValid)
- return BadRequest(new ApiErrorResponse(ModelState));
-
- //Instantiate the business object handler
- PMBiz biz = PMBiz.GetBiz(ct, HttpContext);
-
- var o = await biz.GetAsync(id, false);
- if (o == null)
- return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND));
-
- if (!Authorized.HasModifyRole(HttpContext.Items, biz.BizType))
- return StatusCode(403, new ApiNotAuthorizedResponse());
-
- try
- {
- //patch and validate
- if (!await biz.PatchAsync(o, objectPatch, concurrencyToken))
- return BadRequest(new ApiErrorResponse(biz.Errors));
- }
- catch (DbUpdateConcurrencyException)
- {
- if (!await biz.ExistsAsync(id))
- return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND));
- else
- return StatusCode(409, new ApiErrorResponse(ApiErrorCode.CONCURRENCY_CONFLICT));
- }
- return Ok(ApiOkResponse.Response(new { ConcurrencyToken = o.ConcurrencyToken }, true));
- }
///
/// Post PM
///
- ///
+ ///
+ ///
+ /// force a workorder number, leave null to autogenerate the next one in sequence (mostly used for import)
/// Automatically filled from route path, no need to specify in body
- ///
- [HttpPost]
- public async Task PostPM([FromBody] PM inObj, ApiVersion apiVersion)
+ /// A created workorder ready to fill out
+ [HttpPost("Create")]
+ public async Task PostPM([FromQuery] long? pmTemplateId, long? customerId, uint? serial, ApiVersion apiVersion)
{
if (!serverState.IsOpen)
return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));
@@ -183,7 +142,7 @@ namespace AyaNova.Api.Controllers
return BadRequest(new ApiErrorResponse(ModelState));
//Create and validate
- PM o = await biz.CreateAsync(inObj);
+ PM o = await biz.CreateAsync(pmTemplateId,customerId, serial);
if (o == null)
return BadRequest(new ApiErrorResponse(biz.Errors));
else
diff --git a/server/AyaNova/Controllers/QuoteController.cs b/server/AyaNova/Controllers/QuoteController.cs
index bb3536c8..44088902 100644
--- a/server/AyaNova/Controllers/QuoteController.cs
+++ b/server/AyaNova/Controllers/QuoteController.cs
@@ -3,7 +3,6 @@ using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization;
-using Microsoft.AspNetCore.JsonPatch;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using AyaNova.Models;
@@ -115,59 +114,19 @@ namespace AyaNova.Api.Controllers
- ///
- /// Patch (update) Quote
- ///
- ///
- ///
- ///
- ///
- [HttpPatch("{id}/{concurrencyToken}")]
- public async Task PatchQuote([FromRoute] long id, [FromRoute] uint concurrencyToken, [FromBody]JsonPatchDocument objectPatch)
- {
- //https://dotnetcoretutorials.com/2017/11/29/json-patch-asp-net-core/
- if (!serverState.IsOpen)
- return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));
-
- if (!ModelState.IsValid)
- return BadRequest(new ApiErrorResponse(ModelState));
-
- //Instantiate the business object handler
- QuoteBiz biz = QuoteBiz.GetBiz(ct, HttpContext);
-
- var o = await biz.GetAsync(id, false);
- if (o == null)
- return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND));
-
- if (!Authorized.HasModifyRole(HttpContext.Items, biz.BizType))
- return StatusCode(403, new ApiNotAuthorizedResponse());
-
- try
- {
- //patch and validate
- if (!await biz.PatchAsync(o, objectPatch, concurrencyToken))
- return BadRequest(new ApiErrorResponse(biz.Errors));
- }
- catch (DbUpdateConcurrencyException)
- {
- if (!await biz.ExistsAsync(id))
- return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND));
- else
- return StatusCode(409, new ApiErrorResponse(ApiErrorCode.CONCURRENCY_CONFLICT));
- }
- return Ok(ApiOkResponse.Response(new { ConcurrencyToken = o.ConcurrencyToken }, true));
- }
///
/// Post Quote
///
- ///
+ ///
+ ///
+ /// force a workorder number, leave null to autogenerate the next one in sequence (mostly used for import)
/// Automatically filled from route path, no need to specify in body
- ///
- [HttpPost]
- public async Task PostQuote([FromBody] Quote inObj, ApiVersion apiVersion)
+ /// A created workorder ready to fill out
+ [HttpPost("Create")]
+ public async Task PostQuote([FromQuery] long? quoteTemplateId, long? customerId, uint? serial, ApiVersion apiVersion)
{
if (!serverState.IsOpen)
return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));
@@ -183,7 +142,7 @@ namespace AyaNova.Api.Controllers
return BadRequest(new ApiErrorResponse(ModelState));
//Create and validate
- Quote o = await biz.CreateAsync(inObj);
+ Quote o = await biz.CreateAsync(quoteTemplateId,customerId, serial);
if (o == null)
return BadRequest(new ApiErrorResponse(biz.Errors));
else
diff --git a/server/AyaNova/biz/PMBiz.cs b/server/AyaNova/biz/PMBiz.cs
index 39af7dea..605beb79 100644
--- a/server/AyaNova/biz/PMBiz.cs
+++ b/server/AyaNova/biz/PMBiz.cs
@@ -10,6 +10,8 @@ namespace AyaNova.Biz
internal class PMBiz : BizObject, ISearchAbleObject
{
+ //Feature specific roles
+ internal static AuthorizationRoles RolesAllowedToChangeSerial = AuthorizationRoles.BizAdminFull | AuthorizationRoles.DispatchFull | AuthorizationRoles.AccountingFull;
internal PMBiz(AyContext dbcontext, long currentUserId, long userTranslationId, AuthorizationRoles UserRoles)
{
@@ -60,28 +62,41 @@ namespace AyaNova.Biz
//CREATE
//Called from route and also seeder
- internal async Task CreateAsync(PM inObj)
+ internal async Task CreateAsync(long? workorderTemplateId, long? customerId, uint? serial)
{
- await ValidateAsync(inObj, null);
- if (HasErrors)
- return null;
- else
+ //Create and save to db a new workorder and return it
+ //NOTE: Serial can be specified or edited after the fact in a limited way by full role specfic only!! (service manager, bizadminfull, accounting maybe)
+
+ if (serial != null && !Authorized.HasAnyRole(CurrentUserRoles, RolesAllowedToChangeSerial))
{
- //do stuff with PM
- PM outObj = inObj;
-
- outObj.Tags = TagUtil.NormalizeTags(outObj.Tags);
- outObj.CustomFields = JsonUtil.CompactJson(outObj.CustomFields);
- //Save to db
- await ct.PM.AddAsync(outObj);
- await ct.SaveChangesAsync();
- //Handle child and associated items:
- await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, outObj.Id, BizType, AyaEvent.Created), ct);
- await SearchIndexAsync(outObj, true);
- await TagUtil.ProcessUpdateTagsInRepositoryAsync(ct, outObj.Tags, null);
-
- return outObj;
+ AddError(ApiErrorCode.NOT_AUTHORIZED, "Serial");
+ return null;
}
+
+
+ // await ValidateAsync(inObj, null);
+ // if (HasErrors)
+ // return null;
+ // else
+ // {
+ //do stuff with PM
+ PM o = new PM();
+ o.Serial = serial ?? ServerBootConfig.WORKORDER_SERIAL.GetNext();
+
+ //TODO: template
+ //TODO: CUSTOMER ID
+
+
+ //Save to db
+ await ct.PM.AddAsync(o);
+ await ct.SaveChangesAsync();
+ //Handle child and associated items:
+ await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, o.Id, BizType, AyaEvent.Created), ct);
+ await SearchIndexAsync(o, true);
+ // await TagUtil.ProcessUpdateTagsInRepositoryAsync(ct, o.Tags, null);
+
+ return o;
+ //}
}
@@ -93,34 +108,34 @@ namespace AyaNova.Biz
internal async Task DuplicateAsync(PM dbObj)
{
+ throw new System.NotImplementedException("STUB: WORKORDER DUPLICATE");
+ // PM outObj = new PM();
+ // CopyObject.Copy(dbObj, outObj, "Wiki");
+ // // outObj.Name = Util.StringUtil.NameUniquify(outObj.Name, 255);
+ // //generate unique name
+ // string newUniqueName = string.Empty;
+ // bool NotUnique = true;
+ // long l = 1;
+ // do
+ // {
+ // newUniqueName = Util.StringUtil.UniqueNameBuilder(dbObj.Name, l++, 255);
+ // NotUnique = await ct.PM.AnyAsync(m => m.Name == newUniqueName);
+ // } while (NotUnique);
- PM outObj = new PM();
- CopyObject.Copy(dbObj, outObj, "Wiki");
- // outObj.Name = Util.StringUtil.NameUniquify(outObj.Name, 255);
- //generate unique name
- string newUniqueName = string.Empty;
- bool NotUnique = true;
- long l = 1;
- do
- {
- newUniqueName = Util.StringUtil.UniqueNameBuilder(dbObj.Name, l++, 255);
- NotUnique = await ct.PM.AnyAsync(m => m.Name == newUniqueName);
- } while (NotUnique);
-
- outObj.Name = newUniqueName;
+ // outObj.Name = newUniqueName;
- outObj.Id = 0;
- outObj.ConcurrencyToken = 0;
+ // outObj.Id = 0;
+ // outObj.ConcurrencyToken = 0;
- await ct.PM.AddAsync(outObj);
- await ct.SaveChangesAsync();
+ // await ct.PM.AddAsync(outObj);
+ // await ct.SaveChangesAsync();
- //Handle child and associated items:
- await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, outObj.Id, BizType, AyaEvent.Created), ct);
- await SearchIndexAsync(outObj, true);
- await TagUtil.ProcessUpdateTagsInRepositoryAsync(ct, outObj.Tags, null);
- return outObj;
+ // //Handle child and associated items:
+ // await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, outObj.Id, BizType, AyaEvent.Created), ct);
+ // await SearchIndexAsync(outObj, true);
+ // await TagUtil.ProcessUpdateTagsInRepositoryAsync(ct, outObj.Tags, null);
+ // return outObj;
}
@@ -129,22 +144,28 @@ namespace AyaNova.Biz
//
//put
- internal async Task PutAsync(PM dbObj, PM inObj)
+ internal async Task PutAsync(PM dbObj, PM putObj)
{
- //make a snapshot of the original for validation but update the original to preserve workflow
+ // make a snapshot of the original for validation but update the original to preserve workflow
PM SnapshotOfOriginalDBObj = new PM();
CopyObject.Copy(dbObj, SnapshotOfOriginalDBObj);
//Replace the db object with the PUT object
- CopyObject.Copy(inObj, dbObj, "Id");
+ CopyObject.Copy(putObj, dbObj, "Id,Serial");
+
+ //if user has rights then change it, otherwise just ignore it and do the rest
+ if (SnapshotOfOriginalDBObj.Serial != putObj.Serial && Authorized.HasAnyRole(CurrentUserRoles, RolesAllowedToChangeSerial))
+ {
+ dbObj.Serial = putObj.Serial;
+ }
dbObj.Tags = TagUtil.NormalizeTags(dbObj.Tags);
dbObj.CustomFields = JsonUtil.CompactJson(dbObj.CustomFields);
//Set "original" value of concurrency token to input token
//this will allow EF to check it out
- ct.Entry(dbObj).OriginalValues["ConcurrencyToken"] = inObj.ConcurrencyToken;
+ ct.Entry(dbObj).OriginalValues["ConcurrencyToken"] = putObj.ConcurrencyToken;
await ValidateAsync(dbObj, SnapshotOfOriginalDBObj);
@@ -159,42 +180,13 @@ namespace AyaNova.Biz
return true;
}
- //patch
- internal async Task PatchAsync(PM dbObj, JsonPatchDocument objectPatch, uint concurrencyToken)
- {
- //Validate Patch is allowed
- if (!ValidateJsonPatch.Validate(this, objectPatch)) return false;
-
- //make a snapshot of the original for validation but update the original to preserve workflow
- PM SnapshotOfOriginalDBObj = new PM();
- CopyObject.Copy(dbObj, SnapshotOfOriginalDBObj);
-
- //Do the patching
- objectPatch.ApplyTo(dbObj);
-
- dbObj.Tags = TagUtil.NormalizeTags(dbObj.Tags);
- dbObj.CustomFields = JsonUtil.CompactJson(dbObj.CustomFields);
-
- ct.Entry(dbObj).OriginalValues["ConcurrencyToken"] = concurrencyToken;
- await ValidateAsync(dbObj, SnapshotOfOriginalDBObj);
- if (HasErrors)
- return false;
-
- //Log event and save context
- await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObj.Id, BizType, AyaEvent.Modified), ct);
- await SearchIndexAsync(dbObj, false);
-
- await TagUtil.ProcessUpdateTagsInRepositoryAsync(ct, dbObj.Tags, SnapshotOfOriginalDBObj.Tags);
-
- return true;
- }
private async Task SearchIndexAsync(PM obj, bool isNew)
{
//SEARCH INDEXING
var SearchParams = new Search.SearchIndexProcessObjectParameters(UserTranslationId, obj.Id, BizType);
- SearchParams.AddText(obj.Notes).AddText(obj.Name).AddText(obj.Wiki).AddText(obj.Tags).AddCustomFields(obj.CustomFields);
+ SearchParams.AddText(obj.Notes).AddText(obj.Serial).AddText(obj.Wiki).AddText(obj.Tags).AddCustomFields(obj.CustomFields);
if (isNew)
await Search.ProcessNewObjectKeywordsAsync(SearchParams);
@@ -207,7 +199,7 @@ namespace AyaNova.Biz
var obj = await ct.PM.SingleOrDefaultAsync(m => m.Id == id);
var SearchParams = new Search.SearchIndexProcessObjectParameters();
if (obj != null)
- SearchParams.AddText(obj.Notes).AddText(obj.Name).AddText(obj.Wiki).AddText(obj.Tags).AddCustomFields(obj.CustomFields);
+ SearchParams.AddText(obj.Notes).AddText(obj.Serial).AddText(obj.Wiki).AddText(obj.Tags).AddCustomFields(obj.CustomFields);
return SearchParams;
}
@@ -216,20 +208,21 @@ namespace AyaNova.Biz
//
internal async Task DeleteAsync(PM dbObj)
{
+ throw new System.NotImplementedException("STUB: WORKORDER DELETE");
//Determine if the object can be deleted, do the deletion tentatively
//Probably also in here deal with tags and associated search text etc
//NOT REQUIRED NOW BUT IF IN FUTURE ValidateCanDelete(dbObj);
- if (HasErrors)
- return false;
- ct.PM.Remove(dbObj);
- await ct.SaveChangesAsync();
+ // if (HasErrors)
+ // return false;
+ // ct.PM.Remove(dbObj);
+ // await ct.SaveChangesAsync();
- //Log event
- await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObj.Id, dbObj.Name, ct);
- await Search.ProcessDeletedObjectKeywordsAsync(dbObj.Id, BizType);
- await TagUtil.ProcessDeleteTagsInRepositoryAsync(ct, dbObj.Tags);
- return true;
+ // //Log event
+ // await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObj.Id, dbObj.Serial.ToString(), ct);
+ // await Search.ProcessDeletedObjectKeywordsAsync(dbObj.Id, BizType);
+ // await TagUtil.ProcessDeleteTagsInRepositoryAsync(ct, dbObj.Tags);
+ // return true;
}
@@ -245,23 +238,23 @@ namespace AyaNova.Biz
//run validation and biz rules
bool isNew = currentObj == null;
- //Name required
- if (string.IsNullOrWhiteSpace(proposedObj.Name))
- AddError(ApiErrorCode.VALIDATION_REQUIRED, "Name");
+ // //Name required
+ // if (string.IsNullOrWhiteSpace(proposedObj.Name))
+ // AddError(ApiErrorCode.VALIDATION_REQUIRED, "Name");
- //Name must be less than 255 characters
- if (proposedObj.Name.Length > 255)
- AddError(ApiErrorCode.VALIDATION_LENGTH_EXCEEDED, "Name", "255 max");
+ // //Name must be less than 255 characters
+ // if (proposedObj.Name.Length > 255)
+ // AddError(ApiErrorCode.VALIDATION_LENGTH_EXCEEDED, "Name", "255 max");
- //If name is otherwise OK, check that name is unique
- if (!PropertyHasErrors("Name"))
- {
- //Use Any command is efficient way to check existance, it doesn't return the record, just a true or false
- if (await ct.PM.AnyAsync(m => m.Name == proposedObj.Name && m.Id != proposedObj.Id))
- {
- AddError(ApiErrorCode.VALIDATION_NOT_UNIQUE, "Name");
- }
- }
+ // //If name is otherwise OK, check that name is unique
+ // if (!PropertyHasErrors("Name"))
+ // {
+ // //Use Any command is efficient way to check existance, it doesn't return the record, just a true or false
+ // if (await ct.PM.AnyAsync(m => m.Name == proposedObj.Name && m.Id != proposedObj.Id))
+ // {
+ // AddError(ApiErrorCode.VALIDATION_NOT_UNIQUE, "Name");
+ // }
+ // }
//Any form customizations to validate?
diff --git a/server/AyaNova/biz/QuoteBiz.cs b/server/AyaNova/biz/QuoteBiz.cs
index 812e4140..eedca778 100644
--- a/server/AyaNova/biz/QuoteBiz.cs
+++ b/server/AyaNova/biz/QuoteBiz.cs
@@ -10,6 +10,8 @@ namespace AyaNova.Biz
internal class QuoteBiz : BizObject, ISearchAbleObject
{
+ //Feature specific roles
+ internal static AuthorizationRoles RolesAllowedToChangeSerial = AuthorizationRoles.BizAdminFull | AuthorizationRoles.DispatchFull | AuthorizationRoles.AccountingFull;
internal QuoteBiz(AyContext dbcontext, long currentUserId, long userTranslationId, AuthorizationRoles UserRoles)
{
@@ -60,28 +62,41 @@ namespace AyaNova.Biz
//CREATE
//Called from route and also seeder
- internal async Task CreateAsync(Quote inObj)
+ internal async Task CreateAsync(long? workorderTemplateId, long? customerId, uint? serial)
{
- await ValidateAsync(inObj, null);
- if (HasErrors)
- return null;
- else
+ //Create and save to db a new workorder and return it
+ //NOTE: Serial can be specified or edited after the fact in a limited way by full role specfic only!! (service manager, bizadminfull, accounting maybe)
+
+ if (serial != null && !Authorized.HasAnyRole(CurrentUserRoles, RolesAllowedToChangeSerial))
{
- //do stuff with Quote
- Quote outObj = inObj;
-
- outObj.Tags = TagUtil.NormalizeTags(outObj.Tags);
- outObj.CustomFields = JsonUtil.CompactJson(outObj.CustomFields);
- //Save to db
- await ct.Quote.AddAsync(outObj);
- await ct.SaveChangesAsync();
- //Handle child and associated items:
- await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, outObj.Id, BizType, AyaEvent.Created), ct);
- await SearchIndexAsync(outObj, true);
- await TagUtil.ProcessUpdateTagsInRepositoryAsync(ct, outObj.Tags, null);
-
- return outObj;
+ AddError(ApiErrorCode.NOT_AUTHORIZED, "Serial");
+ return null;
}
+
+
+ // await ValidateAsync(inObj, null);
+ // if (HasErrors)
+ // return null;
+ // else
+ // {
+ //do stuff with Quote
+ Quote o = new Quote();
+ o.Serial = serial ?? ServerBootConfig.WORKORDER_SERIAL.GetNext();
+
+ //TODO: template
+ //TODO: CUSTOMER ID
+
+
+ //Save to db
+ await ct.Quote.AddAsync(o);
+ await ct.SaveChangesAsync();
+ //Handle child and associated items:
+ await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, o.Id, BizType, AyaEvent.Created), ct);
+ await SearchIndexAsync(o, true);
+ // await TagUtil.ProcessUpdateTagsInRepositoryAsync(ct, o.Tags, null);
+
+ return o;
+ //}
}
@@ -93,34 +108,34 @@ namespace AyaNova.Biz
internal async Task DuplicateAsync(Quote dbObj)
{
+ throw new System.NotImplementedException("STUB: WORKORDER DUPLICATE");
+ // Quote outObj = new Quote();
+ // CopyObject.Copy(dbObj, outObj, "Wiki");
+ // // outObj.Name = Util.StringUtil.NameUniquify(outObj.Name, 255);
+ // //generate unique name
+ // string newUniqueName = string.Empty;
+ // bool NotUnique = true;
+ // long l = 1;
+ // do
+ // {
+ // newUniqueName = Util.StringUtil.UniqueNameBuilder(dbObj.Name, l++, 255);
+ // NotUnique = await ct.Quote.AnyAsync(m => m.Name == newUniqueName);
+ // } while (NotUnique);
- Quote outObj = new Quote();
- CopyObject.Copy(dbObj, outObj, "Wiki");
- // outObj.Name = Util.StringUtil.NameUniquify(outObj.Name, 255);
- //generate unique name
- string newUniqueName = string.Empty;
- bool NotUnique = true;
- long l = 1;
- do
- {
- newUniqueName = Util.StringUtil.UniqueNameBuilder(dbObj.Name, l++, 255);
- NotUnique = await ct.Quote.AnyAsync(m => m.Name == newUniqueName);
- } while (NotUnique);
-
- outObj.Name = newUniqueName;
+ // outObj.Name = newUniqueName;
- outObj.Id = 0;
- outObj.ConcurrencyToken = 0;
+ // outObj.Id = 0;
+ // outObj.ConcurrencyToken = 0;
- await ct.Quote.AddAsync(outObj);
- await ct.SaveChangesAsync();
+ // await ct.Quote.AddAsync(outObj);
+ // await ct.SaveChangesAsync();
- //Handle child and associated items:
- await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, outObj.Id, BizType, AyaEvent.Created), ct);
- await SearchIndexAsync(outObj, true);
- await TagUtil.ProcessUpdateTagsInRepositoryAsync(ct, outObj.Tags, null);
- return outObj;
+ // //Handle child and associated items:
+ // await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, outObj.Id, BizType, AyaEvent.Created), ct);
+ // await SearchIndexAsync(outObj, true);
+ // await TagUtil.ProcessUpdateTagsInRepositoryAsync(ct, outObj.Tags, null);
+ // return outObj;
}
@@ -129,22 +144,28 @@ namespace AyaNova.Biz
//
//put
- internal async Task PutAsync(Quote dbObj, Quote inObj)
+ internal async Task PutAsync(Quote dbObj, Quote putObj)
{
- //make a snapshot of the original for validation but update the original to preserve workflow
+ // make a snapshot of the original for validation but update the original to preserve workflow
Quote SnapshotOfOriginalDBObj = new Quote();
CopyObject.Copy(dbObj, SnapshotOfOriginalDBObj);
//Replace the db object with the PUT object
- CopyObject.Copy(inObj, dbObj, "Id");
+ CopyObject.Copy(putObj, dbObj, "Id,Serial");
+
+ //if user has rights then change it, otherwise just ignore it and do the rest
+ if (SnapshotOfOriginalDBObj.Serial != putObj.Serial && Authorized.HasAnyRole(CurrentUserRoles, RolesAllowedToChangeSerial))
+ {
+ dbObj.Serial = putObj.Serial;
+ }
dbObj.Tags = TagUtil.NormalizeTags(dbObj.Tags);
dbObj.CustomFields = JsonUtil.CompactJson(dbObj.CustomFields);
//Set "original" value of concurrency token to input token
//this will allow EF to check it out
- ct.Entry(dbObj).OriginalValues["ConcurrencyToken"] = inObj.ConcurrencyToken;
+ ct.Entry(dbObj).OriginalValues["ConcurrencyToken"] = putObj.ConcurrencyToken;
await ValidateAsync(dbObj, SnapshotOfOriginalDBObj);
@@ -159,42 +180,13 @@ namespace AyaNova.Biz
return true;
}
- //patch
- internal async Task PatchAsync(Quote dbObj, JsonPatchDocument objectPatch, uint concurrencyToken)
- {
- //Validate Patch is allowed
- if (!ValidateJsonPatch.Validate(this, objectPatch)) return false;
-
- //make a snapshot of the original for validation but update the original to preserve workflow
- Quote SnapshotOfOriginalDBObj = new Quote();
- CopyObject.Copy(dbObj, SnapshotOfOriginalDBObj);
-
- //Do the patching
- objectPatch.ApplyTo(dbObj);
-
- dbObj.Tags = TagUtil.NormalizeTags(dbObj.Tags);
- dbObj.CustomFields = JsonUtil.CompactJson(dbObj.CustomFields);
-
- ct.Entry(dbObj).OriginalValues["ConcurrencyToken"] = concurrencyToken;
- await ValidateAsync(dbObj, SnapshotOfOriginalDBObj);
- if (HasErrors)
- return false;
-
- //Log event and save context
- await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObj.Id, BizType, AyaEvent.Modified), ct);
- await SearchIndexAsync(dbObj, false);
-
- await TagUtil.ProcessUpdateTagsInRepositoryAsync(ct, dbObj.Tags, SnapshotOfOriginalDBObj.Tags);
-
- return true;
- }
private async Task SearchIndexAsync(Quote obj, bool isNew)
{
//SEARCH INDEXING
var SearchParams = new Search.SearchIndexProcessObjectParameters(UserTranslationId, obj.Id, BizType);
- SearchParams.AddText(obj.Notes).AddText(obj.Name).AddText(obj.Wiki).AddText(obj.Tags).AddCustomFields(obj.CustomFields);
+ SearchParams.AddText(obj.Notes).AddText(obj.Serial).AddText(obj.Wiki).AddText(obj.Tags).AddCustomFields(obj.CustomFields);
if (isNew)
await Search.ProcessNewObjectKeywordsAsync(SearchParams);
@@ -207,7 +199,7 @@ namespace AyaNova.Biz
var obj = await ct.Quote.SingleOrDefaultAsync(m => m.Id == id);
var SearchParams = new Search.SearchIndexProcessObjectParameters();
if (obj != null)
- SearchParams.AddText(obj.Notes).AddText(obj.Name).AddText(obj.Wiki).AddText(obj.Tags).AddCustomFields(obj.CustomFields);
+ SearchParams.AddText(obj.Notes).AddText(obj.Serial).AddText(obj.Wiki).AddText(obj.Tags).AddCustomFields(obj.CustomFields);
return SearchParams;
}
@@ -216,20 +208,21 @@ namespace AyaNova.Biz
//
internal async Task DeleteAsync(Quote dbObj)
{
+ throw new System.NotImplementedException("STUB: WORKORDER DELETE");
//Determine if the object can be deleted, do the deletion tentatively
//Probably also in here deal with tags and associated search text etc
//NOT REQUIRED NOW BUT IF IN FUTURE ValidateCanDelete(dbObj);
- if (HasErrors)
- return false;
- ct.Quote.Remove(dbObj);
- await ct.SaveChangesAsync();
+ // if (HasErrors)
+ // return false;
+ // ct.Quote.Remove(dbObj);
+ // await ct.SaveChangesAsync();
- //Log event
- await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObj.Id, dbObj.Name, ct);
- await Search.ProcessDeletedObjectKeywordsAsync(dbObj.Id, BizType);
- await TagUtil.ProcessDeleteTagsInRepositoryAsync(ct, dbObj.Tags);
- return true;
+ // //Log event
+ // await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObj.Id, dbObj.Serial.ToString(), ct);
+ // await Search.ProcessDeletedObjectKeywordsAsync(dbObj.Id, BizType);
+ // await TagUtil.ProcessDeleteTagsInRepositoryAsync(ct, dbObj.Tags);
+ // return true;
}
@@ -245,23 +238,23 @@ namespace AyaNova.Biz
//run validation and biz rules
bool isNew = currentObj == null;
- //Name required
- if (string.IsNullOrWhiteSpace(proposedObj.Name))
- AddError(ApiErrorCode.VALIDATION_REQUIRED, "Name");
+ // //Name required
+ // if (string.IsNullOrWhiteSpace(proposedObj.Name))
+ // AddError(ApiErrorCode.VALIDATION_REQUIRED, "Name");
- //Name must be less than 255 characters
- if (proposedObj.Name.Length > 255)
- AddError(ApiErrorCode.VALIDATION_LENGTH_EXCEEDED, "Name", "255 max");
+ // //Name must be less than 255 characters
+ // if (proposedObj.Name.Length > 255)
+ // AddError(ApiErrorCode.VALIDATION_LENGTH_EXCEEDED, "Name", "255 max");
- //If name is otherwise OK, check that name is unique
- if (!PropertyHasErrors("Name"))
- {
- //Use Any command is efficient way to check existance, it doesn't return the record, just a true or false
- if (await ct.Quote.AnyAsync(m => m.Name == proposedObj.Name && m.Id != proposedObj.Id))
- {
- AddError(ApiErrorCode.VALIDATION_NOT_UNIQUE, "Name");
- }
- }
+ // //If name is otherwise OK, check that name is unique
+ // if (!PropertyHasErrors("Name"))
+ // {
+ // //Use Any command is efficient way to check existance, it doesn't return the record, just a true or false
+ // if (await ct.Quote.AnyAsync(m => m.Name == proposedObj.Name && m.Id != proposedObj.Id))
+ // {
+ // AddError(ApiErrorCode.VALIDATION_NOT_UNIQUE, "Name");
+ // }
+ // }
//Any form customizations to validate?