De-Templatization for ALL THE THINGS!!

This commit is contained in:
2021-07-23 19:58:10 +00:00
parent 3565f1a795
commit 48c2c7d8ab
22 changed files with 192 additions and 1966 deletions

2
.vscode/launch.json vendored
View File

@@ -54,7 +54,7 @@
"AYANOVA_FOLDER_BACKUP_FILES": "c:\\temp\\RavenTestData\\backupfiles",
"AYANOVA_FOLDER_TEMPORARY_SERVER_FILES": "c:\\temp\\RavenTestData\\tempfiles",
"AYANOVA_SERVER_TEST_MODE": "true",
"AYANOVA_SERVER_TEST_MODE_SEEDLEVEL": "false",
"AYANOVA_SERVER_TEST_MODE_SEEDLEVEL": "small",
"AYANOVA_SERVER_TEST_MODE_TZ_OFFSET": "-7",
"AYANOVA_BACKUP_PG_DUMP_PATH": "C:\\data\\code\\postgres_13\\bin\\"
},

View File

@@ -233,4 +233,4 @@ https://en.wikipedia.org/wiki/Non-functional_requirement
## ASCII ART
//http://www.patorjk.com/software/taag/#p=display&f=ANSI%20Shadow&t=work-order
//http://www.patorjk.com/software/taag/#p=display&f=ANSI%20Shadow&t=quote

View File

@@ -1,159 +0,0 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging;
using AyaNova.Models;
using AyaNova.Api.ControllerHelpers;
using AyaNova.Biz;
namespace AyaNova.Api.Controllers
{
[ApiController]
[ApiVersion("8.0")]
[Route("api/v{version:apiVersion}/pm-template")]
[Produces("application/json")]
[Authorize]
public class PMTemplateController : ControllerBase
{
private readonly AyContext ct;
private readonly ILogger<PMTemplateController> log;
private readonly ApiServerState serverState;
/// <summary>
/// ctor
/// </summary>
/// <param name="dbcontext"></param>
/// <param name="logger"></param>
/// <param name="apiServerState"></param>
public PMTemplateController(AyContext dbcontext, ILogger<PMTemplateController> logger, ApiServerState apiServerState)
{
ct = dbcontext;
log = logger;
serverState = apiServerState;
}
/// <summary>
/// Create PMTemplate
/// </summary>
/// <param name="newObject"></param>
/// <param name="apiVersion">From route path</param>
/// <returns></returns>
[HttpPost]
public async Task<IActionResult> PostPMTemplate([FromBody] PMTemplate newObject, ApiVersion apiVersion)
{
if (!serverState.IsOpen)
return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));
PMTemplateBiz biz = PMTemplateBiz.GetBiz(ct, HttpContext);
if (!Authorized.HasCreateRole(HttpContext.Items, biz.BizType))
return StatusCode(403, new ApiNotAuthorizedResponse());
if (!ModelState.IsValid)
return BadRequest(new ApiErrorResponse(ModelState));
PMTemplate o = await biz.CreateAsync(newObject);
if (o == null)
return BadRequest(new ApiErrorResponse(biz.Errors));
else
return CreatedAtAction(nameof(PMTemplateController.GetPMTemplate), new { id = o.Id, version = apiVersion.ToString() }, new ApiCreatedResponse(o));
}
// /// <summary>
// /// Duplicate PMTemplate
// /// (Wiki and Attachments are not duplicated)
// /// </summary>
// /// <param name="id">Source object id</param>
// /// <param name="apiVersion">From route path</param>
// /// <returns>PMTemplate</returns>
// [HttpPost("duplicate/{id}")]
// public async Task<IActionResult> DuplicatePMTemplate([FromRoute] long id, ApiVersion apiVersion)
// {
// if (!serverState.IsOpen)
// return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));
// PMTemplateBiz biz = PMTemplateBiz.GetBiz(ct, HttpContext);
// if (!Authorized.HasCreateRole(HttpContext.Items, biz.BizType))
// return StatusCode(403, new ApiNotAuthorizedResponse());
// if (!ModelState.IsValid)
// return BadRequest(new ApiErrorResponse(ModelState));
// PMTemplate o = await biz.DuplicateAsync(id);
// if (o == null)
// return BadRequest(new ApiErrorResponse(biz.Errors));
// else
// return CreatedAtAction(nameof(PMTemplateController.GetPMTemplate), new { id = o.Id, version = apiVersion.ToString() }, new ApiCreatedResponse(o));
// }
/// <summary>
/// Get PMTemplate
/// </summary>
/// <param name="id"></param>
/// <returns>PMTemplate</returns>
[HttpGet("{id}")]
public async Task<IActionResult> GetPMTemplate([FromRoute] long id)
{
if (!serverState.IsOpen)
return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));
PMTemplateBiz biz = PMTemplateBiz.GetBiz(ct, HttpContext);
if (!Authorized.HasReadFullRole(HttpContext.Items, biz.BizType))
return StatusCode(403, new ApiNotAuthorizedResponse());
if (!ModelState.IsValid)
return BadRequest(new ApiErrorResponse(ModelState));
var o = await biz.GetAsync(id);
if (o == null) return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND));
return Ok(ApiOkResponse.Response(o));
}
/// <summary>
/// Update PMTemplate
/// </summary>
/// <param name="updatedObject"></param>
/// <returns></returns>
[HttpPut]
public async Task<IActionResult> PutPMTemplate([FromBody] PMTemplate updatedObject)
{
if (!serverState.IsOpen)
return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));
if (!ModelState.IsValid)
return BadRequest(new ApiErrorResponse(ModelState));
PMTemplateBiz biz = PMTemplateBiz.GetBiz(ct, HttpContext);
if (!Authorized.HasModifyRole(HttpContext.Items, biz.BizType))
return StatusCode(403, new ApiNotAuthorizedResponse());
var o = await biz.PutAsync(updatedObject);//In future may need to return entire object, for now just concurrency token
if (o == null)
{
if (biz.Errors.Exists(z => z.Code == ApiErrorCode.CONCURRENCY_CONFLICT))
return StatusCode(409, new ApiErrorResponse(biz.Errors));
else
return BadRequest(new ApiErrorResponse(biz.Errors));
}
return Ok(ApiOkResponse.Response(new { Concurrency = o.Concurrency }));;
}
/// <summary>
/// Delete PMTemplate
/// </summary>
/// <param name="id"></param>
/// <returns>NoContent</returns>
[HttpDelete("{id}")]
public async Task<IActionResult> DeletePMTemplate([FromRoute] long id)
{
if (!serverState.IsOpen)
return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));
if (!ModelState.IsValid)
return BadRequest(new ApiErrorResponse(ModelState));
PMTemplateBiz biz = PMTemplateBiz.GetBiz(ct, HttpContext);
if (!Authorized.HasDeleteRole(HttpContext.Items, biz.BizType))
return StatusCode(403, new ApiNotAuthorizedResponse());
if (!await biz.DeleteAsync(id))
return BadRequest(new ApiErrorResponse(biz.Errors));
return NoContent();
}
//------------
}//eoc
}//eons

View File

