Final (?) de-widgetification
This commit is contained in:
@@ -23,7 +23,7 @@ namespace AyaNova.Api.Controllers
|
||||
public class SearchController : ControllerBase
|
||||
{
|
||||
private readonly AyContext ct;
|
||||
private readonly ILogger<WidgetController> log;
|
||||
private readonly ILogger<SearchController> log;
|
||||
private readonly ApiServerState serverState;
|
||||
|
||||
/// <summary>
|
||||
@@ -32,7 +32,7 @@ namespace AyaNova.Api.Controllers
|
||||
/// <param name="dbcontext"></param>
|
||||
/// <param name="logger"></param>
|
||||
/// <param name="apiServerState"></param>
|
||||
public SearchController(AyContext dbcontext, ILogger<WidgetController> logger, ApiServerState apiServerState)
|
||||
public SearchController(AyContext dbcontext, ILogger<SearchController> logger, ApiServerState apiServerState)
|
||||
{
|
||||
ct = dbcontext;
|
||||
log = logger;
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace AyaNova.Api.Controllers
|
||||
public class TrialController : ControllerBase
|
||||
{
|
||||
private readonly AyContext ct;
|
||||
private readonly ILogger<WidgetController> log;
|
||||
private readonly ILogger<TrialController> log;
|
||||
private readonly ApiServerState serverState;
|
||||
|
||||
/// <summary>
|
||||
@@ -31,7 +31,7 @@ namespace AyaNova.Api.Controllers
|
||||
/// <param name="dbcontext"></param>
|
||||
/// <param name="logger"></param>
|
||||
/// <param name="apiServerState"></param>
|
||||
public TrialController(AyContext dbcontext, ILogger<WidgetController> logger, ApiServerState apiServerState)
|
||||
public TrialController(AyContext dbcontext, ILogger<TrialController> logger, ApiServerState apiServerState)
|
||||
{
|
||||
ct = dbcontext;
|
||||
log = logger;
|
||||
|
||||
@@ -1,221 +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
|
||||
{
|
||||
//DOCUMENTATING THE API
|
||||
//https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/xmldoc/recommended-tags-for-documentation-comments
|
||||
//https://github.com/domaindrivendev/Swashbuckle.AspNetCore#include-descriptions-from-xml-comments
|
||||
|
||||
/// <summary>
|
||||
/// Sample controller class used during development for testing purposes
|
||||
/// </summary>
|
||||
[ApiController]
|
||||
[ApiVersion("8.0")]
|
||||
[Route("api/v{version:apiVersion}/widget")]
|
||||
[Produces("application/json")]
|
||||
[Authorize]
|
||||
public class WidgetController : ControllerBase
|
||||
{
|
||||
private readonly AyContext ct;
|
||||
private readonly ILogger<WidgetController> log;
|
||||
private readonly ApiServerState serverState;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
/// <param name="dbcontext"></param>
|
||||
/// <param name="logger"></param>
|
||||
/// <param name="apiServerState"></param>
|
||||
public WidgetController(AyContext dbcontext, ILogger<WidgetController> logger, ApiServerState apiServerState)
|
||||
{
|
||||
ct = dbcontext;
|
||||
log = logger;
|
||||
serverState = apiServerState;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create Widget
|
||||
/// </summary>
|
||||
/// <param name="newObject"></param>
|
||||
/// <param name="apiVersion">From route path</param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> PostWidget([FromBody] Widget newObject, ApiVersion apiVersion)
|
||||
{
|
||||
if (!serverState.IsOpen)
|
||||
return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));
|
||||
WidgetBiz biz = WidgetBiz.GetBiz(ct, HttpContext);
|
||||
if (!Authorized.HasCreateRole(HttpContext.Items, biz.BizType))
|
||||
return StatusCode(403, new ApiNotAuthorizedResponse());
|
||||
if (!ModelState.IsValid)
|
||||
return BadRequest(new ApiErrorResponse(ModelState));
|
||||
Widget o = await biz.CreateAsync(newObject);
|
||||
if (o == null)
|
||||
return BadRequest(new ApiErrorResponse(biz.Errors));
|
||||
else
|
||||
return CreatedAtAction(nameof(WidgetController.GetWidget), new { id = o.Id, version = apiVersion.ToString() }, new ApiCreatedResponse(o));
|
||||
}
|
||||
|
||||
// /// <summary>
|
||||
// /// Duplicate Widget
|
||||
// /// (Wiki and Attachments are not duplicated)
|
||||
// /// </summary>
|
||||
// /// <param name="id">Source object id</param>
|
||||
// /// <param name="apiVersion">From route path</param>
|
||||
// /// <returns>Widget</returns>
|
||||
// [HttpPost("duplicate/{id}")]
|
||||
// public async Task<IActionResult> DuplicateWidget([FromRoute] long id, ApiVersion apiVersion)
|
||||
// {
|
||||
// if (!serverState.IsOpen)
|
||||
// return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));
|
||||
// WidgetBiz biz = WidgetBiz.GetBiz(ct, HttpContext);
|
||||
// if (!Authorized.HasCreateRole(HttpContext.Items, biz.BizType))
|
||||
// return StatusCode(403, new ApiNotAuthorizedResponse());
|
||||
// if (!ModelState.IsValid)
|
||||
// return BadRequest(new ApiErrorResponse(ModelState));
|
||||
// Widget o = await biz.DuplicateAsync(id);
|
||||
// if (o == null)
|
||||
// return BadRequest(new ApiErrorResponse(biz.Errors));
|
||||
// else
|
||||
// return CreatedAtAction(nameof(WidgetController.GetWidget), new { id = o.Id, version = apiVersion.ToString() }, new ApiCreatedResponse(o));
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// Get Widget
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns>Widget</returns>
|
||||
[HttpGet("{id}")]
|
||||
public async Task<IActionResult> GetWidget([FromRoute] long id)
|
||||
{
|
||||
if (!serverState.IsOpen)
|
||||
return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));
|
||||
WidgetBiz biz = WidgetBiz.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 Widget
|
||||
/// </summary>
|
||||
/// <param name="updatedObject"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPut]
|
||||
public async Task<IActionResult> PutWidget([FromBody] Widget updatedObject)
|
||||
{
|
||||
if (!serverState.IsOpen)
|
||||
return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));
|
||||
if (!ModelState.IsValid)
|
||||
return BadRequest(new ApiErrorResponse(ModelState));
|
||||
WidgetBiz biz = WidgetBiz.GetBiz(ct, HttpContext);
|
||||
if (!Authorized.HasModifyRole(HttpContext.Items, biz.BizType))
|
||||
return StatusCode(403, new ApiNotAuthorizedResponse());
|
||||
var o = await biz.PutAsync(updatedObject);
|
||||
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 Widget
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns>NoContent</returns>
|
||||
[HttpDelete("{id}")]
|
||||
public async Task<IActionResult> DeleteWidget([FromRoute] long id)
|
||||
{
|
||||
if (!serverState.IsOpen)
|
||||
return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));
|
||||
if (!ModelState.IsValid)
|
||||
return BadRequest(new ApiErrorResponse(ModelState));
|
||||
WidgetBiz biz = WidgetBiz.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();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// ReStart serial number
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="newSerial">Next starting value for auto generated serial numbers</param>
|
||||
/// <param name="apiVersion">From route path</param>
|
||||
/// <returns>Widget</returns>
|
||||
[HttpPost("restart-serial/{newSerial}")]
|
||||
public async Task<IActionResult> ReStartSerial([FromRoute] long newSerial, ApiVersion apiVersion)
|
||||
{
|
||||
if (!serverState.IsOpen)
|
||||
return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));
|
||||
WidgetBiz biz = WidgetBiz.GetBiz(ct, HttpContext);
|
||||
if (!Authorized.HasCreateRole(HttpContext.Items, biz.BizType))
|
||||
return StatusCode(403, new ApiNotAuthorizedResponse());
|
||||
if (!ModelState.IsValid)
|
||||
return BadRequest(new ApiErrorResponse(ModelState));
|
||||
bool result=await biz.RestartSerial(newSerial);
|
||||
if (!result)
|
||||
return BadRequest(new ApiErrorResponse(biz.Errors));
|
||||
else
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////
|
||||
//TEST ROUTES
|
||||
//
|
||||
|
||||
/// <summary>
|
||||
/// Get route that triggers exception for testing
|
||||
/// </summary>
|
||||
/// <returns>Nothing, triggers exception</returns>
|
||||
[HttpGet("exception")]
|
||||
public ActionResult GetException()
|
||||
{
|
||||
//log.LogInformation("Widget::getexception-> Test exception and log from controller test");
|
||||
if (!serverState.IsOpen)
|
||||
return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));
|
||||
throw new System.NotSupportedException("Test exception from widget controller");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get route that triggers an alternate type of exception for testing
|
||||
/// </summary>
|
||||
/// <returns>Nothing, triggers exception</returns>
|
||||
[HttpGet("altexception")]
|
||||
public ActionResult GetAltException()
|
||||
{
|
||||
if (!serverState.IsOpen)
|
||||
return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));
|
||||
throw new System.ArgumentException("Test exception (ALT) from widget controller");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//------------
|
||||
|
||||
|
||||
}//eoc
|
||||
}//eons
|
||||
@@ -1,129 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using AyaNova.Biz;
|
||||
namespace AyaNova.DataList
|
||||
{
|
||||
internal class TestWidgetDataList : DataListProcessingBase
|
||||
{
|
||||
public TestWidgetDataList()
|
||||
{
|
||||
DefaultListAType = AyaType.Widget;
|
||||
SQLFrom = "from awidget left join auser on (awidget.userid=auser.id)";
|
||||
var RoleSet = BizRoles.GetRoleSet(DefaultListAType);
|
||||
AllowedRoles = RoleSet.ReadFullRecord | RoleSet.Change;
|
||||
DefaultColumns = new List<string>() { "widgetname", "widgetserial", "widgetdollaramount", "widgetusertype", "widgetstartdate", "widgetactive", "username" };
|
||||
DefaultSortBy = new Dictionary<string, string>() { { "widgetname", "+" } };
|
||||
FieldDefinitions = new List<DataListFieldDefinition>();
|
||||
|
||||
FieldDefinitions.Add(new DataListFieldDefinition
|
||||
{
|
||||
TKey = "WidgetName",
|
||||
FieldKey = "widgetname",
|
||||
AType = (int)AyaType.Widget,
|
||||
UiFieldDataType = (int)UiFieldDataType.Text,
|
||||
SqlIdColumnName = "awidget.id",
|
||||
SqlValueColumnName = "awidget.name",
|
||||
IsRowId = true
|
||||
});
|
||||
|
||||
FieldDefinitions.Add(new DataListFieldDefinition
|
||||
{
|
||||
TKey = "WidgetSerial",
|
||||
FieldKey = "widgetserial",
|
||||
UiFieldDataType = (int)UiFieldDataType.Integer,
|
||||
SqlValueColumnName = "awidget.serial"
|
||||
});
|
||||
|
||||
FieldDefinitions.Add(new DataListFieldDefinition
|
||||
{
|
||||
TKey = "WidgetDollarAmount",
|
||||
FieldKey = "widgetdollaramount",
|
||||
UiFieldDataType = (int)UiFieldDataType.Currency,
|
||||
SqlValueColumnName = "awidget.dollaramount"
|
||||
});
|
||||
|
||||
FieldDefinitions.Add(new DataListFieldDefinition
|
||||
{
|
||||
TKey = "WidgetCount",
|
||||
FieldKey = "widgetcount",
|
||||
UiFieldDataType = (int)UiFieldDataType.Integer,
|
||||
SqlValueColumnName = "awidget.count"
|
||||
});
|
||||
|
||||
FieldDefinitions.Add(new DataListFieldDefinition
|
||||
{
|
||||
TKey = "UserType",
|
||||
FieldKey = "widgetusertype",
|
||||
UiFieldDataType = (int)UiFieldDataType.Enum,
|
||||
EnumType = AyaNova.Util.StringUtil.TrimTypeName(typeof(UserType).ToString()),
|
||||
SqlValueColumnName = "awidget.usertype"
|
||||
});
|
||||
|
||||
FieldDefinitions.Add(new DataListFieldDefinition
|
||||
{
|
||||
TKey = "WidgetStartDate",
|
||||
FieldKey = "widgetstartdate",
|
||||
UiFieldDataType = (int)UiFieldDataType.DateTime,
|
||||
SqlValueColumnName = "awidget.startdate"
|
||||
});
|
||||
|
||||
FieldDefinitions.Add(new DataListFieldDefinition
|
||||
{
|
||||
TKey = "WidgetEndDate",
|
||||
FieldKey = "widgetenddate",
|
||||
UiFieldDataType = (int)UiFieldDataType.DateTime,
|
||||
SqlValueColumnName = "awidget.enddate"
|
||||
});
|
||||
|
||||
FieldDefinitions.Add(new DataListFieldDefinition
|
||||
{
|
||||
TKey = "WidgetNotes",
|
||||
FieldKey = "widgetnotes",
|
||||
UiFieldDataType = (int)UiFieldDataType.Text,
|
||||
SqlValueColumnName = "awidget.notes"
|
||||
});
|
||||
|
||||
FieldDefinitions.Add(new DataListFieldDefinition
|
||||
{
|
||||
FieldKey = "username",
|
||||
TKey = "User",
|
||||
UiFieldDataType = (int)UiFieldDataType.Text,
|
||||
AType = (int)AyaType.User,
|
||||
SqlIdColumnName = "auser.id",
|
||||
SqlValueColumnName = "auser.name"
|
||||
});
|
||||
|
||||
FieldDefinitions.Add(new DataListFieldDefinition
|
||||
{
|
||||
TKey = "Active",
|
||||
FieldKey = "widgetactive",
|
||||
UiFieldDataType = (int)UiFieldDataType.Bool,
|
||||
SqlValueColumnName = "awidget.active"
|
||||
});
|
||||
|
||||
FieldDefinitions.Add(new DataListFieldDefinition
|
||||
{
|
||||
TKey = "Tags",
|
||||
FieldKey = "widgettags",
|
||||
UiFieldDataType = (int)UiFieldDataType.Tags,
|
||||
SqlValueColumnName = "awidget.tags"
|
||||
});
|
||||
|
||||
FieldDefinitions.Add(new DataListFieldDefinition { TKey = "WidgetCustom1", FieldKey = "widgetcustom1", IsCustomField = true, IsFilterable = false, IsSortable = false, SqlValueColumnName = "awidget.customfields" });
|
||||
FieldDefinitions.Add(new DataListFieldDefinition { TKey = "WidgetCustom2", FieldKey = "widgetcustom2", IsCustomField = true, IsFilterable = false, IsSortable = false, SqlValueColumnName = "awidget.customfields" });
|
||||
FieldDefinitions.Add(new DataListFieldDefinition { TKey = "WidgetCustom3", FieldKey = "widgetcustom3", IsCustomField = true, IsFilterable = false, IsSortable = false, SqlValueColumnName = "awidget.customfields" });
|
||||
FieldDefinitions.Add(new DataListFieldDefinition { TKey = "WidgetCustom4", FieldKey = "widgetcustom4", IsCustomField = true, IsFilterable = false, IsSortable = false, SqlValueColumnName = "awidget.customfields" });
|
||||
FieldDefinitions.Add(new DataListFieldDefinition { TKey = "WidgetCustom5", FieldKey = "widgetcustom5", IsCustomField = true, IsFilterable = false, IsSortable = false, SqlValueColumnName = "awidget.customfields" });
|
||||
FieldDefinitions.Add(new DataListFieldDefinition { TKey = "WidgetCustom6", FieldKey = "widgetcustom6", IsCustomField = true, IsFilterable = false, IsSortable = false, SqlValueColumnName = "awidget.customfields" });
|
||||
FieldDefinitions.Add(new DataListFieldDefinition { TKey = "WidgetCustom7", FieldKey = "widgetcustom7", IsCustomField = true, IsFilterable = false, IsSortable = false, SqlValueColumnName = "awidget.customfields" });
|
||||
FieldDefinitions.Add(new DataListFieldDefinition { TKey = "WidgetCustom8", FieldKey = "widgetcustom8", IsCustomField = true, IsFilterable = false, IsSortable = false, SqlValueColumnName = "awidget.customfields" });
|
||||
FieldDefinitions.Add(new DataListFieldDefinition { TKey = "WidgetCustom9", FieldKey = "widgetcustom9", IsCustomField = true, IsFilterable = false, IsSortable = false, SqlValueColumnName = "awidget.customfields" });
|
||||
FieldDefinitions.Add(new DataListFieldDefinition { TKey = "WidgetCustom10", FieldKey = "widgetcustom10", IsCustomField = true, IsFilterable = false, IsSortable = false, SqlValueColumnName = "awidget.customfields" });
|
||||
FieldDefinitions.Add(new DataListFieldDefinition { TKey = "WidgetCustom11", FieldKey = "widgetcustom11", IsCustomField = true, IsFilterable = false, IsSortable = false, SqlValueColumnName = "awidget.customfields" });
|
||||
FieldDefinitions.Add(new DataListFieldDefinition { TKey = "WidgetCustom12", FieldKey = "widgetcustom12", IsCustomField = true, IsFilterable = false, IsSortable = false, SqlValueColumnName = "awidget.customfields" });
|
||||
FieldDefinitions.Add(new DataListFieldDefinition { TKey = "WidgetCustom13", FieldKey = "widgetcustom13", IsCustomField = true, IsFilterable = false, IsSortable = false, SqlValueColumnName = "awidget.customfields" });
|
||||
FieldDefinitions.Add(new DataListFieldDefinition { TKey = "WidgetCustom14", FieldKey = "widgetcustom14", IsCustomField = true, IsFilterable = false, IsSortable = false, SqlValueColumnName = "awidget.customfields" });
|
||||
FieldDefinitions.Add(new DataListFieldDefinition { TKey = "WidgetCustom15", FieldKey = "widgetcustom15", IsCustomField = true, IsFilterable = false, IsSortable = false, SqlValueColumnName = "awidget.customfields" });
|
||||
FieldDefinitions.Add(new DataListFieldDefinition { TKey = "WidgetCustom16", FieldKey = "widgetcustom16", IsCustomField = true, IsFilterable = false, IsSortable = false, SqlValueColumnName = "awidget.customfields" });
|
||||
}
|
||||
}//eoc
|
||||
}//eons
|
||||
@@ -9,14 +9,7 @@ namespace AyaNova.PickList
|
||||
|
||||
internal static class PickListSqlBuilder
|
||||
{
|
||||
/*Example
|
||||
select awidget.id as plId, awidget.active as plActive, awidget.name || ' ' || awidget.serial || ' ' || auser.name as plname, awidget.tags
|
||||
from awidget left join auser on (awidget.userid=auser.id)
|
||||
where array_to_string(awidget.tags,',') like '%zone-8%'
|
||||
and awidget.active = true
|
||||
and ((awidget.name like '%we%') or (cast (awidget.serial as text) like '%we%') or (auser.name like '%we%'))
|
||||
order by awidget.name,awidget.serial,auser.name limit 100
|
||||
*/
|
||||
|
||||
|
||||
//Maximum number of results to return at any given time
|
||||
//did a little research and may adjust this but it can be fairly girthy in this day and age
|
||||
@@ -149,7 +142,7 @@ namespace AyaNova.PickList
|
||||
lOrderBy.Add(valueColumnName);
|
||||
|
||||
//THIS is the best filter method for a like comparison to each individual tag:
|
||||
//(array_to_string(awidget.tags,',') like '%zo%')
|
||||
//(array_to_string(acustomer.tags,',') like '%zo%')
|
||||
//Note that a tag specific query takes precendence over this which exists
|
||||
//in cases where there are tags in the template and the user has not specified a tag specific query
|
||||
//so this will handle it as a like query against all tags as a composite string of text just like
|
||||
@@ -191,7 +184,7 @@ namespace AyaNova.PickList
|
||||
lOrderBy.Add(valueColumnName);
|
||||
|
||||
//Where fragment is different for non text fields: it needs to be cast to text to like query on it
|
||||
//(cast (awidget.serial as text) like '%some%')
|
||||
//(cast (aworkorder.serial as text) like '%some%')
|
||||
if (HasAutoCompleteQuery)
|
||||
if (ServerGlobalBizSettings.Cache.SearchCaseSensitiveOnly)
|
||||
sWhere = $"(cast ({valueColumnName} as text) like '%{autoCompleteQuery}%')";
|
||||
@@ -221,9 +214,9 @@ namespace AyaNova.PickList
|
||||
sb.Append(", ");
|
||||
|
||||
//nope, this will return null if any of the values are null, very bad for this use, instead
|
||||
//select name || ' ' || serial || ' ' || array_to_string(tags,',') as display from awidget
|
||||
//select name || ' ' || serial || ' ' || array_to_string(tags,',') as display from acustomer
|
||||
//this, on the other hand will work even if all of them are null
|
||||
//concat_ws(' ', awidget.name, awidget.serial, auser.name)
|
||||
//concat_ws(' ', acustomer.name, acustomer.serial, auser.name)
|
||||
|
||||
sb.Append("concat_ws(' ', ");
|
||||
foreach (string s in lSelect)
|
||||
@@ -315,8 +308,8 @@ namespace AyaNova.PickList
|
||||
return sb.ToString();
|
||||
|
||||
}
|
||||
//"select awidget.id as plId || ' 'awidget.active as plActive || ' 'awidget.name || ' 'awidget.serial || ' 'auser.name as plname from awidget left join auser on (awidget.userid=auser.id)
|
||||
//where awidget.active = true and ((awidget.name like '%on%') or (cast (awidget.serial as text) like '%on%') or (auser.name like '%on%')) order by awidget.name,awidget.serial,auser.name limit 100"
|
||||
//"select acustomer.id as plId || ' 'acustomer.active as plActive || ' 'acustomer.name || ' 'acustomer.serial || ' 'auser.name as plname from acustomer left join auser on (acustomer.userid=auser.id)
|
||||
//where acustomer.active = true and ((acustomer.name like '%on%') or (cast (acustomer.serial as text) like '%on%') or (auser.name like '%on%')) order by acustomer.name,acustomer.serial,auser.name limit 100"
|
||||
|
||||
|
||||
}//eoc
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using AyaNova.Biz;
|
||||
namespace AyaNova.PickList
|
||||
{
|
||||
internal class WidgetPickList : AyaPickList
|
||||
{
|
||||
public WidgetPickList()
|
||||
{
|
||||
DefaultListAType = AyaType.Widget;
|
||||
SQLFrom = "from awidget left join auser on (awidget.userid=auser.id)";
|
||||
AllowedRoles = BizRoles.GetRoleSet(DefaultListAType).Select;
|
||||
|
||||
//Default template
|
||||
dynamic dTemplate = new JArray();
|
||||
|
||||
dynamic cm = new JObject();
|
||||
cm.fld = "widgetname";
|
||||
dTemplate.Add(cm);
|
||||
|
||||
cm = new JObject();
|
||||
cm.fld = "widgetserial";
|
||||
dTemplate.Add(cm);
|
||||
|
||||
cm = new JObject();
|
||||
cm.fld = "username";
|
||||
dTemplate.Add(cm);
|
||||
|
||||
cm = new JObject();
|
||||
cm.fld = "widgettags";
|
||||
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 (in this case User) table need to be specified completely
|
||||
ColumnDefinitions = new List<AyaPickListFieldDefinition>();
|
||||
ColumnDefinitions.Add(new AyaPickListFieldDefinition
|
||||
{
|
||||
TKey = "Active",
|
||||
FieldKey = "widgetactive",
|
||||
ColumnDataType = UiFieldDataType.Bool,
|
||||
SqlValueColumnName = "awidget.active",
|
||||
IsActiveColumn = true
|
||||
});
|
||||
|
||||
ColumnDefinitions.Add(new AyaPickListFieldDefinition
|
||||
{
|
||||
TKey = "WidgetName",
|
||||
FieldKey = "widgetname",
|
||||
//AType = AyaType.Widget,
|
||||
ColumnDataType = UiFieldDataType.Text,
|
||||
SqlIdColumnName = "awidget.id",
|
||||
SqlValueColumnName = "awidget.name",
|
||||
IsRowId = true
|
||||
});
|
||||
|
||||
ColumnDefinitions.Add(new AyaPickListFieldDefinition
|
||||
{
|
||||
TKey = "WidgetSerial",
|
||||
FieldKey = "widgetserial",
|
||||
ColumnDataType = UiFieldDataType.Integer,
|
||||
SqlValueColumnName = "awidget.serial"
|
||||
});
|
||||
|
||||
ColumnDefinitions.Add(new AyaPickListFieldDefinition
|
||||
{
|
||||
FieldKey = "username",
|
||||
TKey = "User",
|
||||
ColumnDataType = UiFieldDataType.Text,
|
||||
SqlIdColumnName = "auser.id",
|
||||
SqlValueColumnName = "auser.name"
|
||||
});
|
||||
|
||||
ColumnDefinitions.Add(new AyaPickListFieldDefinition
|
||||
{
|
||||
TKey = "Tags",
|
||||
FieldKey = "widgettags",
|
||||
ColumnDataType = UiFieldDataType.Tags,
|
||||
SqlValueColumnName = "awidget.tags"
|
||||
});
|
||||
}
|
||||
}//eoc
|
||||
}//eons
|
||||
@@ -22,9 +22,8 @@ namespace AyaNova.Biz
|
||||
//because enumlist gets it that way, i.e. "Global" would be the expected key
|
||||
|
||||
NoType = 0,
|
||||
Global = 1,
|
||||
[CoreBizObject,ReportableBizObject]
|
||||
Widget = 2,
|
||||
Global = 1,
|
||||
UNUSED_2 = 2,
|
||||
[CoreBizObject,ReportableBizObject]
|
||||
User = 3,
|
||||
ServerState = 4,
|
||||
|
||||
@@ -31,9 +31,7 @@ namespace AyaNova.Biz
|
||||
case AyaType.FormCustom:
|
||||
return await ct.FormCustom.AnyAsync(z => z.Id == id);
|
||||
case AyaType.User:
|
||||
return await ct.User.AnyAsync(z => z.Id == id);
|
||||
case AyaType.Widget:
|
||||
return await ct.Widget.AnyAsync(z => z.Id == id);
|
||||
return await ct.User.AnyAsync(z => z.Id == id);
|
||||
case AyaType.Customer:
|
||||
return await ct.Customer.AnyAsync(z => z.Id == id);
|
||||
case AyaType.CustomerNote:
|
||||
|
||||
@@ -33,9 +33,7 @@ namespace AyaNova.Biz
|
||||
case AyaType.DataListSavedFilter:
|
||||
return new DataListSavedFilterBiz(ct, userId, translationId, roles);
|
||||
case AyaType.FormCustom:
|
||||
return new FormCustomBiz(ct, userId, translationId, roles);
|
||||
case AyaType.Widget:
|
||||
return new WidgetBiz(ct, userId, translationId, roles);
|
||||
return new FormCustomBiz(ct, userId, translationId, roles);
|
||||
case AyaType.FileAttachment:
|
||||
return new AttachmentBiz(ct, userId, roles);
|
||||
case AyaType.Customer:
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -60,40 +60,6 @@ namespace AyaNova.Biz
|
||||
/* ***************************** WARNING: Be careful here, if a standard field is hideable and also it's DB SCHEMA is set to NON NULLABLE then the CLIENT end needs to set a default
|
||||
***************************** Otherwise the hidden field can't be set and the object can't be saved EVER
|
||||
*/
|
||||
#region WIDGET_KEY
|
||||
{
|
||||
List<FormField> l = new List<FormField>();
|
||||
|
||||
l.Add(new FormField { TKey = "WidgetSerial", FieldKey = "Serial" });
|
||||
l.Add(new FormField { TKey = "WidgetCount", FieldKey = "Count" });
|
||||
l.Add(new FormField { TKey = "WidgetDollarAmount", FieldKey = "DollarAmount" });
|
||||
l.Add(new FormField { TKey = "WidgetStartDate", FieldKey = "StartDate" });
|
||||
l.Add(new FormField { TKey = "WidgetEndDate", FieldKey = "EndDate" });
|
||||
l.Add(new FormField { TKey = "User", FieldKey = "UserId" });
|
||||
l.Add(new FormField { TKey = "UserType", FieldKey = "UserType" });
|
||||
l.Add(new FormField { TKey = "WidgetNotes", FieldKey = "Notes" });
|
||||
l.Add(new FormField { TKey = "Tags", FieldKey = "Tags" });
|
||||
l.Add(new FormField { TKey = "Wiki", FieldKey = "Wiki" });
|
||||
l.Add(new FormField { TKey = "Attachments", FieldKey = "Attachments" });
|
||||
l.Add(new FormField { TKey = "WidgetCustom1", FieldKey = "WidgetCustom1", IsCustomField = true });
|
||||
l.Add(new FormField { TKey = "WidgetCustom2", FieldKey = "WidgetCustom2", IsCustomField = true });
|
||||
l.Add(new FormField { TKey = "WidgetCustom3", FieldKey = "WidgetCustom3", IsCustomField = true });
|
||||
l.Add(new FormField { TKey = "WidgetCustom4", FieldKey = "WidgetCustom4", IsCustomField = true });
|
||||
l.Add(new FormField { TKey = "WidgetCustom5", FieldKey = "WidgetCustom5", IsCustomField = true });
|
||||
l.Add(new FormField { TKey = "WidgetCustom6", FieldKey = "WidgetCustom6", IsCustomField = true });
|
||||
l.Add(new FormField { TKey = "WidgetCustom7", FieldKey = "WidgetCustom7", IsCustomField = true });
|
||||
l.Add(new FormField { TKey = "WidgetCustom8", FieldKey = "WidgetCustom8", IsCustomField = true });
|
||||
l.Add(new FormField { TKey = "WidgetCustom9", FieldKey = "WidgetCustom9", IsCustomField = true });
|
||||
l.Add(new FormField { TKey = "WidgetCustom10", FieldKey = "WidgetCustom10", IsCustomField = true });
|
||||
l.Add(new FormField { TKey = "WidgetCustom11", FieldKey = "WidgetCustom11", IsCustomField = true });
|
||||
l.Add(new FormField { TKey = "WidgetCustom12", FieldKey = "WidgetCustom12", IsCustomField = true });
|
||||
l.Add(new FormField { TKey = "WidgetCustom13", FieldKey = "WidgetCustom13", IsCustomField = true });
|
||||
l.Add(new FormField { TKey = "WidgetCustom14", FieldKey = "WidgetCustom14", IsCustomField = true });
|
||||
l.Add(new FormField { TKey = "WidgetCustom15", FieldKey = "WidgetCustom15", IsCustomField = true });
|
||||
l.Add(new FormField { TKey = "WidgetCustom16", FieldKey = "WidgetCustom16", IsCustomField = true });
|
||||
_formFields.Add(AyaType.Widget.ToString(), l);
|
||||
}
|
||||
#endregion widget
|
||||
|
||||
#region USER_KEY
|
||||
{
|
||||
|
||||
@@ -931,7 +931,7 @@ namespace AyaNova.Biz
|
||||
if (jobData.ContainsKey("idList"))
|
||||
idList = ((JArray)jobData["idList"]).ToObject<List<long>>();
|
||||
else
|
||||
idList = await ct.Widget.Select(z => z.Id).ToListAsync();
|
||||
idList = await ct.PM.Select(z => z.Id).ToListAsync();
|
||||
bool SaveIt = false;
|
||||
foreach (long id in idList)
|
||||
{
|
||||
|
||||
@@ -912,7 +912,7 @@ namespace AyaNova.Biz
|
||||
if (jobData.ContainsKey("idList"))
|
||||
idList = ((JArray)jobData["idList"]).ToObject<List<long>>();
|
||||
else
|
||||
idList = await ct.Widget.Select(z => z.Id).ToListAsync();
|
||||
idList = await ct.Quote.Select(z => z.Id).ToListAsync();
|
||||
bool SaveIt = false;
|
||||
foreach (long id in idList)
|
||||
{
|
||||
|
||||
@@ -1,552 +0,0 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Linq;
|
||||
using EnumsNET;
|
||||
using AyaNova.Util;
|
||||
using AyaNova.Api.ControllerHelpers;
|
||||
using AyaNova.Models;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace AyaNova.Biz
|
||||
{
|
||||
internal class WidgetBiz : BizObject, IJobObject, ISearchAbleObject, IReportAbleObject, IExportAbleObject, IImportAbleObject, INotifiableObject
|
||||
{
|
||||
|
||||
|
||||
internal WidgetBiz(AyContext dbcontext, long currentUserId, long userTranslationId, AuthorizationRoles UserRoles)
|
||||
{
|
||||
ct = dbcontext;
|
||||
UserId = currentUserId;
|
||||
UserTranslationId = userTranslationId;
|
||||
CurrentUserRoles = UserRoles;
|
||||
BizType = AyaType.Widget;
|
||||
}
|
||||
|
||||
internal static WidgetBiz GetBiz(AyContext ct, Microsoft.AspNetCore.Http.HttpContext httpContext = null)
|
||||
{
|
||||
if (httpContext != null)
|
||||
return new WidgetBiz(ct, UserIdFromContext.Id(httpContext.Items), UserTranslationIdFromContext.Id(httpContext.Items), UserRolesFromContext.Roles(httpContext.Items));
|
||||
else
|
||||
return new WidgetBiz(ct, 1, ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION_ID, AuthorizationRoles.BizAdmin);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//EXISTS
|
||||
internal async Task<bool> ExistsAsync(long id)
|
||||
{
|
||||
return await ct.Widget.AnyAsync(z => z.Id == id);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//CREATE
|
||||
//
|
||||
internal async Task<Widget> CreateAsync(Widget newObject)
|
||||
{
|
||||
await ValidateAsync(newObject);
|
||||
if (HasErrors)
|
||||
return null;
|
||||
else
|
||||
{
|
||||
newObject.Tags = TagBiz.NormalizeTags(newObject.Tags);
|
||||
newObject.CustomFields = JsonUtil.CompactJson(newObject.CustomFields);
|
||||
await ct.Widget.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<Widget> DuplicateAsync(long id)
|
||||
// {
|
||||
// var dbObject = await GetAsync(id, false);
|
||||
// if (dbObject == null)
|
||||
// {
|
||||
// AddError(ApiErrorCode.NOT_FOUND, "id");
|
||||
// return null;
|
||||
// }
|
||||
// var newObject = new Widget();
|
||||
// CopyObject.Copy(dbObject, newObject, "Wiki,Serial");
|
||||
// string newUniqueName = string.Empty;
|
||||
// bool NotUnique = true;
|
||||
// long l = 1;
|
||||
// do
|
||||
// {
|
||||
// newUniqueName = Util.StringUtil.UniqueNameBuilder(dbObject.Name, l++, 255);
|
||||
// NotUnique = await ct.Widget.AnyAsync(z => z.Name == newUniqueName);
|
||||
// } while (NotUnique);
|
||||
// newObject.Name = newUniqueName;
|
||||
// newObject.Id = 0;
|
||||
// newObject.Concurrency = 0;
|
||||
// await ct.Widget.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<Widget> GetAsync(long id, bool logTheGetEvent = true)
|
||||
{
|
||||
var ret = await ct.Widget.AsNoTracking().SingleOrDefaultAsync(z => z.Id == id);
|
||||
if (logTheGetEvent && ret != null)
|
||||
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, id, BizType, AyaEvent.Retrieved), ct);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
OLD PUT CODE
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//UPDATE
|
||||
//
|
||||
internal async Task<Widget> PutAsync(Widget putObject)
|
||||
{
|
||||
Widget dbObject = await ct.Widget.SingleOrDefaultAsync(z => z.Id == putObject.Id);
|
||||
if (dbObject == null)
|
||||
{
|
||||
AddError(ApiErrorCode.NOT_FOUND, "id");
|
||||
return null;
|
||||
}
|
||||
Widget SnapshotOfOriginalDBObj = new Widget();
|
||||
CopyObject.Copy(dbObject, SnapshotOfOriginalDBObj);
|
||||
CopyObject.Copy(putObject, dbObject, "Id");//can update serial
|
||||
dbObject.Tags = TagBiz.NormalizeTags(dbObject.Tags);
|
||||
dbObject.CustomFields = JsonUtil.CompactJson(dbObject.CustomFields);
|
||||
ct.Entry(dbObject).OriginalValues["Concurrency"] = putObject.Concurrency;
|
||||
await ValidateAsync(dbObject);
|
||||
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 NotifyEventProcessor.HandlePotentialNotificationEvent(AyaEvent.Modified, dbObject, SnapshotOfOriginalDBObj);
|
||||
return dbObject;
|
||||
}
|
||||
*/
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//UPDATE
|
||||
//
|
||||
internal async Task<Widget> PutAsync(Widget putObject)
|
||||
{
|
||||
var dbObject = await GetAsync(putObject.Id, false);
|
||||
if (dbObject == null)
|
||||
{
|
||||
AddError(ApiErrorCode.NOT_FOUND, "id");
|
||||
return null;
|
||||
}
|
||||
if (dbObject.Concurrency != putObject.Concurrency)
|
||||
{
|
||||
AddError(ApiErrorCode.CONCURRENCY_CONFLICT);
|
||||
return null;
|
||||
}
|
||||
|
||||
putObject.Tags = TagBiz.NormalizeTags(putObject.Tags);
|
||||
putObject.CustomFields = JsonUtil.CompactJson(putObject.CustomFields);
|
||||
await ValidateAsync(putObject);
|
||||
if (HasErrors) return null;
|
||||
ct.Replace(dbObject, putObject);
|
||||
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(putObject, false);
|
||||
await TagBiz.ProcessUpdateTagsInRepositoryAsync(ct, putObject.Tags, dbObject.Tags);
|
||||
await HandlePotentialNotificationEvent(AyaEvent.Modified, putObject, dbObject);
|
||||
return putObject;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//DELETE
|
||||
//
|
||||
internal async Task<bool> DeleteAsync(long id)
|
||||
{
|
||||
using (var transaction = await ct.Database.BeginTransactionAsync())
|
||||
{
|
||||
var dbObject = await GetAsync(id, false);
|
||||
if (dbObject == null)
|
||||
{
|
||||
AddError(ApiErrorCode.NOT_FOUND);
|
||||
return false;
|
||||
}
|
||||
ValidateCanDelete(dbObject);
|
||||
if (HasErrors)
|
||||
return false;
|
||||
if (HasErrors)
|
||||
return false;
|
||||
ct.Widget.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);
|
||||
//all good do the commit
|
||||
await transaction.CommitAsync();
|
||||
await HandlePotentialNotificationEvent(AyaEvent.Deleted, dbObject);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//RESTART SERIAL
|
||||
//
|
||||
internal async Task<bool> RestartSerial(long newSerial)
|
||||
{
|
||||
using (var command = ct.Database.GetDbConnection().CreateCommand())
|
||||
{
|
||||
command.CommandText = $"alter table awidget alter column serial restart with {newSerial}";
|
||||
await ct.Database.OpenConnectionAsync();
|
||||
await command.ExecuteNonQueryAsync();
|
||||
await ct.Database.CloseConnectionAsync();
|
||||
}
|
||||
await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserId, 0, BizType, AyaEvent.ResetSerial, newSerial.ToString()), ct);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//SEARCH
|
||||
//
|
||||
private async Task SearchIndexAsync(Widget 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, AyaType specificType)
|
||||
{
|
||||
var obj = await GetAsync(id, false);
|
||||
var SearchParams = new Search.SearchIndexProcessObjectParameters();
|
||||
DigestSearchText(obj, SearchParams);
|
||||
return SearchParams;
|
||||
}
|
||||
|
||||
public void DigestSearchText(Widget obj, Search.SearchIndexProcessObjectParameters searchParams)
|
||||
{
|
||||
if (obj != null)
|
||||
searchParams.AddText(obj.Notes)
|
||||
.AddText(obj.Name)
|
||||
.AddText(obj.Wiki)
|
||||
.AddText(obj.Tags)
|
||||
.AddText(obj.Serial)
|
||||
.AddText(obj.DollarAmount)
|
||||
.AddText(obj.Count)
|
||||
.AddCustomFields(obj.CustomFields);
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//VALIDATION
|
||||
//
|
||||
private async Task ValidateAsync(Widget proposedObj)
|
||||
{
|
||||
//skip validation if seeding
|
||||
if(ServerBootConfig.SEEDING) return;
|
||||
|
||||
//NOTE: In DB schema only name and serial are not nullable
|
||||
|
||||
//run validation and biz rules
|
||||
|
||||
//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.Widget.AnyAsync(z => z.Name == proposedObj.Name && z.Id != proposedObj.Id))
|
||||
{
|
||||
AddError(ApiErrorCode.VALIDATION_NOT_UNIQUE, "Name");
|
||||
}
|
||||
}
|
||||
|
||||
//Start date AND end date must both be null or both contain values
|
||||
if (proposedObj.StartDate == null && proposedObj.EndDate != null)
|
||||
AddError(ApiErrorCode.VALIDATION_REQUIRED, "StartDate");
|
||||
|
||||
if (proposedObj.StartDate != null && proposedObj.EndDate == null)
|
||||
AddError(ApiErrorCode.VALIDATION_REQUIRED, "EndDate");
|
||||
|
||||
//Start date before end date
|
||||
if (proposedObj.StartDate != null && proposedObj.EndDate != null)
|
||||
if (proposedObj.StartDate > proposedObj.EndDate)
|
||||
AddError(ApiErrorCode.VALIDATION_STARTDATE_AFTER_ENDDATE, "StartDate");
|
||||
|
||||
//Enum is valid value
|
||||
if (!proposedObj.UserType.IsValid())
|
||||
{
|
||||
AddError(ApiErrorCode.VALIDATION_INVALID_VALUE, "UserType");
|
||||
}
|
||||
|
||||
//Any form customizations to validate?
|
||||
var FormCustomization = await ct.FormCustom.AsNoTracking().SingleOrDefaultAsync(z => z.FormKey == AyaType.Widget.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(Widget inObj)
|
||||
{
|
||||
//whatever needs to be check to delete this object
|
||||
}
|
||||
|
||||
//Fulfil report request for data
|
||||
public async Task<JArray> GetReportData(DataListSelectedRequest dataListSelectedRequest)
|
||||
{
|
||||
//NOTE: Report widget is a superset of biz object widget
|
||||
//Biz objects will add and needed linked records here as extra fields with the data included
|
||||
//for example instead of a userid only there will be username added to the record
|
||||
//so the report designer can just select it as a field, no need to query seperately for it etc
|
||||
//REMEMBER: there is a name display format system and it should honour that so that the report
|
||||
//displays a user the same as it would display in the UI in an input form, no surprises
|
||||
|
||||
var idList = dataListSelectedRequest.SelectedRowIds;
|
||||
JArray ReportData = new JArray();
|
||||
while (idList.Any())
|
||||
{
|
||||
var batch = idList.Take(IReportAbleObject.REPORT_DATA_BATCH_SIZE);
|
||||
idList = idList.Skip(IReportAbleObject.REPORT_DATA_BATCH_SIZE).ToArray();
|
||||
//query for this batch, comes back in db natural order unfortunately
|
||||
var batchResults = await ct.Widget.AsNoTracking().Where(z => batch.Contains(z.Id)).ToArrayAsync();
|
||||
//order the results back into original
|
||||
var orderedList = from id in batch join z in batchResults on id equals z.Id select z;
|
||||
|
||||
//cache frequent viz data
|
||||
//usertypes
|
||||
var UserTypesEnumList = await AyaNova.Api.Controllers.EnumListController.GetEnumList(
|
||||
StringUtil.TrimTypeName(typeof(UserType).ToString()),
|
||||
UserTranslationId,
|
||||
CurrentUserRoles);
|
||||
|
||||
foreach (Widget w in orderedList)
|
||||
{
|
||||
await PopulateVizFields(w, UserTypesEnumList);
|
||||
var jo = JObject.FromObject(w);
|
||||
if (!JsonUtil.JTokenIsNullOrEmpty(jo["CustomFields"]))
|
||||
jo["CustomFields"] = JObject.Parse((string)jo["CustomFields"]);
|
||||
ReportData.Add(jo);
|
||||
}
|
||||
}
|
||||
return ReportData;
|
||||
}
|
||||
|
||||
//populate viz fields from provided object
|
||||
private async Task PopulateVizFields(Widget o, List<NameIdItem> userTypesEnumList)
|
||||
{
|
||||
if (o.UserId != null)
|
||||
o.UserViz = await ct.User.AsNoTracking().Where(x => x.Id == o.UserId).Select(x => x.Name).FirstOrDefaultAsync();
|
||||
o.UserTypeViz = userTypesEnumList.Where(x => x.Id == (long)o.UserType).Select(x => x.Name).First();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// IMPORT EXPORT
|
||||
//
|
||||
|
||||
|
||||
public async Task<JArray> GetExportData(DataListSelectedRequest dataListSelectedRequest)
|
||||
{
|
||||
//for now just re-use the report data code
|
||||
//this may turn out to be the pattern for most biz object types but keeping it seperate allows for custom usage from time to time
|
||||
return await GetReportData(dataListSelectedRequest);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public async Task<List<string>> ImportData(JArray ja)
|
||||
{
|
||||
List<string> ImportResult = new List<string>();
|
||||
string ImportTag = $"imported-{FileUtil.GetSafeDateFileName()}";
|
||||
|
||||
var jsset = JsonSerializer.CreateDefault(new JsonSerializerSettings { ContractResolver = new AyaNova.Util.JsonUtil.ShouldSerializeContractResolver(new string[] { "Concurrency", "Id", "CustomFields" }) });
|
||||
foreach (JObject j in ja)
|
||||
{
|
||||
var w = j.ToObject<Widget>(jsset);
|
||||
if (j["CustomFields"] != null)
|
||||
w.CustomFields = j["CustomFields"].ToString();
|
||||
w.Tags.Add(ImportTag);//so user can find them all and revert later if necessary
|
||||
var res = await CreateAsync(w);
|
||||
if (res == null)
|
||||
{
|
||||
ImportResult.Add($"* {w.Name} - {this.GetErrorsAsString()}");
|
||||
this.ClearErrors();
|
||||
}
|
||||
else
|
||||
{
|
||||
ImportResult.Add($"{w.Name} - ok");
|
||||
}
|
||||
}
|
||||
return ImportResult;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//JOB / OPERATIONS
|
||||
//
|
||||
public async Task HandleJobAsync(OpsJob job)
|
||||
{
|
||||
//Hand off the particular job to the corresponding processing code
|
||||
//NOTE: If this code throws an exception the caller (JobsBiz::ProcessJobsAsync) will automatically set the job to failed and log the exeption so
|
||||
//basically any error condition during job processing should throw up an exception if it can't be handled
|
||||
switch (job.JobType)
|
||||
{
|
||||
case JobType.BatchCoreObjectOperation:
|
||||
await ProcessBatchJobAsync(job);
|
||||
break;
|
||||
default:
|
||||
throw new System.ArgumentOutOfRangeException($"WidgetBiz.HandleJob-> Invalid job type{job.JobType.ToString()}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private async Task ProcessBatchJobAsync(OpsJob job)
|
||||
{
|
||||
await JobsBiz.UpdateJobStatusAsync(job.GId, JobStatus.Running);
|
||||
await JobsBiz.LogJobAsync(job.GId, $"LT:StartJob {job.SubType}");
|
||||
List<long> idList = new List<long>();
|
||||
long FailedObjectCount = 0;
|
||||
JObject jobData = JObject.Parse(job.JobInfo);
|
||||
if (jobData.ContainsKey("idList"))
|
||||
idList = ((JArray)jobData["idList"]).ToObject<List<long>>();
|
||||
else
|
||||
idList = await ct.Widget.AsNoTracking().Select(z => z.Id).ToListAsync();
|
||||
bool SaveIt = false;
|
||||
foreach (long id in idList)
|
||||
{
|
||||
try
|
||||
{
|
||||
SaveIt = false;
|
||||
ClearErrors();
|
||||
Widget o = null;
|
||||
//save a fetch if it's a delete
|
||||
if (job.SubType != JobSubType.Delete)
|
||||
o = await GetAsync(id, false);
|
||||
switch (job.SubType)
|
||||
{
|
||||
case JobSubType.TagAddAny:
|
||||
case JobSubType.TagAdd:
|
||||
case JobSubType.TagRemoveAny:
|
||||
case JobSubType.TagRemove:
|
||||
case JobSubType.TagReplaceAny:
|
||||
case JobSubType.TagReplace:
|
||||
SaveIt = TagBiz.ProcessBatchTagOperation(o.Tags, (string)jobData["tag"], jobData.ContainsKey("toTag") ? (string)jobData["toTag"] : null, job.SubType);
|
||||
break;
|
||||
case JobSubType.Delete:
|
||||
if (!await DeleteAsync(id))
|
||||
{
|
||||
await JobsBiz.LogJobAsync(job.GId, $"LT:Errors {GetErrorsAsString()} id {id}");
|
||||
FailedObjectCount++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new System.ArgumentOutOfRangeException($"ProcessBatchJobAsync -> Invalid job Subtype{job.SubType}");
|
||||
}
|
||||
if (SaveIt)
|
||||
{
|
||||
o = await PutAsync(o);
|
||||
if (o == null)
|
||||
{
|
||||
await JobsBiz.LogJobAsync(job.GId, $"LT:Errors {GetErrorsAsString()} id {id}");
|
||||
FailedObjectCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await JobsBiz.LogJobAsync(job.GId, $"LT:Errors id({id})");
|
||||
await JobsBiz.LogJobAsync(job.GId, ExceptionUtil.ExtractAllExceptionMessages(ex));
|
||||
}
|
||||
}
|
||||
await JobsBiz.LogJobAsync(job.GId, $"LT:BatchJob {job.SubType} {idList.Count}{(FailedObjectCount > 0 ? " - LT:Failed " + FailedObjectCount : "")}");
|
||||
await JobsBiz.UpdateJobStatusAsync(job.GId, JobStatus.Completed);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// NOTIFICATION PROCESSING
|
||||
//
|
||||
public async Task HandlePotentialNotificationEvent(AyaEvent ayaEvent, ICoreBizObjectModel proposedObj, ICoreBizObjectModel currentObj = null)
|
||||
{
|
||||
ILogger log = AyaNova.Util.ApplicationLogging.CreateLogger<WidgetBiz>();
|
||||
if(ServerBootConfig.SEEDING || ServerBootConfig.MIGRATING) 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
|
||||
|
||||
@@ -1029,7 +1029,7 @@ namespace AyaNova.Biz
|
||||
if (jobData.ContainsKey("idList"))
|
||||
idList = ((JArray)jobData["idList"]).ToObject<List<long>>();
|
||||
else
|
||||
idList = await ct.Widget.Select(z => z.Id).ToListAsync();
|
||||
idList = await ct.WorkOrder.Select(z => z.Id).ToListAsync();
|
||||
bool SaveIt = false;
|
||||
foreach (long id in idList)
|
||||
{
|
||||
|
||||
@@ -10,7 +10,6 @@ namespace AyaNova.Models
|
||||
public virtual DbSet<MetricDD> MetricDD { get; set; }
|
||||
public virtual DbSet<User> User { get; set; }
|
||||
public virtual DbSet<UserOptions> UserOptions { get; set; }
|
||||
public virtual DbSet<Widget> Widget { get; set; }
|
||||
public virtual DbSet<GlobalBizSettings> GlobalBizSettings { get; set; }
|
||||
public virtual DbSet<GlobalOpsBackupSettings> GlobalOpsBackupSettings { get; set; }
|
||||
public virtual DbSet<GlobalOpsNotificationSettings> GlobalOpsNotificationSettings { get; set; }
|
||||
@@ -186,7 +185,6 @@ namespace AyaNova.Models
|
||||
//SERIALIZED OBJECTS
|
||||
//
|
||||
modelBuilder.Entity<PurchaseOrder>().Property(z => z.Serial).UseIdentityByDefaultColumn();
|
||||
modelBuilder.Entity<Widget>().Property(z => z.Serial).UseIdentityByDefaultColumn();
|
||||
modelBuilder.Entity<WorkOrder>().Property(z => z.Serial).UseIdentityByDefaultColumn();
|
||||
modelBuilder.Entity<Quote>().Property(z => z.Serial).UseIdentityByDefaultColumn();
|
||||
modelBuilder.Entity<PM>().Property(z => z.Serial).UseIdentityByDefaultColumn();
|
||||
|
||||
@@ -116,8 +116,7 @@ namespace AyaNova.Models
|
||||
[JsonIgnore]
|
||||
public Vendor Vendor { get; set; }
|
||||
|
||||
[JsonIgnore]//hide from being returned (as null anyway) with User object in routes
|
||||
public Widget Widget { get; set; }
|
||||
|
||||
|
||||
public User()
|
||||
{
|
||||
|
||||
@@ -1,52 +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
|
||||
//NOTE: In Widget DB schema only name and serial are not nullable
|
||||
public class Widget : ICoreBizObjectModel
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public uint Concurrency { get; set; }
|
||||
|
||||
[Required]
|
||||
public string Name { get; set; }
|
||||
public long Serial { get; set; }
|
||||
public decimal? DollarAmount { get; set; }
|
||||
public bool? Active { get; set; }
|
||||
public UserType UserType { get; set; }
|
||||
[NotMapped]
|
||||
public string UserTypeViz { get; set; }
|
||||
public DateTime? StartDate { get; set; }
|
||||
public DateTime? EndDate { get; set; }
|
||||
public string Notes { get; set; }
|
||||
public int? Count { get; set; }
|
||||
public string Wiki { get; set; }
|
||||
public string CustomFields { get; set; }
|
||||
public List<string> Tags { get; set; }
|
||||
//relations
|
||||
//https://docs.microsoft.com/en-us/ef/core/modeling/relationships#other-relationship-patterns
|
||||
[JsonIgnore]//hide from being returned (as null anyway) with User object in routes
|
||||
public User User { get; set; }
|
||||
|
||||
public long? UserId { get; set; }
|
||||
[NotMapped]
|
||||
public string UserViz { get; set; }
|
||||
|
||||
public Widget()
|
||||
{
|
||||
Tags = new List<string>();
|
||||
}
|
||||
|
||||
[NotMapped, JsonIgnore]
|
||||
public AyaType AyaType { get => AyaType.Widget; }
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1663,31 +1663,6 @@
|
||||
"SupportedUntil": "Support- und Aktualisierungsdatum",
|
||||
"LicensedOptions": "Lizenzoptionen",
|
||||
"Log": "Protokoll",
|
||||
"Widget": "Widget",
|
||||
"WidgetList": "Widgets",
|
||||
"WidgetName": "Name",
|
||||
"WidgetSerial": "Seriennummer",
|
||||
"WidgetDollarAmount": "Betrag",
|
||||
"WidgetCount": "Anzahl",
|
||||
"WidgetStartDate": "Startdatum",
|
||||
"WidgetEndDate": "Enddatum",
|
||||
"WidgetNotes": "Notizen",
|
||||
"WidgetCustom1": "Angepasstes Feld 1",
|
||||
"WidgetCustom2": "Angepasstes Feld 2",
|
||||
"WidgetCustom3": "Angepasstes Feld 3",
|
||||
"WidgetCustom4": "Angepasstes Feld 4",
|
||||
"WidgetCustom5": "Angepasstes Feld 5",
|
||||
"WidgetCustom6": "Angepasstes Feld 6",
|
||||
"WidgetCustom7": "Angepasstes Feld 7",
|
||||
"WidgetCustom8": "Angepasstes Feld 8",
|
||||
"WidgetCustom9": "Angepasstes Feld 9",
|
||||
"WidgetCustom10": "Angepasstes Feld 10",
|
||||
"WidgetCustom11": "Angepasstes Feld 11",
|
||||
"WidgetCustom12": "Angepasstes Feld 12",
|
||||
"WidgetCustom13": "Angepasstes Feld 13",
|
||||
"WidgetCustom14": "Angepasstes Feld 14",
|
||||
"WidgetCustom15": "Angepasstes Feld 15",
|
||||
"WidgetCustom16": "Angepasstes Feld 16",
|
||||
"RowsPerPage": "Zeilen pro Seite",
|
||||
"PageOfPageText": "{0}-{1} von {2}",
|
||||
"Loading": "Wird geladen...",
|
||||
|
||||
@@ -1663,31 +1663,6 @@
|
||||
"SupportedUntil": "Support and updates expiration date",
|
||||
"LicensedOptions": "Licensed options",
|
||||
"Log": "Log",
|
||||
"Widget": "Widget",
|
||||
"WidgetList": "Widgets",
|
||||
"WidgetName": "Name",
|
||||
"WidgetSerial": "Serial #",
|
||||
"WidgetDollarAmount": "Price",
|
||||
"WidgetCount": "Count",
|
||||
"WidgetStartDate": "Start",
|
||||
"WidgetEndDate": "End",
|
||||
"WidgetNotes": "Notes",
|
||||
"WidgetCustom1": "Custom1",
|
||||
"WidgetCustom2": "Custom2",
|
||||
"WidgetCustom3": "Custom3",
|
||||
"WidgetCustom4": "Custom4",
|
||||
"WidgetCustom5": "Custom5",
|
||||
"WidgetCustom6": "Custom6",
|
||||
"WidgetCustom7": "Custom7",
|
||||
"WidgetCustom8": "Custom8",
|
||||
"WidgetCustom9": "Custom9",
|
||||
"WidgetCustom10": "Custom10",
|
||||
"WidgetCustom11": "Custom11",
|
||||
"WidgetCustom12": "Custom12",
|
||||
"WidgetCustom13": "Custom13",
|
||||
"WidgetCustom14": "Custom14",
|
||||
"WidgetCustom15": "Custom15",
|
||||
"WidgetCustom16": "Custom16",
|
||||
"RowsPerPage": "Rows per page",
|
||||
"PageOfPageText": "{0}-{1} of {2}",
|
||||
"Loading": "Loading...",
|
||||
|
||||
@@ -1663,31 +1663,6 @@
|
||||
"SupportedUntil": "Soporte y actualizaciones fecha de caducidad",
|
||||
"LicensedOptions": "Opciones de licencia",
|
||||
"Log": "Registro",
|
||||
"Widget": "Widget",
|
||||
"WidgetList": "Widgets",
|
||||
"WidgetName": "Nombre",
|
||||
"WidgetSerial": "Número de serie",
|
||||
"WidgetDollarAmount": "Importe",
|
||||
"WidgetCount": "Recuento",
|
||||
"WidgetStartDate": "Fecha de comienzo",
|
||||
"WidgetEndDate": "Fecha de fin",
|
||||
"WidgetNotes": "Notas",
|
||||
"WidgetCustom1": "Campo personalizado 1",
|
||||
"WidgetCustom2": "Campo personalizado 2",
|
||||
"WidgetCustom3": "Campo personalizado 3",
|
||||
"WidgetCustom4": "Campo personalizado 4",
|
||||
"WidgetCustom5": "Campo personalizado 5",
|
||||
"WidgetCustom6": "Campo personalizado 6",
|
||||
"WidgetCustom7": "Campo personalizado 7",
|
||||
"WidgetCustom8": "Campo personalizado 8",
|
||||
"WidgetCustom9": "Campo personalizado 9",
|
||||
"WidgetCustom10": "Campo personalizado 10",
|
||||
"WidgetCustom11": "Campo personalizado 11",
|
||||
"WidgetCustom12": "Campo personalizado 12",
|
||||
"WidgetCustom13": "Campo personalizado 13",
|
||||
"WidgetCustom14": "Campo personalizado 14",
|
||||
"WidgetCustom15": "Campo personalizado 15",
|
||||
"WidgetCustom16": "Campo personalizado 16",
|
||||
"RowsPerPage": "Filas por página",
|
||||
"PageOfPageText": "{0}-{1} de {2}",
|
||||
"Loading": "Cargando...",
|
||||
|
||||
@@ -1663,31 +1663,6 @@
|
||||
"SupportedUntil": "Support et mises à jour date d'expiration",
|
||||
"LicensedOptions": "Options de licence",
|
||||
"Log": "Enregistrement",
|
||||
"Widget": "Widget",
|
||||
"WidgetList": "Widgets",
|
||||
"WidgetName": "Nom",
|
||||
"WidgetSerial": "Numéro de série",
|
||||
"WidgetDollarAmount": "Montant",
|
||||
"WidgetCount": "Nombre",
|
||||
"WidgetStartDate": "Date de début",
|
||||
"WidgetEndDate": "Date de fin",
|
||||
"WidgetNotes": "Remarques",
|
||||
"WidgetCustom1": "Champ personnalisé 1",
|
||||
"WidgetCustom2": "Champ personnalisé 2",
|
||||
"WidgetCustom3": "Champ personnalisé 3",
|
||||
"WidgetCustom4": "Champ personnalisé 4",
|
||||
"WidgetCustom5": "Champ personnalisé 5",
|
||||
"WidgetCustom6": "Champ personnalisé 6",
|
||||
"WidgetCustom7": "Champ personnalisé 7",
|
||||
"WidgetCustom8": "Champ personnalisé 8",
|
||||
"WidgetCustom9": "Champ personnalisé 9",
|
||||
"WidgetCustom10": "Champ personnalisé 10",
|
||||
"WidgetCustom11": "Champ personnalisé 11",
|
||||
"WidgetCustom12": "Champ personnalisé 12",
|
||||
"WidgetCustom13": "Champ personnalisé 13",
|
||||
"WidgetCustom14": "Champ personnalisé 14",
|
||||
"WidgetCustom15": "Champ personnalisé 15",
|
||||
"WidgetCustom16": "Champ personnalisé 16",
|
||||
"RowsPerPage": "Lignes par page",
|
||||
"PageOfPageText": "{0}-{1} sur {2}",
|
||||
"Loading": "Chargement...",
|
||||
|
||||
@@ -22,16 +22,16 @@ namespace AyaNova.Util
|
||||
//!!!!WARNING: BE SURE TO UPDATE THE DbUtil::EmptyBizDataFromDatabaseForSeedingOrImportingAsync WHEN NEW TABLES ADDED!!!!
|
||||
private const int DESIRED_SCHEMA_LEVEL = 1;
|
||||
|
||||
internal const long EXPECTED_COLUMN_COUNT = 1276;
|
||||
internal const long EXPECTED_INDEX_COUNT = 146;
|
||||
internal const long EXPECTED_CHECK_CONSTRAINTS = 517;
|
||||
internal const long EXPECTED_COLUMN_COUNT = 1262;
|
||||
internal const long EXPECTED_INDEX_COUNT = 144;
|
||||
internal const long EXPECTED_CHECK_CONSTRAINTS = 513;
|
||||
internal const long EXPECTED_FOREIGN_KEY_CONSTRAINTS = 192;
|
||||
internal const long EXPECTED_VIEWS = 9;
|
||||
internal const long EXPECTED_ROUTINES = 2;
|
||||
|
||||
//!!!!WARNING: BE SURE TO UPDATE THE DbUtil::EmptyBizDataFromDatabaseForSeedingOrImportingAsync WHEN NEW TABLES ADDED!!!!
|
||||
|
||||
///////////////////////////////////////////////////////////////// C1276:I146:CC517:FC192:V9:R2
|
||||
///////////////////////////////////////////////////////////////// C1262:I144:CC513:FC192:V9:R2
|
||||
|
||||
|
||||
|
||||
@@ -369,7 +369,7 @@ BEGIN
|
||||
case ayatype
|
||||
when 0 then return 'LT:NoType';
|
||||
when 1 then return 'LT:Global';
|
||||
when 2 then aytable = 'awidget';
|
||||
when 2 then return 'LT:UNUSED';
|
||||
when 3 then aytable = 'auser';
|
||||
when 4 then return 'LT:ServerState';
|
||||
when 5 then return 'LT:License';
|
||||
@@ -494,15 +494,9 @@ $BODY$ LANGUAGE PLPGSQL STABLE");
|
||||
//Add user table
|
||||
await ExecQueryAsync("CREATE TABLE alicense (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, dbid TEXT, key TEXT NOT NULL)");
|
||||
|
||||
//Add widget table
|
||||
//id, TEXT, longtext, boolean, currency,
|
||||
await ExecQueryAsync("CREATE TABLE awidget (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, name TEXT NOT NULL UNIQUE, serial BIGINT GENERATED BY DEFAULT AS IDENTITY NOT NULL,"
|
||||
+ "startdate TIMESTAMP, enddate TIMESTAMP, dollaramount DECIMAL(38,18), active BOOL NOT NULL, usertype int4, count INTEGER,"
|
||||
+ "notes TEXT, userid BIGINT, wiki TEXT, customfields TEXT, tags VARCHAR(255) ARRAY)");
|
||||
|
||||
await ExecQueryAsync("CREATE TABLE afileattachment (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, "
|
||||
+ "attachtoobjectid BIGINT NOT NULL, attachtoatype INTEGER NOT NULL, "
|
||||
+ "storedfilename TEXT NOT NULL, displayfilename TEXT NOT NULL, contenttype TEXT, lastmodified TIMESTAMP NOT NULL, notes TEXT, exists BOOL NOT NULL, size BIGINT NOT NULL)");
|
||||
+ "attachtoobjectid BIGINT NOT NULL, attachtoatype INTEGER NOT NULL, "
|
||||
+ "storedfilename TEXT NOT NULL, displayfilename TEXT NOT NULL, contenttype TEXT, lastmodified TIMESTAMP NOT NULL, notes TEXT, exists BOOL NOT NULL, size BIGINT NOT NULL)");
|
||||
|
||||
//index required for ops that need to check if file already in db (delete, count refs etc)
|
||||
//LOOKAT: isn't this useless without the ID as well or is that not fetched?
|
||||
|
||||
@@ -402,8 +402,7 @@ namespace AyaNova.Util
|
||||
await EraseTableAsync("apm", conn);
|
||||
//---
|
||||
|
||||
await EraseTableAsync("afileattachment", conn);
|
||||
await EraseTableAsync("awidget", conn);
|
||||
await EraseTableAsync("afileattachment", conn);
|
||||
await EraseTableAsync("aevent", conn);
|
||||
await EraseTableAsync("adatalistsavedfilter", conn);
|
||||
await EraseTableAsync("adatalistcolumnview", conn);
|
||||
|
||||
@@ -114,49 +114,49 @@ namespace AyaNova.Util
|
||||
apiServerState.SetOpsOnly("Seeding database with sample data");
|
||||
|
||||
|
||||
// //WIDGET sample form customization
|
||||
// //CUSTOMER sample form customization
|
||||
// {
|
||||
|
||||
// var fc = new FormCustom()
|
||||
// {
|
||||
// FormKey = AyaType.Widget.ToString(),
|
||||
// FormKey = AyaType.Customer.ToString(),
|
||||
// Template = @"[
|
||||
// {
|
||||
// ""fld"": ""Notes"",
|
||||
// ""required"": true
|
||||
// },
|
||||
// {
|
||||
// ""fld"": ""WidgetCustom1"",
|
||||
// ""fld"": ""CustomerCustom1"",
|
||||
// ""required"": false,
|
||||
// ""type"": 1
|
||||
// },
|
||||
// {
|
||||
// ""fld"": ""WidgetCustom2"",
|
||||
// ""fld"": ""CustomerCustom2"",
|
||||
// ""required"": true,
|
||||
// ""type"": 4
|
||||
// },
|
||||
// {
|
||||
// ""fld"": ""WidgetCustom3"",
|
||||
// ""fld"": ""CustomerCustom3"",
|
||||
// ""required"": false,
|
||||
// ""type"": 5
|
||||
// },
|
||||
// {
|
||||
// ""fld"": ""WidgetCustom4"",
|
||||
// ""fld"": ""CustomerCustom4"",
|
||||
// ""required"": false,
|
||||
// ""type"": 6
|
||||
// },
|
||||
// {
|
||||
// ""fld"": ""WidgetCustom5"",
|
||||
// ""fld"": ""CustomerCustom5"",
|
||||
// ""required"": false,
|
||||
// ""type"": 8
|
||||
// },
|
||||
// {
|
||||
// ""fld"": ""WidgetCustom6"",
|
||||
// ""fld"": ""CustomerCustom6"",
|
||||
// ""required"": false,
|
||||
// ""type"": 2
|
||||
// },
|
||||
// {
|
||||
// ""fld"": ""WidgetCustom7"",
|
||||
// ""fld"": ""CustomerCustom7"",
|
||||
// ""required"": false,
|
||||
// ""type"": 3
|
||||
// }
|
||||
@@ -175,9 +175,9 @@ namespace AyaNova.Util
|
||||
// {
|
||||
// Name = "Name starts with generic",
|
||||
// UserId = 1,
|
||||
// ListKey = "TestWidgetDataList",
|
||||
// ListKey = "TestCustomerDataList",
|
||||
// Public = true,
|
||||
// ListView = @"[{""fld"": ""widgetname"",""filter"": {""any"":false,""items"": [{""op"": ""%-"",""value"": ""Generic""}]}}]"
|
||||
// ListView = @"[{""fld"": ""customername"",""filter"": {""any"":false,""items"": [{""op"": ""%-"",""value"": ""Generic""}]}}]"
|
||||
// };
|
||||
|
||||
// //Create and save to db
|
||||
@@ -188,9 +188,9 @@ namespace AyaNova.Util
|
||||
// {
|
||||
// Name = "Awesome (lots of fields)",
|
||||
// UserId = 1,
|
||||
// ListKey = "TestWidgetDataList",
|
||||
// ListKey = "TestCustomerDataList",
|
||||
// Public = true,
|
||||
// ListView = @"[{""fld"": ""widgetname"",""filter"": {""any"":false,""items"": [{""op"": ""%-"",""value"": ""Awesome""}]}},{""fld"":""widgetserial""},{""fld"":""widgetdollaramount""},{""fld"":""widgetusertype""},{""fld"":""widgetstartdate""},{""fld"":""widgetactive""},{""fld"":""username""},{""fld"":""widgettags""},{""fld"":""widgetcustom1""},{""fld"":""widgetcustom2""}]"
|
||||
// ListView = @"[{""fld"": ""customername"",""filter"": {""any"":false,""items"": [{""op"": ""%-"",""value"": ""Awesome""}]}},{""fld"":""customerserial""},{""fld"":""customerdollaramount""},{""fld"":""customerusertype""},{""fld"":""customerstartdate""},{""fld"":""customeractive""},{""fld"":""username""},{""fld"":""customertags""},{""fld"":""customercustom1""},{""fld"":""customercustom2""}]"
|
||||
// };
|
||||
|
||||
// //Create and save to db
|
||||
@@ -227,8 +227,7 @@ namespace AyaNova.Util
|
||||
//Generate owner and lead tech
|
||||
await SeedUserAsync(log, 1, AuthorizationRoles.BizAdmin | AuthorizationRoles.Service | AuthorizationRoles.Inventory | AuthorizationRoles.OpsAdmin, UserType.Service);
|
||||
//Generate one office person / secretary
|
||||
await SeedUserAsync(log, 1, AuthorizationRoles.Service | AuthorizationRoles.Inventory | AuthorizationRoles.Accounting, UserType.NotService);
|
||||
// await SeedWidgetAsync(log, 3);//keeping this here for now but must remove later
|
||||
await SeedUserAsync(log, 1, AuthorizationRoles.Service | AuthorizationRoles.Inventory | AuthorizationRoles.Accounting, UserType.NotService);
|
||||
await SeedVendorAsync(log, 10);
|
||||
await SeedUnitModelAsync(log, 10);
|
||||
await SeedCustomerAsync(log, 25);
|
||||
@@ -287,7 +286,6 @@ namespace AyaNova.Util
|
||||
//1 accountant / bookkeeper
|
||||
await SeedUserAsync(log, 1, AuthorizationRoles.Accounting | AuthorizationRoles.BizAdminRestricted, UserType.NotService);
|
||||
|
||||
//await SeedWidgetAsync(log, 100);
|
||||
await SeedVendorAsync(log, 50);
|
||||
await SeedUnitModelAsync(log, 20);
|
||||
await SeedCustomerAsync(log, 500);
|
||||
@@ -356,7 +354,6 @@ namespace AyaNova.Util
|
||||
//5 accountant / bookkeeper
|
||||
await SeedUserAsync(log, 5, AuthorizationRoles.Accounting | AuthorizationRoles.BizAdminRestricted, UserType.NotService);
|
||||
|
||||
//await SeedWidgetAsync(log, 100);
|
||||
await SeedVendorAsync(log, 100);
|
||||
await SeedUnitModelAsync(log, 40);
|
||||
await SeedCustomerAsync(log, 1000);
|
||||
@@ -426,7 +423,6 @@ namespace AyaNova.Util
|
||||
//accountant / bookkeeper
|
||||
await SeedUserAsync(log, 20, AuthorizationRoles.Accounting | AuthorizationRoles.BizAdminRestricted, UserType.NotService);
|
||||
|
||||
//await SeedWidgetAsync(log, 100);
|
||||
await SeedVendorAsync(log, 500);
|
||||
await SeedUnitModelAsync(log, 200);
|
||||
await SeedCustomerAsync(log, 10000);
|
||||
@@ -1772,62 +1768,7 @@ namespace AyaNova.Util
|
||||
|
||||
}
|
||||
|
||||
#region WIDGET
|
||||
// //////////////////////////////////////////////////////
|
||||
// //Seed widget for testing
|
||||
// //
|
||||
// public async Task SeedWidgetAsync(ILogger log, int count)
|
||||
// {
|
||||
// //this is 4 times slower than doing it inside the loop below
|
||||
// //seems counterintuitive but maybe it's to do with the db context not being refreshed?
|
||||
|
||||
// //RANDOM ROLES
|
||||
// Array values = Enum.GetValues(typeof(UserType));
|
||||
// Random random = new Random();
|
||||
|
||||
// DateTime seedStartWindow = DateTime.Now.AddYears(-1).AddMonths(-6);
|
||||
// DateTime seedEndWindow = DateTime.Now.AddYears(1).AddMonths(6);
|
||||
// for (int x = 0; x < count; x++)
|
||||
// {
|
||||
// Widget o = new Widget();
|
||||
// o.Name = Uniquify(Fake.Commerce.ProductName());
|
||||
// o.Active = true;
|
||||
// DateTime dtSeed = Fake.Date.Between(seedStartWindow, seedEndWindow).ToUniversalTime();
|
||||
// o.StartDate = dtSeed;
|
||||
// o.EndDate = dtSeed.AddMinutes(60).ToUniversalTime();
|
||||
// o.DollarAmount = Convert.ToDecimal(Fake.Commerce.Price());
|
||||
|
||||
// //Random but valid enum
|
||||
// UserType randomUserType = (UserType)values.GetValue(random.Next(values.Length));
|
||||
// o.UserType = randomUserType;
|
||||
// o.Notes = Fake.Lorem.Sentence(null, 5);
|
||||
// o.Tags = RandomTags();
|
||||
// o.UserId = Fake.Random.Int(1, TotalSeededUsers);
|
||||
|
||||
// //RANDOM CUSTOM FIELD DATA
|
||||
// var c1 = DateUtil.UniversalISO8661Format(Fake.Date.Between(DateTime.Now.AddYears(-1), DateTime.Now.AddYears(1)));
|
||||
// var c2 = Fake.Lorem.Sentence(null, 5);
|
||||
// var c3 = Fake.Random.Int(1, 99999999);
|
||||
// var c4 = Fake.Random.Bool().ToString().ToLowerInvariant();
|
||||
// var c5 = Fake.Random.Decimal();
|
||||
// o.CustomFields = $@"{{c1:""{c1}"",c2:""{c2}"",c3:{c3},c4:{c4},c5:{c5}}}";
|
||||
|
||||
// //This seems wrong to do in a loop but is 4 times faster this way ?!?
|
||||
// using (AyContext ct = ServiceProviderProvider.DBContext)
|
||||
// {
|
||||
// WidgetBiz biz = WidgetBiz.GetBiz(ct);
|
||||
// var NewObject = await biz.CreateAsync(o);
|
||||
// if (NewObject == null)
|
||||
// {
|
||||
// log.LogError($"Seeder::SeedWidget error creating {o.Name}\r\n" + biz.GetErrorsAsString());
|
||||
// throw new System.Exception("Seeder::SeedWidget error creating widget\r\n" + biz.GetErrorsAsString());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
public HashSet<string> HashCompanyNames = new HashSet<string>();
|
||||
|
||||
private int TotalSeededCustomers = 0;
|
||||
|
||||
Reference in New Issue
Block a user