@@ -1,224 +0,0 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using AyaNova.Models;
using AyaNova.Api.ControllerHelpers;
using AyaNova.Biz;
namespace AyaNova.Api.Controllers
{
[ApiController]
[ApiVersion("8.0")]
[Route("api/v{version:apiVersion}/quote-template")]
[Produces("application/json")]
[Authorize]
public class QuoteTemplateController : ControllerBase
{
private readonly AyContext ct;
private readonly ILogger<QuoteTemplateController> log;
private readonly ApiServerState serverState;
/// <summary>
/// ctor
/// </summary>
/// <param name="dbcontext"></param>
/// <param name="logger"></param>
/// <param name="apiServerState"></param>
public QuoteTemplateController(AyContext dbcontext, ILogger<QuoteTemplateController> logger, ApiServerState apiServerState)
{
ct = dbcontext;
log = logger;
serverState = apiServerState;
}
/// <summary>
/// Get full QuoteTemplate object
/// </summary>
/// <param name="id"></param>
/// <returns>A single QuoteTemplate</returns>
[HttpGet("{id}")]
public async Task<IActionResult> GetQuoteTemplate([FromRoute] long id)
{
if (!serverState.IsOpen)
return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));
//Instantiate the business object handler
QuoteTemplateBiz biz = QuoteTemplateBiz.GetBiz(ct, HttpContext);
//NOTE: This is the first check and often the only check but in some cases with some objects this will also need to check biz object rules
if (!Authorized.HasReadFullRole(HttpContext.Items, biz.BizType))
return StatusCode(403, new ApiNotAuthorizedResponse());
if (!ModelState.IsValid)
return BadRequest(new ApiErrorResponse(ModelState));
var o = await biz.GetAsync(id);
if (o == null)
return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND));
// NOTE: HERE would be the second check of biz rules before returning the object
// in cases where there is also a business rule to affect retrieval on top of basic rights
return Ok(ApiOkResponse.Response(o));
}
/// <summary>
/// Update QuoteTemplate
/// </summary>
/// <param name="id"></param>
/// <param name="inObj"></param>
/// <returns></returns>
[HttpPut("{id}")]
public async Task<IActionResult> PutQuoteTemplate([FromRoute] long id, [FromBody] QuoteTemplate inObj)
{
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
QuoteTemplateBiz biz = QuoteTemplateBiz.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
{
if (!await biz.PutAsync(o, inObj))
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 { Concurrency = o.Concurrency }));
}
/// <summary>
/// Create QuoteTemplate
/// </summary>
/// <param name="inObj"></param>
/// <param name="apiVersion">From route path</param>
/// <returns></returns>
[HttpPost]
public async Task<IActionResult> PostQuoteTemplate([FromBody] QuoteTemplate inObj, ApiVersion apiVersion)
{
if (!serverState.IsOpen)
return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));
//Instantiate the business object handler
QuoteTemplateBiz biz = QuoteTemplateBiz.GetBiz(ct, HttpContext);
//If a user has change roles
if (!Authorized.HasCreateRole(HttpContext.Items, biz.BizType))
return StatusCode(403, new ApiNotAuthorizedResponse());
if (!ModelState.IsValid)
return BadRequest(new ApiErrorResponse(ModelState));
//Create and validate
QuoteTemplate o = await biz.CreateAsync(inObj);
if (o == null)
return BadRequest(new ApiErrorResponse(biz.Errors));
else
return CreatedAtAction(nameof(QuoteTemplateController.GetQuoteTemplate), new { id = o.Id, version = apiVersion.ToString() }, new ApiCreatedResponse(o));
}
// /// <summary>
// /// Duplicate QuoteTemplate
// /// </summary>
// /// <param name="id">Create a duplicate of this items id</param>
// /// <param name="apiVersion">From route path</param>
// /// <returns></returns>
// [HttpPost("duplicate/{id}")]
// public async Task<IActionResult> DuplicateQuoteTemplate([FromRoute] long id, ApiVersion apiVersion)
// {
// if (!serverState.IsOpen)
// return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));
// //Instantiate the business object handler
// QuoteTemplateBiz biz = QuoteTemplateBiz.GetBiz(ct, HttpContext);
// //If a user has change roles
// if (!Authorized.HasCreateRole(HttpContext.Items, biz.BizType))
// return StatusCode(403, new ApiNotAuthorizedResponse());
// if (!ModelState.IsValid)
// return BadRequest(new ApiErrorResponse(ModelState));
// var oSrc = await biz.GetAsync(id, false);
// if (oSrc == null)
// return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND));
// //Create and validate
// QuoteTemplate o = await biz.DuplicateAsync(oSrc);
// if (o == null)
// return BadRequest(new ApiErrorResponse(biz.Errors));
// else
// return CreatedAtAction(nameof(QuoteTemplateController.GetQuoteTemplate), new { id = o.Id, version = apiVersion.ToString() }, new ApiCreatedResponse(o));
// }
/// <summary>
/// Delete QuoteTemplate
/// </summary>
/// <param name="id"></param>
/// <returns>Ok</returns>
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteQuoteTemplate([FromRoute] long id)
{
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
QuoteTemplateBiz biz = QuoteTemplateBiz.GetBiz(ct, HttpContext);
var o = await biz.GetAsync(id, false);
if (o == null)
return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND));
if (!Authorized.HasDeleteRole(HttpContext.Items, biz.BizType))
return StatusCode(403, new ApiNotAuthorizedResponse());
if (!await biz.DeleteAsync(o))
return BadRequest(new ApiErrorResponse(biz.Errors));
return NoContent();
}
//------------
}//eoc
}//eons

View File

@@ -1,224 +0,0 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Authorization;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using AyaNova.Models;
using AyaNova.Api.ControllerHelpers;
using AyaNova.Biz;
namespace AyaNova.Api.Controllers
{
[ApiController]
[ApiVersion("8.0")]
[Route("api/v{version:apiVersion}/workorder-template")]
[Produces("application/json")]
[Authorize]
public class WorkOrderTemplateController : ControllerBase
{
private readonly AyContext ct;
private readonly ILogger<WorkOrderTemplateController> log;
private readonly ApiServerState serverState;
/// <summary>
/// ctor
/// </summary>
/// <param name="dbcontext"></param>
/// <param name="logger"></param>
/// <param name="apiServerState"></param>
public WorkOrderTemplateController(AyContext dbcontext, ILogger<WorkOrderTemplateController> logger, ApiServerState apiServerState)
{
ct = dbcontext;
log = logger;
serverState = apiServerState;
}
/// <summary>
/// Get full WorkOrderTemplate object
/// </summary>
/// <param name="id"></param>
/// <returns>A single WorkOrderTemplate</returns>
[HttpGet("{id}")]
public async Task<IActionResult> GetWorkOrderTemplate([FromRoute] long id)
{
if (!serverState.IsOpen)
return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));
//Instantiate the business object handler
WorkOrderTemplateBiz biz = WorkOrderTemplateBiz.GetBiz(ct, HttpContext);
//NOTE: This is the first check and often the only check but in some cases with some objects this will also need to check biz object rules
if (!Authorized.HasReadFullRole(HttpContext.Items, biz.BizType))
return StatusCode(403, new ApiNotAuthorizedResponse());
if (!ModelState.IsValid)
return BadRequest(new ApiErrorResponse(ModelState));
var o = await biz.GetAsync(id);
if (o == null)
return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND));
// NOTE: HERE would be the second check of biz rules before returning the object
// in cases where there is also a business rule to affect retrieval on top of basic rights
return Ok(ApiOkResponse.Response(o));
}
/// <summary>
/// Update WorkOrderTemplate
/// </summary>
/// <param name="id"></param>
/// <param name="inObj"></param>
/// <returns></returns>
[HttpPut("{id}")]
public async Task<IActionResult> PutWorkOrderTemplate([FromRoute] long id, [FromBody] WorkOrderTemplate inObj)
{
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
WorkOrderTemplateBiz biz = WorkOrderTemplateBiz.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
{
if (!await biz.PutAsync(o, inObj))
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 { Concurrency = o.Concurrency }));
}
/// <summary>
/// Create WorkOrderTemplate
/// </summary>
/// <param name="inObj"></param>
/// <param name="apiVersion">From route path</param>
/// <returns></returns>
[HttpPost]
public async Task<IActionResult> PostWorkOrderTemplate([FromBody] WorkOrderTemplate inObj, ApiVersion apiVersion)
{
if (!serverState.IsOpen)
return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));
//Instantiate the business object handler
WorkOrderTemplateBiz biz = WorkOrderTemplateBiz.GetBiz(ct, HttpContext);
//If a user has change roles
if (!Authorized.HasCreateRole(HttpContext.Items, biz.BizType))
return StatusCode(403, new ApiNotAuthorizedResponse());
if (!ModelState.IsValid)
return BadRequest(new ApiErrorResponse(ModelState));
//Create and validate
WorkOrderTemplate o = await biz.CreateAsync(inObj);
if (o == null)
return BadRequest(new ApiErrorResponse(biz.Errors));
else
return CreatedAtAction(nameof(WorkOrderTemplateController.GetWorkOrderTemplate), new { id = o.Id, version = apiVersion.ToString() }, new ApiCreatedResponse(o));
}
// /// <summary>
// /// Duplicate WorkOrderTemplate
// /// </summary>
// /// <param name="id">Create a duplicate of this items id</param>
// /// <param name="apiVersion">From route path</param>
// /// <returns></returns>
// [HttpPost("duplicate/{id}")]
// public async Task<IActionResult> DuplicateWorkOrderTemplate([FromRoute] long id, ApiVersion apiVersion)
// {
// if (!serverState.IsOpen)
// return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));
// //Instantiate the business object handler
// WorkOrderTemplateBiz biz = WorkOrderTemplateBiz.GetBiz(ct, HttpContext);
// //If a user has change roles
// if (!Authorized.HasCreateRole(HttpContext.Items, biz.BizType))
// return StatusCode(403, new ApiNotAuthorizedResponse());
// if (!ModelState.IsValid)
// return BadRequest(new ApiErrorResponse(ModelState));
// var oSrc = await biz.GetAsync(id, false);
// if (oSrc == null)
// return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND));
// //Create and validate
// WorkOrderTemplate o = await biz.DuplicateAsync(oSrc);
// if (o == null)
// return BadRequest(new ApiErrorResponse(biz.Errors));
// else
// return CreatedAtAction(nameof(WorkOrderTemplateController.GetWorkOrderTemplate), new { id = o.Id, version = apiVersion.ToString() }, new ApiCreatedResponse(o));
// }
/// <summary>
/// Delete WorkOrderTemplate
/// </summary>
/// <param name="id"></param>
/// <returns>Ok</returns>
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteWorkOrderTemplate([FromRoute] long id)
{
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
WorkOrderTemplateBiz biz = WorkOrderTemplateBiz.GetBiz(ct, HttpContext);
var o = await biz.GetAsync(id, false);
if (o == null)
return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND));
if (!Authorized.HasDeleteRole(HttpContext.Items, biz.BizType))
return StatusCode(403, new ApiNotAuthorizedResponse());
if (!await biz.DeleteAsync(o))
return BadRequest(new ApiErrorResponse(biz.Errors));
return NoContent();
}
//------------
}//eoc
}//eons

View File

@@ -1,46 +0,0 @@
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
using AyaNova.Biz;
namespace AyaNova.PickList
{
internal class WorkOrderTemplatePickList : AyaPickList
{
public WorkOrderTemplatePickList()
{
DefaultListAType = AyaType.WorkOrderTemplate;
SQLFrom = "from aworkordertemplate";
AllowedRoles = BizRoles.GetRoleSet(DefaultListAType).Select;
dynamic dTemplate = new JArray();
dynamic cm = new JObject();
cm.fld = "name";
dTemplate.Add(cm);
base.DefaultTemplate = dTemplate.ToString(Newtonsoft.Json.Formatting.None);
//NOTE: Due to the join, all the sql id and name fields that can conflict with the joined table need to be specified completely
ColumnDefinitions = new List<AyaPickListFieldDefinition>();
ColumnDefinitions.Add(new AyaPickListFieldDefinition
{
TKey = "Active",
FieldKey = "active",
ColumnDataType = UiFieldDataType.Bool,
SqlValueColumnName = "aworkordertemplate.active",
IsActiveColumn = true
});
ColumnDefinitions.Add(new AyaPickListFieldDefinition
{
TKey = "Name",
FieldKey = "name",
ColumnDataType = UiFieldDataType.Text,
SqlIdColumnName = "aworkordertemplate.id",
SqlValueColumnName = "aworkordertemplate.name",
IsRowId = true
});
}
}//eoc
}//eons

View File

@@ -54,9 +54,9 @@ namespace AyaNova.Biz
[CoreBizObject]
PMItem = 22,
[CoreBizObject]
PMTemplate = 23,
unused23 = 23,
[CoreBizObject]
PMTemplateItem = 24,
unused24 = 24,
[CoreBizObject]
Project = 25,
[CoreBizObject]
@@ -66,9 +66,9 @@ namespace AyaNova.Biz
[CoreBizObject]
QuoteItem = 28,
[CoreBizObject]
QuoteTemplate = 29,
unused29 = 29,
[CoreBizObject]
QuoteTemplateItem = 30,
unused30 = 30,
[CoreBizObject]
Unit = 31,
[CoreBizObject]
@@ -100,9 +100,9 @@ namespace AyaNova.Biz
WorkOrderItemUnit = 44,
//---
[CoreBizObject]
WorkOrderTemplate = 45,
unused45 = 45,
[CoreBizObject]
WorkOrderTemplateItem = 46,
unused46 = 46,
GlobalOps = 47,//really only used for rights, not an object type of any kind
BizMetrics = 48,//deprecate? Not used for anything as of nov 2020
Backup = 49,

View File

@@ -56,10 +56,7 @@ namespace AyaNova.Biz
return await ct.PM.AnyAsync(z => z.Id == id);
case AyaType.PMItem:
return await ct.PMItem.AnyAsync(z => z.Id == id);
case AyaType.PMTemplate:
return await ct.PMTemplate.AnyAsync(z => z.Id == id);
case AyaType.PMTemplateItem:
return await ct.PMTemplateItem.AnyAsync(z => z.Id == id);
case AyaType.Project:
return await ct.Project.AnyAsync(z => z.Id == id);
case AyaType.PurchaseOrder:
@@ -68,10 +65,7 @@ namespace AyaNova.Biz
return await ct.Quote.AnyAsync(z => z.Id == id);
case AyaType.QuoteItem:
return await ct.QuoteItem.AnyAsync(z => z.Id == id);
case AyaType.QuoteTemplate:
return await ct.QuoteTemplate.AnyAsync(z => z.Id == id);
case AyaType.QuoteTemplateItem:
return await ct.QuoteTemplateItem.AnyAsync(z => z.Id == id);
case AyaType.Unit:
return await ct.Unit.AnyAsync(z => z.Id == id);
case AyaType.UnitModel:
@@ -104,10 +98,7 @@ namespace AyaNova.Biz
case AyaType.WorkOrderItemOutsideService:
return await ct.WorkOrderItemOutsideService.AnyAsync(z => z.Id == id);
//---
case AyaType.WorkOrderTemplate:
return await ct.WorkOrderTemplate.AnyAsync(z => z.Id == id);
case AyaType.WorkOrderTemplateItem:
return await ct.WorkOrderTemplateItem.AnyAsync(z => z.Id == id);
case AyaType.Report:
return await ct.Report.AnyAsync(z => z.Id == id);
case AyaType.Reminder:

View File

@@ -64,8 +64,6 @@ namespace AyaNova.Biz
case AyaType.PM:
return new PMBiz(ct, userId, translationId, roles);
case AyaType.PMTemplate:
return new PMTemplateBiz(ct, userId, translationId, roles);
case AyaType.Project:
return new ProjectBiz(ct, userId, translationId, roles);
@@ -74,8 +72,6 @@ namespace AyaNova.Biz
case AyaType.Quote:
return new QuoteBiz(ct, userId, translationId, roles);
case AyaType.QuoteTemplate:
return new QuoteTemplateBiz(ct, userId, translationId, roles);
case AyaType.Unit:
return new UnitBiz(ct, userId, translationId, roles);
@@ -98,8 +94,6 @@ namespace AyaNova.Biz
case AyaType.WorkOrderItemOutsideService:
return new WorkOrderBiz(ct, userId, translationId, roles, UserType.NotService);//default to not service for now arbitrarily on the principle of least access
//---
case AyaType.WorkOrderTemplate:
return new WorkOrderTemplateBiz(ct, userId, translationId, roles);
case AyaType.Reminder:
return new ReminderBiz(ct, userId, translationId, roles);

View File

@@ -269,25 +269,7 @@ namespace AyaNova.Biz
Select = AuthorizationRoles.All
});
////////////////////////////////////////////////////////////
//PMTemplate
//
roles.Add(AyaType.PMTemplate, new BizRoleSet()
{
Change = AuthorizationRoles.BizAdmin | AuthorizationRoles.Service | AuthorizationRoles.Sales | AuthorizationRoles.Tech | AuthorizationRoles.Accounting,
ReadFullRecord = AuthorizationRoles.BizAdminRestricted | AuthorizationRoles.ServiceRestricted | AuthorizationRoles.SalesRestricted | AuthorizationRoles.TechRestricted,
Select = AuthorizationRoles.All
});
////////////////////////////////////////////////////////////
//PMTemplateItem
//
roles.Add(AyaType.PMTemplateItem, new BizRoleSet()
{
Change = AuthorizationRoles.BizAdmin | AuthorizationRoles.Service | AuthorizationRoles.Sales | AuthorizationRoles.Tech | AuthorizationRoles.Accounting,
ReadFullRecord = AuthorizationRoles.BizAdminRestricted | AuthorizationRoles.ServiceRestricted | AuthorizationRoles.SalesRestricted | AuthorizationRoles.TechRestricted,
Select = AuthorizationRoles.All
});
////////////////////////////////////////////////////////////
//Project
@@ -400,25 +382,6 @@ namespace AyaNova.Biz
Select = AuthorizationRoles.All
});
////////////////////////////////////////////////////////////
//QuoteTemplate
//
roles.Add(AyaType.QuoteTemplate, new BizRoleSet()
{
Change = AuthorizationRoles.BizAdmin | AuthorizationRoles.Service | AuthorizationRoles.Sales | AuthorizationRoles.Tech | AuthorizationRoles.Accounting,
ReadFullRecord = AuthorizationRoles.BizAdminRestricted | AuthorizationRoles.ServiceRestricted | AuthorizationRoles.SalesRestricted | AuthorizationRoles.TechRestricted,
Select = AuthorizationRoles.All
});
////////////////////////////////////////////////////////////
//QuoteTemplateItem
//
roles.Add(AyaType.QuoteTemplateItem, new BizRoleSet()
{
Change = AuthorizationRoles.BizAdmin | AuthorizationRoles.Service | AuthorizationRoles.Sales | AuthorizationRoles.Tech | AuthorizationRoles.Accounting,
ReadFullRecord = AuthorizationRoles.BizAdminRestricted | AuthorizationRoles.ServiceRestricted | AuthorizationRoles.SalesRestricted | AuthorizationRoles.TechRestricted,
Select = AuthorizationRoles.All
});
////////////////////////////////////////////////////////////
//Unit
@@ -597,28 +560,6 @@ namespace AyaNova.Biz
//---
////////////////////////////////////////////////////////////
//WorkOrderTemplate
//
roles.Add(AyaType.WorkOrderTemplate, new BizRoleSet()
{
Change = AuthorizationRoles.BizAdmin | AuthorizationRoles.Service | AuthorizationRoles.Sales | AuthorizationRoles.Tech | AuthorizationRoles.Accounting,
ReadFullRecord = AuthorizationRoles.BizAdminRestricted | AuthorizationRoles.ServiceRestricted | AuthorizationRoles.SalesRestricted | AuthorizationRoles.TechRestricted,
Select = AuthorizationRoles.All
});
////////////////////////////////////////////////////////////
//WorkOrderTemplateItem
//
roles.Add(AyaType.WorkOrderTemplateItem, new BizRoleSet()
{
Change = AuthorizationRoles.BizAdmin | AuthorizationRoles.Service | AuthorizationRoles.Sales | AuthorizationRoles.Tech | AuthorizationRoles.Accounting,
ReadFullRecord = AuthorizationRoles.BizAdminRestricted | AuthorizationRoles.ServiceRestricted | AuthorizationRoles.SalesRestricted | AuthorizationRoles.TechRestricted,
Select = AuthorizationRoles.All
});
////////////////////////////////////////////////////////////
//GLOBAL BIZ SETTINGS

View File

@@ -1,309 +0,0 @@
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using AyaNova.Util;
using AyaNova.Api.ControllerHelpers;
using AyaNova.Models;
namespace AyaNova.Biz
{
internal class PMTemplateBiz : BizObject, ISearchAbleObject, INotifiableObject
{
internal PMTemplateBiz(AyContext dbcontext, long currentUserId, long userTranslationId, AuthorizationRoles UserRoles)
{
ct = dbcontext;
UserId = currentUserId;
UserTranslationId = userTranslationId;
CurrentUserRoles = UserRoles;
BizType = AyaType.PMTemplate;
}
internal static PMTemplateBiz GetBiz(AyContext ct, Microsoft.AspNetCore.Http.HttpContext httpContext = null)
{
if (httpContext != null)
return new PMTemplateBiz(ct, UserIdFromContext.Id(httpContext.Items), UserTranslationIdFromContext.Id(httpContext.Items), UserRolesFromContext.Roles(httpContext.Items));
else
return new PMTemplateBiz(ct, 1, ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION_ID, AuthorizationRoles.BizAdmin);
}
////////////////////////////////////////////////////////////////////////////////////////////////
//EXISTS
internal async Task<bool> ExistsAsync(long id)
{
return await ct.PMTemplate.AnyAsync(z => z.Id == id);
}
//###################################################################################################################################################
//###################################################################################################################################################
// WARNING! THIS OBJECT IS AN INITIAL TEST VERSION NOT UP TO CURRENT STANDARDS, SEE WORKORDERBIZ FOR HOW THIS SHOULD BE CODED
//###################################################################################################################################################
//###################################################################################################################################################
////////////////////////////////////////////////////////////////////////////////////////////////
//CREATE
//
internal async Task<PMTemplate> CreateAsync(PMTemplate newObject)
{
await ValidateAsync(newObject, null);
if (HasErrors)
return null;
else
{
newObject.Tags = TagBiz.NormalizeTags(newObject.Tags);
newObject.CustomFields = JsonUtil.CompactJson(newObject.CustomFields);
await ct.PMTemplate.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;
}
}
// ////////////////////////////////////////////////////////////////////////////////////////////////
// //DUPLICATE
// //
// internal async Task<PMTemplate> DuplicateAsync(long id)
// {
// PMTemplate dbObject = await GetAsync(id, false);
// if (dbObject == null)
// {
// AddError(ApiErrorCode.NOT_FOUND, "id");
// return null;
// }
// PMTemplate newObject = new PMTemplate();
// CopyObject.Copy(dbObject, newObject, "Wiki");
// string newUniqueName = string.Empty;
// bool NotUnique = true;
// long l = 1;
// do
// {
// newUniqueName = Util.StringUtil.UniqueNameBuilder(dbObject.Name, l++, 255);
// NotUnique = await ct.PMTemplate.AnyAsync(z => z.Name == newUniqueName);
// } while (NotUnique);
// newObject.Name = newUniqueName;
// newObject.Id = 0;
// newObject.Concurrency = 0;
// await ct.PMTemplate.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
//
internal async Task<PMTemplate> GetAsync(long id, bool logTheGetEvent = true)
{
var ret = await ct.PMTemplate.SingleOrDefaultAsync(z => z.Id == id);
if (logTheGetEvent && ret != null)
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, id, BizType, AyaEvent.Retrieved), ct);
return ret;
}
//###################################################################################################################################################
//###################################################################################################################################################
// WARNING! THIS OBJECT IS AN INITIAL TEST VERSION NOT UP TO CURRENT STANDARDS, SEE PARTASSEMBLYBIZ / some of WORKORDERBIZ FOR HOW THIS SHOULD BE CODED
//###################################################################################################################################################
//###################################################################################################################################################
////////////////////////////////////////////////////////////////////////////////////////////////
//UPDATE
//
internal async Task<PMTemplate> PutAsync(PMTemplate putObject)
{
PMTemplate dbObject = await ct.PMTemplate.SingleOrDefaultAsync(z => z.Id == putObject.Id);
if (dbObject == null)
{
AddError(ApiErrorCode.NOT_FOUND, "id");
return null;
}
PMTemplate SnapshotOfOriginalDBObj = new PMTemplate();
CopyObject.Copy(dbObject, SnapshotOfOriginalDBObj);
CopyObject.Copy(putObject, dbObject, "Id");
dbObject.Tags = TagBiz.NormalizeTags(dbObject.Tags);
dbObject.CustomFields = JsonUtil.CompactJson(dbObject.CustomFields);
ct.Entry(dbObject).OriginalValues["Concurrency"] = putObject.Concurrency;
await ValidateAsync(dbObject, SnapshotOfOriginalDBObj);
if (HasErrors) return null;
try
{
await ct.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!await ExistsAsync(putObject.Id))
AddError(ApiErrorCode.NOT_FOUND);
else
AddError(ApiErrorCode.CONCURRENCY_CONFLICT);
return null;
}
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, BizType, AyaEvent.Modified), ct);
await SearchIndexAsync(dbObject, false);
await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, dbObject.Tags, SnapshotOfOriginalDBObj.Tags);
await HandlePotentialNotificationEvent(AyaEvent.Modified, dbObject, SnapshotOfOriginalDBObj);
return dbObject;
}
////////////////////////////////////////////////////////////////////////////////////////////////
//DELETE
//
internal async Task<bool> DeleteAsync(long id)
{
using (var transaction = await ct.Database.BeginTransactionAsync())
{
try
{
PMTemplate dbObject = await ct.PMTemplate.SingleOrDefaultAsync(z => z.Id == id);
if (dbObject == null)
{
AddError(ApiErrorCode.NOT_FOUND);
return false;
}
ValidateCanDelete(dbObject);
if (HasErrors)
return false;
if (HasErrors)
return false;
ct.PMTemplate.Remove(dbObject);
await ct.SaveChangesAsync();
//Log event
await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObject.Id, dbObject.Name, ct);
await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, BizType, ct);
await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags);
await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct);
await transaction.CommitAsync();
await HandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject);
}
catch
{
//Just re-throw for now, let exception handler deal, but in future may want to deal with this more here
throw;
}
return true;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////
//SEARCH
//
private async Task SearchIndexAsync(PMTemplate 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<Search.SearchIndexProcessObjectParameters> GetSearchResultSummary(long id)
{
var obj = await ct.PMTemplate.SingleOrDefaultAsync(z => z.Id == id);
var SearchParams = new Search.SearchIndexProcessObjectParameters();
DigestSearchText(obj, SearchParams);
return SearchParams;
}
public void DigestSearchText(PMTemplate obj, Search.SearchIndexProcessObjectParameters searchParams)
{
if (obj != null)
searchParams.AddText(obj.Notes)
.AddText(obj.Name)
.AddText(obj.Wiki)
.AddText(obj.Tags)
.AddCustomFields(obj.CustomFields);
}
////////////////////////////////////////////////////////////////////////////////////////////////
//VALIDATION
//
private async Task ValidateAsync(PMTemplate proposedObj, PMTemplate currentObj)
{
bool isNew = currentObj == null;
//Name required
if (string.IsNullOrWhiteSpace(proposedObj.Name))
AddError(ApiErrorCode.VALIDATION_REQUIRED, "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.PMTemplate.AnyAsync(z => z.Name == proposedObj.Name && z.Id != proposedObj.Id))
{
AddError(ApiErrorCode.VALIDATION_NOT_UNIQUE, "Name");
}
}
//Any form customizations to validate?
var FormCustomization = await ct.FormCustom.AsNoTracking().SingleOrDefaultAsync(z => z.FormKey == AyaType.PMTemplate.ToString());
if (FormCustomization != null)
{
//Yeppers, do the validation, there are two, the custom fields and the regular fields that might be set to required
//validate users choices for required non custom fields
RequiredFieldsValidator.Validate(this, FormCustomization, proposedObj);
//validate custom fields
CustomFieldsValidator.Validate(this, FormCustomization, proposedObj.CustomFields);
}
}
private void ValidateCanDelete(PMTemplate inObj)
{
//whatever needs to be check to delete this object
}
////////////////////////////////////////////////////////////////////////////////////////////////
// NOTIFICATION PROCESSING
//
public async Task HandlePotentialNotificationEvent(AyaEvent ayaEvent, ICoreBizObjectModel proposedObj, ICoreBizObjectModel currentObj = null)
{
ILogger log = AyaNova.Util.ApplicationLogging.CreateLogger<PMTemplateBiz>();
if (ServerBootConfig.SEEDING) return;
log.LogDebug($"HandlePotentialNotificationEvent processing: [AyaType:{this.BizType}, AyaEvent:{ayaEvent}]");
bool isNew = currentObj == null;
//STANDARD EVENTS FOR ALL OBJECTS
await NotifyEventHelper.ProcessStandardObjectEvents(ayaEvent, proposedObj, ct);
//SPECIFIC EVENTS FOR THIS OBJECT
}//end of process notifications
/////////////////////////////////////////////////////////////////////
}//eoc
}//eons

View File

@@ -1,307 +0,0 @@
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using AyaNova.Util;
using AyaNova.Api.ControllerHelpers;
using AyaNova.Models;
namespace AyaNova.Biz
{
internal class QuoteTemplateBiz : BizObject, ISearchAbleObject
{
internal QuoteTemplateBiz(AyContext dbcontext, long currentUserId, long userTranslationId, AuthorizationRoles UserRoles)
{
ct = dbcontext;
UserId = currentUserId;
UserTranslationId = userTranslationId;
CurrentUserRoles = UserRoles;
BizType = AyaType.QuoteTemplate;
}
internal static QuoteTemplateBiz GetBiz(AyContext ct, Microsoft.AspNetCore.Http.HttpContext httpContext = null)
{
if (httpContext != null)
return new QuoteTemplateBiz(ct, UserIdFromContext.Id(httpContext.Items), UserTranslationIdFromContext.Id(httpContext.Items), UserRolesFromContext.Roles(httpContext.Items));
else//when called internally for internal ops there will be no context so need to set default values for that
return new QuoteTemplateBiz(ct, 1, ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION_ID, AuthorizationRoles.BizAdmin);
}
////////////////////////////////////////////////////////////////////////////////////////////////
//EXISTS
internal async Task<bool> ExistsAsync(long id)
{
return await ct.QuoteTemplate.AnyAsync(z => z.Id == id);
}
//###################################################################################################################################################
//###################################################################################################################################################
// WARNING! THIS OBJECT IS AN INITIAL TEST VERSION NOT UP TO CURRENT STANDARDS, SEE WORKORDERBIZ FOR HOW THIS SHOULD BE CODED
//###################################################################################################################################################
//###################################################################################################################################################
////////////////////////////////////////////////////////////////////////////////////////////////
/// GET
///
///
internal async Task<QuoteTemplate> GetAsync(long fetchId, bool logTheGetEvent = true)
{
//This is simple so nothing more here, but often will be copying to a different output object or some other ops
var ret = await ct.QuoteTemplate.SingleOrDefaultAsync(z => z.Id == fetchId);
if (logTheGetEvent && ret != null)
{
//Log
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, fetchId, BizType, AyaEvent.Retrieved), ct);
}
return ret;
}
////////////////////////////////////////////////////////////////////////////////////////////////
//CREATE
//Called from route and also seeder
internal async Task<QuoteTemplate> CreateAsync(QuoteTemplate inObj)
{
await ValidateAsync(inObj, null);
if (HasErrors)
return null;
else
{
//do stuff with QuoteTemplate
QuoteTemplate outObj = inObj;
outObj.Tags = TagBiz.NormalizeTags(outObj.Tags);
outObj.CustomFields = JsonUtil.CompactJson(outObj.CustomFields);
//Save to db
await ct.QuoteTemplate.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 TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, outObj.Tags, null);
return outObj;
}
}
// ////////////////////////////////////////////////////////////////////////////////////////////////
// //DUPLICATE
// //
// internal async Task<QuoteTemplate> DuplicateAsync(QuoteTemplate dbObject)
// {
// QuoteTemplate outObj = new QuoteTemplate();
// CopyObject.Copy(dbObject, 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(dbObject.Name, l++, 255);
// NotUnique = await ct.QuoteTemplate.AnyAsync(z => z.Name == newUniqueName);
// } while (NotUnique);
// outObj.Name = newUniqueName;
// outObj.Id = 0;
// outObj.Concurrency = 0;
// await ct.QuoteTemplate.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 TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, outObj.Tags, null);
// return outObj;
// }
//###################################################################################################################################################
//###################################################################################################################################################
// WARNING! THIS OBJECT IS AN INITIAL TEST VERSION NOT UP TO CURRENT STANDARDS, SEE PARTASSEMBLYBIZ / some of WORKORDERBIZ FOR HOW THIS SHOULD BE CODED
//###################################################################################################################################################
//###################################################################################################################################################
////////////////////////////////////////////////////////////////////////////////////////////////
//UPDATE
//
//put
internal async Task<bool> PutAsync(QuoteTemplate dbObject, QuoteTemplate inObj)
{
//make a snapshot of the original for validation but update the original to preserve workflow
QuoteTemplate SnapshotOfOriginalDBObj = new QuoteTemplate();
CopyObject.Copy(dbObject, SnapshotOfOriginalDBObj);
//Replace the db object with the PUT object
CopyObject.Copy(inObj, dbObject, "Id");
dbObject.Tags = TagBiz.NormalizeTags(dbObject.Tags);
dbObject.CustomFields = JsonUtil.CompactJson(dbObject.CustomFields);
//Set "original" value of concurrency token to input token
//this will allow EF to check it out
ct.Entry(dbObject).OriginalValues["Concurrency"] = inObj.Concurrency;
await ValidateAsync(dbObject, SnapshotOfOriginalDBObj);
if (HasErrors)
return false;
//Log event and save context
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, BizType, AyaEvent.Modified), ct);
await SearchIndexAsync(dbObject, false);
await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, dbObject.Tags, SnapshotOfOriginalDBObj.Tags);
return true;
}
//###################################################################################################################################################
//###################################################################################################################################################
// WARNING! THIS OBJECT IS AN INITIAL TEST VERSION NOT UP TO CURRENT STANDARDS, SEE WORKORDERBIZ FOR HOW THIS SHOULD BE CODED
//###################################################################################################################################################
//###################################################################################################################################################
////////////////////////////////////////////////////////////////////////////////////////////////
//SEARCH
//
private async Task SearchIndexAsync(QuoteTemplate 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<Search.SearchIndexProcessObjectParameters> GetSearchResultSummary(long id)
{
var obj = await ct.QuoteTemplate.SingleOrDefaultAsync(z => z.Id == id);
var SearchParams = new Search.SearchIndexProcessObjectParameters();
DigestSearchText(obj, SearchParams);
return SearchParams;
}
public void DigestSearchText(QuoteTemplate obj, Search.SearchIndexProcessObjectParameters searchParams)
{
if (obj != null)
searchParams.AddText(obj.Notes)
.AddText(obj.Name)
.AddText(obj.Wiki)
.AddText(obj.Tags)
.AddCustomFields(obj.CustomFields);
}
////////////////////////////////////////////////////////////////////////////////////////////////
//DELETE
//
internal async Task<bool> DeleteAsync(QuoteTemplate dbObject)
{
//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(dbObject);
if (HasErrors)
return false;
ct.QuoteTemplate.Remove(dbObject);
await ct.SaveChangesAsync();
//Log event
await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObject.Id, dbObject.Name, ct);
await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, BizType, ct);
await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags);
await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct);
return true;
}
////////////////////////////////////////////////////////////////////////////////////////////////
//VALIDATION
//
//Can save or update?
private async Task ValidateAsync(QuoteTemplate proposedObj, QuoteTemplate currentObj)
{
//run validation and biz rules
bool isNew = currentObj == null;
//Name required
if (string.IsNullOrWhiteSpace(proposedObj.Name))
AddError(ApiErrorCode.VALIDATION_REQUIRED, "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.QuoteTemplate.AnyAsync(z => z.Name == proposedObj.Name && z.Id != proposedObj.Id))
{
AddError(ApiErrorCode.VALIDATION_NOT_UNIQUE, "Name");
}
}
//Any form customizations to validate?
var FormCustomization = await ct.FormCustom.AsNoTracking().SingleOrDefaultAsync(z => z.FormKey == AyaType.QuoteTemplate.ToString());
if (FormCustomization != null)
{
//Yeppers, do the validation, there are two, the custom fields and the regular fields that might be set to required
//validate users choices for required non custom fields
RequiredFieldsValidator.Validate(this, FormCustomization, proposedObj);
//validate custom fields
CustomFieldsValidator.Validate(this, FormCustomization, proposedObj.CustomFields);
}
}
//Can delete?
// private void ValidateCanDelete(QuoteTemplate inObj)
// {
// //whatever needs to be check to delete this object
// }
////////////////////////////////////////////////////////////////////////////////////////////////
//JOB / OPERATIONS
//
//Other job handlers here...
/////////////////////////////////////////////////////////////////////
}//eoc
}//eons

View File

@@ -1,322 +0,0 @@
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using AyaNova.Util;
using AyaNova.Api.ControllerHelpers;
using AyaNova.Models;
namespace AyaNova.Biz
{
internal class WorkOrderTemplateBiz : BizObject, ISearchAbleObject, INotifiableObject
{
internal WorkOrderTemplateBiz(AyContext dbcontext, long currentUserId, long userTranslationId, AuthorizationRoles UserRoles)
{
ct = dbcontext;
UserId = currentUserId;
UserTranslationId = userTranslationId;
CurrentUserRoles = UserRoles;
BizType = AyaType.WorkOrderTemplate;
}
internal static WorkOrderTemplateBiz GetBiz(AyContext ct, Microsoft.AspNetCore.Http.HttpContext httpContext = null)
{
if (httpContext != null)
return new WorkOrderTemplateBiz(ct, UserIdFromContext.Id(httpContext.Items), UserTranslationIdFromContext.Id(httpContext.Items), UserRolesFromContext.Roles(httpContext.Items));
else//when called internally for internal ops there will be no context so need to set default values for that
return new WorkOrderTemplateBiz(ct, 1, ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION_ID, AuthorizationRoles.BizAdmin);
}
////////////////////////////////////////////////////////////////////////////////////////////////
//EXISTS
internal async Task<bool> ExistsAsync(long id)
{
return await ct.WorkOrderTemplate.AnyAsync(z => z.Id == id);
}
////////////////////////////////////////////////////////////////////////////////////////////////
/// GET
///
///
internal async Task<WorkOrderTemplate> GetAsync(long fetchId, bool logTheGetEvent = true)
{
//This is simple so nothing more here, but often will be copying to a different output object or some other ops
var ret = await ct.WorkOrderTemplate.SingleOrDefaultAsync(z => z.Id == fetchId);
if (logTheGetEvent && ret != null)
{
//Log
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, fetchId, BizType, AyaEvent.Retrieved), ct);
}
return ret;
}
//###################################################################################################################################################
//###################################################################################################################################################
// WARNING! THIS OBJECT IS AN INITIAL TEST VERSION NOT UP TO CURRENT STANDARDS, SEE WORKORDERBIZ FOR HOW THIS SHOULD BE CODED
//###################################################################################################################################################
//###################################################################################################################################################
////////////////////////////////////////////////////////////////////////////////////////////////
//CREATE
//Called from route and also seeder
internal async Task<WorkOrderTemplate> CreateAsync(WorkOrderTemplate newObject)
{
await ValidateAsync(newObject, null);
if (HasErrors)
return null;
else
{
//do stuff with WorkOrderTemplate
WorkOrderTemplate outObj = newObject;
outObj.Tags = TagBiz.NormalizeTags(outObj.Tags);
outObj.CustomFields = JsonUtil.CompactJson(outObj.CustomFields);
//Save to db
await ct.WorkOrderTemplate.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 TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, outObj.Tags, null);
await HandlePotentialNotificationEvent(AyaEvent.Created, newObject);
return outObj;
}
}
// ////////////////////////////////////////////////////////////////////////////////////////////////
// //DUPLICATE
// //
// internal async Task<WorkOrderTemplate> DuplicateAsync(WorkOrderTemplate dbObject)
// {
// WorkOrderTemplate newObject = new WorkOrderTemplate();
// CopyObject.Copy(dbObject, newObject, "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(dbObject.Name, l++, 255);
// NotUnique = await ct.WorkOrderTemplate.AnyAsync(z => z.Name == newUniqueName);
// } while (NotUnique);
// newObject.Name = newUniqueName;
// newObject.Id = 0;
// newObject.Concurrency = 0;
// await ct.WorkOrderTemplate.AddAsync(newObject);
// await ct.SaveChangesAsync();
// //Handle child and associated items:
// 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;
// }
//###################################################################################################################################################
//###################################################################################################################################################
// WARNING! THIS OBJECT IS AN INITIAL TEST VERSION NOT UP TO CURRENT STANDARDS, SEE PARTASSEMBLYBIZ / some of WORKORDERBIZ FOR HOW THIS SHOULD BE CODED
//###################################################################################################################################################
//###################################################################################################################################################
////////////////////////////////////////////////////////////////////////////////////////////////
//UPDATE
//
//put
internal async Task<bool> PutAsync(WorkOrderTemplate dbObject, WorkOrderTemplate inObj)
{
//make a snapshot of the original for validation but update the original to preserve workflow
WorkOrderTemplate SnapshotOfOriginalDBObj = new WorkOrderTemplate();
CopyObject.Copy(dbObject, SnapshotOfOriginalDBObj);
//Replace the db object with the PUT object
CopyObject.Copy(inObj, dbObject, "Id");
dbObject.Tags = TagBiz.NormalizeTags(dbObject.Tags);
dbObject.CustomFields = JsonUtil.CompactJson(dbObject.CustomFields);
//Set "original" value of concurrency token to input token
//this will allow EF to check it out
ct.Entry(dbObject).OriginalValues["Concurrency"] = inObj.Concurrency;
await ValidateAsync(dbObject, SnapshotOfOriginalDBObj);
if (HasErrors)
return false;
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, dbObject.Id, BizType, AyaEvent.Modified), ct);
await SearchIndexAsync(dbObject, false);
await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, dbObject.Tags, SnapshotOfOriginalDBObj.Tags);
await HandlePotentialNotificationEvent(AyaEvent.Modified, dbObject, SnapshotOfOriginalDBObj);
return true;
}
////////////////////////////////////////////////////////////////////////////////////////////////
//SEARCH
//
private async Task SearchIndexAsync(WorkOrderTemplate 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<Search.SearchIndexProcessObjectParameters> GetSearchResultSummary(long id)
{
var obj = await ct.WorkOrderTemplate.SingleOrDefaultAsync(z => z.Id == id);
var SearchParams = new Search.SearchIndexProcessObjectParameters();
DigestSearchText(obj, SearchParams);
return SearchParams;
}
public void DigestSearchText(WorkOrderTemplate obj, Search.SearchIndexProcessObjectParameters searchParams)
{
if (obj != null)
searchParams.AddText(obj.Notes)
.AddText(obj.Name)
.AddText(obj.Wiki)
.AddText(obj.Tags)
.AddCustomFields(obj.CustomFields);
}
//###################################################################################################################################################
//###################################################################################################################################################
// WARNING! THIS OBJECT IS AN INITIAL TEST VERSION NOT UP TO CURRENT STANDARDS, SEE WORKORDERBIZ FOR HOW THIS SHOULD BE CODED
//###################################################################################################################################################
//###################################################################################################################################################
////////////////////////////////////////////////////////////////////////////////////////////////
//DELETE
//
internal async Task<bool> DeleteAsync(WorkOrderTemplate dbObject)
{
//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(dbObject);
if (HasErrors)
return false;
ct.WorkOrderTemplate.Remove(dbObject);
await ct.SaveChangesAsync();
//Log event
await EventLogProcessor.DeleteObjectLogAsync(UserId, BizType, dbObject.Id, dbObject.Name, ct);
await Search.ProcessDeletedObjectKeywordsAsync(dbObject.Id, BizType, ct);
await TagBiz.ProcessDeleteTagsInRepositoryAsync(ct, dbObject.Tags);
await FileUtil.DeleteAttachmentsForObjectAsync(BizType, dbObject.Id, ct);
await HandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject);
return true;
}
////////////////////////////////////////////////////////////////////////////////////////////////
//VALIDATION
//
//Can save or update?
private async Task ValidateAsync(WorkOrderTemplate proposedObj, WorkOrderTemplate currentObj)
{
//run validation and biz rules
bool isNew = currentObj == null;
//Name required
if (string.IsNullOrWhiteSpace(proposedObj.Name))
AddError(ApiErrorCode.VALIDATION_REQUIRED, "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.WorkOrderTemplate.AnyAsync(z => z.Name == proposedObj.Name && z.Id != proposedObj.Id))
{
AddError(ApiErrorCode.VALIDATION_NOT_UNIQUE, "Name");
}
}
//Any form customizations to validate?
var FormCustomization = await ct.FormCustom.AsNoTracking().SingleOrDefaultAsync(z => z.FormKey == AyaType.WorkOrderTemplate.ToString());
if (FormCustomization != null)
{
//Yeppers, do the validation, there are two, the custom fields and the regular fields that might be set to required
//validate users choices for required non custom fields
RequiredFieldsValidator.Validate(this, FormCustomization, proposedObj);
//validate custom fields
CustomFieldsValidator.Validate(this, FormCustomization, proposedObj.CustomFields);
}
}
//Can delete?
// private void ValidateCanDelete(WorkOrderTemplate inObj)
// {
// //whatever needs to be check to delete this object
// }
////////////////////////////////////////////////////////////////////////////////////////////////
// NOTIFICATION PROCESSING
//
public async Task HandlePotentialNotificationEvent(AyaEvent ayaEvent, ICoreBizObjectModel proposedObj, ICoreBizObjectModel currentObj = null)
{
ILogger log = AyaNova.Util.ApplicationLogging.CreateLogger<WorkOrderTemplateBiz>();
if (ServerBootConfig.SEEDING) return;
log.LogDebug($"HandlePotentialNotificationEvent processing: [AyaType:{this.BizType}, AyaEvent:{ayaEvent}]");
bool isNew = currentObj == null;
//STANDARD EVENTS FOR ALL OBJECTS
await NotifyEventHelper.ProcessStandardObjectEvents(ayaEvent, proposedObj, ct);
//SPECIFIC EVENTS FOR THIS OBJECT
}//end of process notifications
/////////////////////////////////////////////////////////////////////
}//eoc
}//eons

View File

@@ -54,15 +54,12 @@ namespace AyaNova.Models
public virtual DbSet<PartAssemblyItem> PartAssemblyItem { get; set; }
public virtual DbSet<PM> PM { get; set; }
public virtual DbSet<PMItem> PMItem { get; set; }
public virtual DbSet<PMTemplate> PMTemplate { get; set; }
public virtual DbSet<PMTemplateItem> PMTemplateItem { get; set; }
public virtual DbSet<Project> Project { get; set; }
public virtual DbSet<PurchaseOrder> PurchaseOrder { get; set; }
public virtual DbSet<PurchaseOrderItem> PurchaseOrderItem { get; set; }
public virtual DbSet<Quote> Quote { get; set; }
public virtual DbSet<QuoteItem> QuoteItem { get; set; }
public virtual DbSet<QuoteTemplate> QuoteTemplate { get; set; }
public virtual DbSet<QuoteTemplateItem> QuoteTemplateItem { get; set; }
public virtual DbSet<Unit> Unit { get; set; }
public virtual DbSet<UnitModel> UnitModel { get; set; }
public virtual DbSet<Vendor> Vendor { get; set; }
@@ -92,9 +89,25 @@ namespace AyaNova.Models
public virtual DbSet<WorkOrderItemPriority> WorkOrderItemPriority { get; set; }
public virtual DbSet<WorkOrderItemStatus> WorkOrderItemStatus { get; set; }
//WorkOrderTemplate
public virtual DbSet<WorkOrderTemplate> WorkOrderTemplate { get; set; }
public virtual DbSet<WorkOrderTemplateItem> WorkOrderTemplateItem { get; set; }
//Quote
public virtual DbSet<Quote> Quote { get; set; }
public virtual DbSet<QuoteItem> QuoteItem { get; set; }
public virtual DbSet<QuoteState> QuoteState { get; set; }
public virtual DbSet<QuoteItemExpense> QuoteItemExpense { get; set; }
public virtual DbSet<QuoteItemLabor> QuoteItemLabor { get; set; }
public virtual DbSet<QuoteItemLoan> QuoteItemLoan { get; set; }
public virtual DbSet<QuoteItemPart> QuoteItemPart { get; set; }
public virtual DbSet<QuoteItemScheduledUser> QuoteItemScheduledUser { get; set; }
public virtual DbSet<QuoteItemTask> QuoteItemTask { get; set; }
public virtual DbSet<QuoteItemTravel> QuoteItemTravel { get; set; }
public virtual DbSet<QuoteItemUnit> QuoteItemUnit { get; set; }
public virtual DbSet<QuoteItemOutsideService> QuoteItemOutsideService { get; set; }
public virtual DbSet<QuoteStatus> QuoteStatus { get; set; }
public virtual DbSet<QuoteItemPriority> QuoteItemPriority { get; set; }
public virtual DbSet<QuoteItemStatus> QuoteItemStatus { get; set; }
public virtual DbSet<Logo> Logo { get; set; }
public virtual DbSet<Report> Report { get; set; }

View File

@@ -1,37 +0,0 @@
using System;
using System.Collections.Generic;
using AyaNova.Biz;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Newtonsoft.Json;
namespace AyaNova.Models
{
//NOTE: Any non required field (nullable in DB) sb nullable here, i.e. decimal? not decimal,
//otherwise the server will call it an invalid record if the field isn't sent from client
public class PMTemplate : ICoreBizObjectModel
{
public long Id { get; set; }
public uint Concurrency { get; set; }
[Required]
public string Name { get; set; }
public bool Active { get; set; }
public string Notes { get; set; }
public string Wiki { get; set; }
public string CustomFields { get; set; }
public List<string> Tags { get; set; }
public PMTemplate()
{
Tags = new List<string>();
}
[NotMapped, JsonIgnore]
public AyaType AyaType { get => AyaType.PMTemplate; }
}//eoc
}//eons

View File

@@ -1,37 +0,0 @@
using System;
using System.Collections.Generic;
using AyaNova.Biz;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Newtonsoft.Json;
namespace AyaNova.Models
{
//NOTE: Any non required field (nullable in DB) sb nullable here, i.e. decimal? not decimal,
//otherwise the server will call it an invalid record if the field isn't sent from client
public class PMTemplateItem : ICoreBizObjectModel
{
public long Id { get; set; }
public uint Concurrency { get; set; }
[Required]
public string Name { get; set; }
public bool Active { get; set; }
public string Notes { get; set; }
public string Wiki { get; set; }
public string CustomFields { get; set; }
public List<string> Tags { get; set; }
public PMTemplateItem()
{
Tags = new List<string>();
}
[NotMapped, JsonIgnore]
public AyaType AyaType { get => AyaType.PMTemplateItem; }
}//eoc
}//eons

View File

@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
@@ -6,8 +7,6 @@ using AyaNova.Biz;
namespace AyaNova.Models
{
//NOTE: Any non required field (nullable in DB) sb nullable here, i.e. decimal? not decimal,
//otherwise the server will call it an invalid record if the field isn't sent from client
public class Quote : ICoreBizObjectModel
{
@@ -16,37 +15,148 @@ namespace AyaNova.Models
[Required]
public long Serial { get; set; }
public bool Active { get; set; }
public string Notes { get; set; }
public string Notes { get; set; }//WAS "SUMMARY"
public string Wiki { get; set; }
public string CustomFields { get; set; }
public List<string> Tags { get; set; }
public List<string> Tags { get; set; } = new List<string>();
[Required]
public long CustomerId { get; set; }
[NotMapped]
public string CustomerViz { get; set; }
[NotMapped]
public string CustomerTechNotesViz { get; set; }
public long? ProjectId { get; set; }
[NotMapped]
public string ProjectViz { get; set; }
public string InternalReferenceNumber { get; set; }
public string CustomerReferenceNumber { get; set; }
public string CustomerContactName { get; set; }
public DateTime CreatedDate { get; set; } = DateTime.UtcNow;
public DateTime? ServiceDate { get; set; }
public DateTime? CompleteByDate { get; set; }
public TimeSpan DurationToCompleted { get; set; } = TimeSpan.Zero;
public string InvoiceNumber { get; set; }
public string CustomerSignature { get; set; }
public string CustomerSignatureName { get; set; }
public DateTime? CustomerSignatureCaptured { get; set; }
public string TechSignature { get; set; }
public string TechSignatureName { get; set; }
public DateTime? TechSignatureCaptured { get; set; }
public bool Onsite { get; set; }
public long? ContractId { get; set; }
[NotMapped]
public string ContractViz { get; set; }
//redundant field to speed up list queries
//(added after status system already coded)
public long? LastStatusId { get; set; }
//POSTAL ADDRESS / "BILLING ADDRESS"
public string PostAddress { get; set; }
public string PostCity { get; set; }
public string PostRegion { get; set; }
public string PostCountry { get; set; }
public string PostCode { get; set; }
//PHYSICAL ADDRESS / "SERVICE ADDRESS"
public string Address { get; set; }
public string City { get; set; }
public string Region { get; set; }
public string Country { get; set; }
public decimal? Latitude { get; set; }
public decimal? Longitude { get; set; }
public List<WorkOrderItem> Items { get; set; } = new List<WorkOrderItem>();
public List<WorkOrderState> States { get; set; } = new List<WorkOrderState>();
//UTILITY FIELDS
[NotMapped]
public bool IsLockedAtServer { get; set; } = false;//signal to client that it came from the server in a locked state
[NotMapped]
public string AlertViz { get; set; } = null;
[NotMapped]
public string FromQuoteViz { get; set; }
[NotMapped]
public string FromPMViz { get; set; }
[NotMapped]
public string FromCSRViz { get; set; }
[NotMapped]
public bool IsCompleteRecord { get; set; } = true;//indicates if some items were removed due to user role / type restrictions (i.e. woitems they are not scheduled on)
[NotMapped]
public bool UserIsRestrictedType { get; set; }
[NotMapped]
public bool UserIsTechRestricted { get; set; }
[NotMapped]
public bool UserIsSubContractorFull { get; set; }
[NotMapped]
public bool UserIsSubContractorRestricted { get; set; }
[NotMapped]
public bool UserCanViewPartCosts { get; set; }
[NotMapped]
public bool UserCanViewLaborOrTravelRateCosts { get; set; }
[NotMapped]
public bool UserCanViewLoanerCosts { get; set; }
[NotMapped, JsonIgnore]
public AyaType AyaType { get => AyaType.WorkOrder; }
//workaround for notification
[NotMapped, JsonIgnore]
public string Name { get; set; }
/*
todo: Consider adding latitude / longitude to wo, quote, pm objects
can copy over from the unit or customer or set themselves
and can always hide
means wo could be scheduled for ad-hoc locations and serviced that way, i.e. a truck parked on the side of the highway etc
*/
//dependents
public List<QuoteItem> QuoteItems { get; set; }
public Quote()
{
Tags = new List<string>();
QuoteItems = new List<QuoteItem>();
}
[NotMapped, JsonIgnore]
public AyaType AyaType { get => AyaType.Quote; }
}//eoc
}//eons
/*
QUOTE FIELDS
CREATE TABLE [dbo].[AWORKORDERQUOTE](
[AID] [uniqueidentifier] NOT NULL,
[AWORKORDERID] [uniqueidentifier] NOT NULL,
[ACREATOR] [uniqueidentifier] NOT NULL,
[AMODIFIER] [uniqueidentifier] NOT NULL,
[ACREATED] [datetime] NOT NULL,
[AMODIFIED] [datetime] NOT NULL,
[AQUOTENUMBER] [int] IDENTITY(1,1) NOT NULL,
[AQUOTESTATUSTYPE] [smallint] NULL,
[APREPAREDBYID] [uniqueidentifier] NULL,
[AQUOTEREQUESTDATE] [datetime] NULL,
[AINTRODUCTION] [nvarchar](255) NULL,
[AVALIDUNTILDATE] [datetime] NULL,
[ADATESUBMITTED] [datetime] NULL,
[ADATEAPPROVED] [datetime] NULL,
PRIMARY KEY NONCLUSTERED
QUOTE DOESN'T NEED THESE FIELDS
CREATE TABLE [dbo].[AWORKORDERSERVICE](
[AID] [uniqueidentifier] NOT NULL,
[AWORKORDERID] [uniqueidentifier] NOT NULL,
[ACREATOR] [uniqueidentifier] NOT NULL,
[AMODIFIER] [uniqueidentifier] NOT NULL,
[ACREATED] [datetime] NOT NULL,
[AMODIFIED] [datetime] NOT NULL,
[AWORKORDERSTATUSID] [uniqueidentifier] NULL,//## Replaced by workorderstate collection
[ASERVICEDATE] [datetime] NULL,
[AINVOICENUMBER] [nvarchar](255) NULL,
[ASERVICENUMBER] [int] IDENTITY(1,1) NOT NULL,//## replaced by Serial field
[AQUOTEWORKORDERID] [uniqueidentifier] NULL,
[ACLIENTREQUESTID] [uniqueidentifier] NULL,//# now FromCSRId
[APREVENTIVEMAINTENANCEID] [uniqueidentifier] NULL,
[ACLOSEBYDATE] [datetime] NULL,//## Now CompleteByDate
[ASIGNATURE] [ntext] NULL,//# now customersignature (more sig types coming)
[ASIGNED] [datetime] NULL,//# now CustomerSignatureCaptured
*/

View File

@@ -1,37 +0,0 @@
using System;
using System.Collections.Generic;
using AyaNova.Biz;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Newtonsoft.Json;
namespace AyaNova.Models
{
//NOTE: Any non required field (nullable in DB) sb nullable here, i.e. decimal? not decimal,
//otherwise the server will call it an invalid record if the field isn't sent from client
public class QuoteTemplate : ICoreBizObjectModel
{
public long Id { get; set; }
public uint Concurrency { get; set; }
[Required]
public string Name { get; set; }
public bool Active { get; set; }
public string Notes { get; set; }
public string Wiki { get; set; }
public string CustomFields { get; set; }
public List<string> Tags { get; set; }
public QuoteTemplate()
{
Tags = new List<string>();
}
[NotMapped, JsonIgnore]
public AyaType AyaType { get => AyaType.QuoteTemplate; }
}//eoc
}//eons

View File

@@ -1,37 +0,0 @@
using System;
using System.Collections.Generic;
using AyaNova.Biz;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Newtonsoft.Json;
namespace AyaNova.Models
{
//NOTE: Any non required field (nullable in DB) sb nullable here, i.e. decimal? not decimal,
//otherwise the server will call it an invalid record if the field isn't sent from client
public class QuoteTemplateItem : ICoreBizObjectModel
{
public long Id { get; set; }
public uint Concurrency { get; set; }
[Required]
public string Name { get; set; }
public bool Active { get; set; }
public string Notes { get; set; }
public string Wiki { get; set; }
public string CustomFields { get; set; }
public List<string> Tags { get; set; }
public QuoteTemplateItem()
{
Tags = new List<string>();
}
[NotMapped, JsonIgnore]
public AyaType AyaType { get => AyaType.QuoteTemplateItem; }
}//eoc
}//eons

View File

@@ -1,37 +0,0 @@
using System;
using System.Collections.Generic;
using AyaNova.Biz;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Newtonsoft.Json;
namespace AyaNova.Models
{
//NOTE: Any non required field (nullable in DB) sb nullable here, i.e. decimal? not decimal,
//otherwise the server will call it an invalid record if the field isn't sent from client
public class WorkOrderTemplate : ICoreBizObjectModel
{
public long Id { get; set; }
public uint Concurrency { get; set; }
[Required]
public string Name { get; set; }
public bool Active { get; set; }
public string Notes { get; set; }
public string Wiki { get; set; }
public string CustomFields { get; set; }
public List<string> Tags { get; set; }
public WorkOrderTemplate()
{
Tags = new List<string>();
}
[NotMapped, JsonIgnore]
public AyaType AyaType { get => AyaType.WorkOrderTemplate; }
}//eoc
}//eons

View File

@@ -1,37 +0,0 @@
using System;
using System.Collections.Generic;
using AyaNova.Biz;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Newtonsoft.Json;
namespace AyaNova.Models
{
//NOTE: Any non required field (nullable in DB) sb nullable here, i.e. decimal? not decimal,
//otherwise the server will call it an invalid record if the field isn't sent from client
public class WorkOrderTemplateItem : ICoreBizObjectModel
{
public long Id { get; set; }
public uint Concurrency { get; set; }
[Required]
public string Name { get; set; }
public bool Active { get; set; }
public string Notes { get; set; }
public string Wiki { get; set; }
public string CustomFields { get; set; }
public List<string> Tags { get; set; }
public WorkOrderTemplateItem()
{
Tags = new List<string>();
}
[NotMapped, JsonIgnore]
public AyaType AyaType { get => AyaType.WorkOrderTemplateItem; }
}//eoc
}//eons

View File

@@ -896,30 +896,28 @@ $BODY$ LANGUAGE PLPGSQL STABLE");
//----------
//WORKORDERTEMPLATE
await ExecQueryAsync("CREATE TABLE aworkordertemplate (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, name TEXT NOT NULL UNIQUE, active BOOL NOT NULL, "
+ "notes TEXT, wiki TEXT, customfields TEXT, tags VARCHAR(255) ARRAY )");
await ExecQueryAsync("ALTER TABLE acustomer ADD column defaultservicetemplateid BIGINT NULL REFERENCES aworkordertemplate");
//WORKORDERTEMPLATEITEM
await ExecQueryAsync("CREATE TABLE aworkordertemplateitem (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, name TEXT NOT NULL UNIQUE, active BOOL NOT NULL, "
+ "notes TEXT, wiki TEXT, customfields TEXT, tags VARCHAR(255) ARRAY )");
//QUOTE
await ExecQueryAsync("CREATE TABLE aquote (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, serial BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, active BOOL NOT NULL, "
+ "notes TEXT, wiki TEXT, customfields TEXT, tags VARCHAR(255) ARRAY )");
/*
██████╗ ██╗ ██╗ ██████╗ ████████╗███████╗
██╔═══██╗██║ ██║██╔═══██╗╚══██╔══╝██╔════╝
██║ ██║██║ ██║██║ ██║ ██║ █████╗
██║▄▄ ██║██║ ██║██║ ██║ ██║ ██╔══╝
╚██████╔╝╚██████╔╝╚██████╔╝ ██║ ███████╗
╚══▀▀═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝
*/
//QUOTEITEM
await ExecQueryAsync("CREATE TABLE aquoteitem (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, quoteid BIGINT NOT NULL REFERENCES aquote (id), name TEXT NOT NULL UNIQUE, active BOOL NOT NULL, "
+ "notes TEXT, wiki TEXT, customfields TEXT, tags VARCHAR(255) ARRAY )");
//QUOTETEMPLATE
await ExecQueryAsync("CREATE TABLE aquotetemplate (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, name TEXT NOT NULL UNIQUE, active BOOL NOT NULL, "
+ "notes TEXT, wiki TEXT, customfields TEXT, tags VARCHAR(255) ARRAY )");
//QUOTETEMPLATEITEM
await ExecQueryAsync("CREATE TABLE aquotetemplateitem (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, name TEXT NOT NULL UNIQUE, active BOOL NOT NULL, "
+ "notes TEXT, wiki TEXT, customfields TEXT, tags VARCHAR(255) ARRAY )");
// //QUOTE
// await ExecQueryAsync("CREATE TABLE aquote (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, serial BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, active BOOL NOT NULL, "
// + "notes TEXT, wiki TEXT, customfields TEXT, tags VARCHAR(255) ARRAY )");
// //QUOTEITEM
// await ExecQueryAsync("CREATE TABLE aquoteitem (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, quoteid BIGINT NOT NULL REFERENCES aquote (id), name TEXT NOT NULL UNIQUE, active BOOL NOT NULL, "
// + "notes TEXT, wiki TEXT, customfields TEXT, tags VARCHAR(255) ARRAY )");
//PM
await ExecQueryAsync("CREATE TABLE apm (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, serial BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL, active BOOL NOT NULL, "
@@ -929,14 +927,6 @@ $BODY$ LANGUAGE PLPGSQL STABLE");
await ExecQueryAsync("CREATE TABLE apmitem (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, pmid BIGINT NOT NULL REFERENCES apm (id), name TEXT NOT NULL UNIQUE, active BOOL NOT NULL, "
+ "notes TEXT, wiki TEXT, customfields TEXT, tags VARCHAR(255) ARRAY )");
//PMTEMPLATE
await ExecQueryAsync("CREATE TABLE apmtemplate (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, name TEXT NOT NULL UNIQUE, active BOOL NOT NULL, "
+ "notes TEXT, wiki TEXT, customfields TEXT, tags VARCHAR(255) ARRAY )");
//PMTEMPLATEITEM
await ExecQueryAsync("CREATE TABLE apmtemplateitem (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, name TEXT NOT NULL UNIQUE, active BOOL NOT NULL, "
+ "notes TEXT, wiki TEXT, customfields TEXT, tags VARCHAR(255) ARRAY )");
//CUSTOMERSERVICEREQUEST
await ExecQueryAsync("CREATE TABLE acustomerservicerequest (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, name TEXT NOT NULL, "
+ "notes TEXT, wiki TEXT, customfields TEXT, tags VARCHAR(255) ARRAY, "