This commit is contained in:
@@ -26,7 +26,9 @@ namespace AyaNova.Biz
|
||||
TrialSeeder = 11,
|
||||
Metrics = 12,
|
||||
Locale = 13,
|
||||
UserOptions=14
|
||||
UserOptions=14,
|
||||
TagGroup = 15,
|
||||
TagGroupMap = 16
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -112,6 +112,26 @@ namespace AyaNova.Biz
|
||||
ReadFullRecord = AuthorizationRoles.AnyRole
|
||||
});
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//TAGGROUP - MIRROR TAGS
|
||||
//Full roles can make new tags and can edit or delete existing tags
|
||||
roles.Add(AyaType.TagGroup, new BizRoleSet()
|
||||
{
|
||||
Change = AuthorizationRoles.BizAdminFull | AuthorizationRoles.DispatchFull | AuthorizationRoles.InventoryFull | AuthorizationRoles.TechFull | AuthorizationRoles.AccountingFull,
|
||||
EditOwn = AuthorizationRoles.NoRole,
|
||||
ReadFullRecord = AuthorizationRoles.AnyRole
|
||||
});
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//TAGGROUPMAP - MIRROR TAGMAP
|
||||
//Any roles can tag objects and remove tags as per their rights to the taggable object type in question
|
||||
roles.Add(AyaType.TagGroupMap, new BizRoleSet()
|
||||
{
|
||||
Change = AuthorizationRoles.AnyRole,
|
||||
EditOwn = AuthorizationRoles.NoRole,
|
||||
ReadFullRecord = AuthorizationRoles.AnyRole
|
||||
});
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//OPERATIONS / JOBS
|
||||
|
||||
426
server/AyaNova/biz/TagGroupBiz.cs
Normal file
426
server/AyaNova/biz/TagGroupBiz.cs
Normal file
@@ -0,0 +1,426 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.JsonPatch;
|
||||
using EnumsNET;
|
||||
using AyaNova.Util;
|
||||
using AyaNova.Api.ControllerHelpers;
|
||||
using AyaNova.Biz;
|
||||
using AyaNova.Models;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AyaNova.Biz
|
||||
{
|
||||
|
||||
internal class TagGroupBiz : BizObject, IImportAyaNova7Object
|
||||
{
|
||||
private readonly AyContext ct;
|
||||
public readonly long userId;
|
||||
private readonly AuthorizationRoles userRoles;
|
||||
|
||||
public bool V7ValidationImportMode { get; set; }
|
||||
|
||||
internal TagGroupBiz(AyContext dbcontext, long currentUserId, AuthorizationRoles UserRoles)
|
||||
{
|
||||
ct = dbcontext;
|
||||
userId = currentUserId;
|
||||
userRoles = UserRoles;
|
||||
V7ValidationImportMode = false;//default
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//CREATE
|
||||
internal async Task<TagGroup> CreateAsync(string inObj)
|
||||
{
|
||||
inObj = CleanTagGroupName(inObj);
|
||||
Validate(inObj, true);
|
||||
if (HasErrors)
|
||||
return null;
|
||||
else
|
||||
{
|
||||
//do stuff with TagGroup
|
||||
TagGroup outObj = new TagGroup()
|
||||
{
|
||||
Name = inObj,
|
||||
OwnerId = userId
|
||||
};
|
||||
|
||||
|
||||
await ct.TagGroup.AddAsync(outObj);
|
||||
return outObj;
|
||||
}
|
||||
}
|
||||
|
||||
private static string CleanTagGroupName(string inObj)
|
||||
{
|
||||
//Must be lowercase per rules
|
||||
//This may be naive when we get international customers but for now supporting utf-8 and it appears it's safe to do this with unicode
|
||||
inObj = inObj.ToLowerInvariant();
|
||||
//No spaces in TagGroups, replace with dashes
|
||||
inObj = inObj.Replace(" ", "-");
|
||||
//Remove multiple dash sequences
|
||||
inObj = System.Text.RegularExpressions.Regex.Replace(inObj, "-+", "-");
|
||||
//Ensure doesn't start or end with a dash
|
||||
inObj = inObj.Trim('-');
|
||||
//No longer than 255 characters
|
||||
inObj = StringUtil.MaxLength(inObj, 255);
|
||||
return inObj;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// GET
|
||||
|
||||
//Get one
|
||||
internal async Task<TagGroup> GetAsync(long fetchId)
|
||||
{
|
||||
//This is simple so nothing more here, but often will be copying to a different output object or some other ops
|
||||
return await ct.TagGroup.SingleOrDefaultAsync(m => m.Id == fetchId);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//get picklist (paged)
|
||||
//Unlike most picklists, this one only checks for starts with and wildcards are not supported / treated as part of TagGroup name
|
||||
internal async Task<ApiPagedResponse<NameIdItem>> GetPickListAsync(IUrlHelper Url, string routeName, PagingOptions pagingOptions, string q)
|
||||
{
|
||||
pagingOptions.Offset = pagingOptions.Offset ?? PagingOptions.DefaultOffset;
|
||||
pagingOptions.Limit = pagingOptions.Limit ?? PagingOptions.DefaultLimit;
|
||||
|
||||
NameIdItem[] items;
|
||||
int totalRecordCount = 0;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(q))
|
||||
{
|
||||
//TagGroups are allow saved this way so search this way too
|
||||
q = q.ToLowerInvariant();
|
||||
|
||||
items = await ct.TagGroup
|
||||
//There is some debate on this for efficiency
|
||||
//I chose this method because I think it escapes potential wildcards in the string automatically
|
||||
//and I don't want people using wildcards with this, only starts with is supported
|
||||
//https://stackoverflow.com/questions/45708715/entity-framework-ef-functions-like-vs-string-contains
|
||||
.Where(m => m.Name.StartsWith(q))
|
||||
// .Where(m => EF.Functions.ILike(m.Name, q))
|
||||
.OrderBy(m => m.Name)
|
||||
.Skip(pagingOptions.Offset.Value)
|
||||
.Take(pagingOptions.Limit.Value)
|
||||
.Select(m => new NameIdItem()
|
||||
{
|
||||
Id = m.Id,
|
||||
Name = m.Name
|
||||
}).ToArrayAsync();
|
||||
|
||||
totalRecordCount = await ct.TagGroup.Where(m => m.Name.StartsWith(q)).CountAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
items = await ct.TagGroup
|
||||
.OrderBy(m => m.Name)
|
||||
.Skip(pagingOptions.Offset.Value)
|
||||
.Take(pagingOptions.Limit.Value)
|
||||
.Select(m => new NameIdItem()
|
||||
{
|
||||
Id = m.Id,
|
||||
Name = m.Name
|
||||
}).ToArrayAsync();
|
||||
|
||||
totalRecordCount = await ct.TagGroup.CountAsync();
|
||||
}
|
||||
|
||||
|
||||
|
||||
var pageLinks = new PaginationLinkBuilder(Url, routeName, null, pagingOptions, totalRecordCount).PagingLinksObject();
|
||||
|
||||
ApiPagedResponse<NameIdItem> pr = new ApiPagedResponse<NameIdItem>(items, pageLinks);
|
||||
return pr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//UPDATE
|
||||
//
|
||||
|
||||
//put
|
||||
internal bool Put(TagGroup dbObj, TagGroup inObj)
|
||||
{
|
||||
//Ensure it follows the rules
|
||||
inObj.Name = CleanTagGroupName(inObj.Name);
|
||||
|
||||
//Replace the db object with the PUT object
|
||||
CopyObject.Copy(inObj, dbObj, "Id");
|
||||
//Set "original" value of concurrency token to input token
|
||||
//this will allow EF to check it out
|
||||
ct.Entry(dbObj).OriginalValues["ConcurrencyToken"] = inObj.ConcurrencyToken;
|
||||
|
||||
Validate(dbObj.Name, false);
|
||||
if (HasErrors)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//patch
|
||||
internal bool Patch(TagGroup dbObj, JsonPatchDocument<TagGroup> objectPatch, uint concurrencyToken)
|
||||
{
|
||||
//Validate Patch is allowed
|
||||
if (!ValidateJsonPatch<TagGroup>.Validate(this, objectPatch)) return false;
|
||||
|
||||
//Do the patching
|
||||
objectPatch.ApplyTo(dbObj);
|
||||
ct.Entry(dbObj).OriginalValues["ConcurrencyToken"] = concurrencyToken;
|
||||
//Ensure it follows the rules
|
||||
dbObj.Name = CleanTagGroupName(dbObj.Name);
|
||||
Validate(dbObj.Name, false);
|
||||
if (HasErrors)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//DELETE
|
||||
//
|
||||
|
||||
internal bool Delete(TagGroup dbObj)
|
||||
{
|
||||
//Determine if the object can be deleted, do the deletion tentatively
|
||||
|
||||
ValidateCanDelete(dbObj);
|
||||
if (HasErrors)
|
||||
return false;
|
||||
ct.TagGroup.Remove(dbObj);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//VALIDATION
|
||||
//
|
||||
|
||||
//Can save or update?
|
||||
private void Validate(string inObj, bool isNew)
|
||||
{
|
||||
//run validation and biz rules
|
||||
|
||||
//Name required
|
||||
if (string.IsNullOrWhiteSpace(inObj))
|
||||
AddError(ValidationErrorType.RequiredPropertyEmpty, "Name");
|
||||
|
||||
//Name must be less than 255 characters
|
||||
if (inObj.Length > 255)
|
||||
AddError(ValidationErrorType.LengthExceeded, "Name", "255 char max");
|
||||
|
||||
//Name must be unique
|
||||
if (ct.TagGroup.Where(m => m.Name == inObj).FirstOrDefault() != null)
|
||||
AddError(ValidationErrorType.NotUnique, "Name");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//Can delete?
|
||||
private void ValidateCanDelete(TagGroup inObj)
|
||||
{
|
||||
//whatever needs to be check to delete this object
|
||||
|
||||
//See if any TagGroupmaps exist with this TagGroup in which case it's not deleteable
|
||||
if (ct.TagGroupMap.Any(e => e.TagGroupId == inObj.Id))
|
||||
{
|
||||
AddError(ValidationErrorType.ReferentialIntegrity, "object", "Can't be deleted while has relations");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
/// IMPORT v7 implementation
|
||||
public async Task<bool> ImportV7Async(JObject j, List<ImportAyaNova7MapItem> importMap, Guid jobId)
|
||||
{
|
||||
//NO TASK TYPE, IT'S ALL THE SAME, KEEPING THIS FOR POSSIBLE FUTURE PURPOSES LIKE APPENDING OBJECT TYPE OR SOMETHING
|
||||
string SourceType = j["V7_TYPE"].Value<string>();
|
||||
switch (SourceType)
|
||||
{
|
||||
case "GZTW.AyaNova.BLL.Region":
|
||||
case "GZTW.AyaNova.BLL.UnitModelCategory":
|
||||
case "GZTW.AyaNova.BLL.UnitServiceType":
|
||||
case "GZTW.AyaNova.BLL.WorkorderItemType":
|
||||
case "GZTW.AyaNova.BLL.ClientGroup":
|
||||
case "GZTW.AyaNova.BLL.WorkorderCategory":
|
||||
case "GZTW.AyaNova.BLL.PartCategory":
|
||||
case "GZTW.AyaNova.BLL.DispatchZone":
|
||||
case "GZTW.AyaNova.BLL.ScheduleableUserGroup":
|
||||
{
|
||||
switch (j["IMPORT_TASK"].Value<string>())
|
||||
{
|
||||
case "main":
|
||||
{
|
||||
#region main import task
|
||||
var NewTagGroupName = j["Name"].Value<string>();
|
||||
|
||||
var ShortTypeName = string.Empty;
|
||||
switch (SourceType)
|
||||
{
|
||||
case "GZTW.AyaNova.BLL.Region":
|
||||
ShortTypeName = "rgn";
|
||||
break;
|
||||
case "GZTW.AyaNova.BLL.UnitModelCategory":
|
||||
ShortTypeName = "unitmdlctgry";
|
||||
break;
|
||||
case "GZTW.AyaNova.BLL.UnitServiceType":
|
||||
ShortTypeName = "unitsvtyp";
|
||||
break;
|
||||
case "GZTW.AyaNova.BLL.WorkorderItemType":
|
||||
ShortTypeName = "woitemtyp";
|
||||
break;
|
||||
case "GZTW.AyaNova.BLL.ClientGroup":
|
||||
ShortTypeName = "clntgrp";
|
||||
break;
|
||||
case "GZTW.AyaNova.BLL.WorkorderCategory":
|
||||
ShortTypeName = "woctgry";
|
||||
break;
|
||||
case "GZTW.AyaNova.BLL.PartCategory":
|
||||
ShortTypeName = "prtctgry";
|
||||
break;
|
||||
case "GZTW.AyaNova.BLL.DispatchZone":
|
||||
ShortTypeName = "dspchzn";
|
||||
break;
|
||||
case "GZTW.AyaNova.BLL.ScheduleableUserGroup":
|
||||
ShortTypeName = "schdusrgrp";
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
NewTagGroupName += "." + ShortTypeName;
|
||||
var OldV7Id = new Guid(j["ID"].Value<string>());
|
||||
|
||||
//Ensure it follows the rules
|
||||
NewTagGroupName = CleanTagGroupName(NewTagGroupName);
|
||||
|
||||
//There might already be a TagGroup of the same name since so many different types of V7 objects are becoming TagGroups
|
||||
//Weighed the pros and cons of uniquifying by object type versus just using the same name for different object types:
|
||||
//it seems to me at this point that people might desire the same exact name because if they used it that way they probably
|
||||
//intended it that way, so decision is to check if it already exists and then use that ID in the importMap instead
|
||||
//for matching other objects imported to TagGroups
|
||||
|
||||
//Already present?
|
||||
var ExistingTagGroup = ct.TagGroup.Where(m => m.Name == NewTagGroupName).FirstOrDefault();
|
||||
if (ExistingTagGroup != null)
|
||||
{
|
||||
//map it to the existing TagGroup of same name
|
||||
var mapItem = new ImportAyaNova7MapItem(OldV7Id, AyaType.TagGroup, ExistingTagGroup.Id);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
TagGroup o = await CreateAsync(NewTagGroupName);
|
||||
if (HasErrors)
|
||||
{
|
||||
//If there are any validation errors, log in joblog and move on
|
||||
JobsBiz.LogJob(jobId, $"TagGroupBiz::ImportV7Async -> import object \"{NewTagGroupName}\" of type \"{SourceType}\" source id {OldV7Id.ToString()} failed validation and was not imported: {GetErrorsAsString()} ", ct);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
await ct.SaveChangesAsync();
|
||||
var mapItem = new ImportAyaNova7MapItem(OldV7Id, AyaType.TagGroup, o.Id);
|
||||
importMap.Add(mapItem);
|
||||
await ImportAyaNova7Biz.LogEventCreatedModifiedEvents(j, importMap, AyaType.TagGroup, ct);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
break;
|
||||
case "scheduleableusergroupTagGroups":
|
||||
{
|
||||
#region attribute sched user group TagGroups
|
||||
/*
|
||||
{
|
||||
"ID": "871e77b2-979a-4f26-930b-46f7c05fc19f",
|
||||
"Created": "08/30/2018 08:12 AM",
|
||||
"Modified": "08/30/2018 08:13 AM",
|
||||
"Creator": "2ecc77fc-69e2-4a7e-b88d-bd0ecaf36aed",
|
||||
"Modifier": "2ecc77fc-69e2-4a7e-b88d-bd0ecaf36aed",
|
||||
"Name": "Yet another test group",
|
||||
"Active": true,
|
||||
"Description": "More testing yay!",
|
||||
"ScheduleableUsers": [
|
||||
{
|
||||
"Created": "08/30/2018 08:13 AM",
|
||||
"Creator": "2ecc77fc-69e2-4a7e-b88d-bd0ecaf36aed",
|
||||
"Modified": "08/30/2018 08:13 AM",
|
||||
"Modifier": "2ecc77fc-69e2-4a7e-b88d-bd0ecaf36aed",
|
||||
"ID": "676475be-8301-47d0-bd54-af9dbd1fe7eb",
|
||||
"ScheduleableUserID": "1d859264-3f32-462a-9b0c-a67dddfdf4d3",
|
||||
"ScheduleableUserGroupID": "871e77b2-979a-4f26-930b-46f7c05fc19f"
|
||||
},
|
||||
{
|
||||
"Created": "08/30/2018 08:13 AM",
|
||||
"Creator": "2ecc77fc-69e2-4a7e-b88d-bd0ecaf36aed",
|
||||
"Modified": "08/30/2018 08:13 AM",
|
||||
"Modifier": "2ecc77fc-69e2-4a7e-b88d-bd0ecaf36aed",
|
||||
"ID": "173499c3-a616-42a0-b08c-74008f8fa352",
|
||||
"ScheduleableUserID": "42b282bb-100b-4b31-aa14-5c831d7cda66",
|
||||
"ScheduleableUserGroupID": "871e77b2-979a-4f26-930b-46f7c05fc19f"
|
||||
},
|
||||
{
|
||||
"Created": "08/30/2018 08:13 AM",
|
||||
"Creator": "2ecc77fc-69e2-4a7e-b88d-bd0ecaf36aed",
|
||||
"Modified": "08/30/2018 08:13 AM",
|
||||
"Modifier": "2ecc77fc-69e2-4a7e-b88d-bd0ecaf36aed",
|
||||
"ID": "19c9b3d6-eeb2-44ac-be4e-6ec93d15b02a",
|
||||
"ScheduleableUserID": "e6ff9bc6-a550-4242-8c41-857f740e2841",
|
||||
"ScheduleableUserGroupID": "871e77b2-979a-4f26-930b-46f7c05fc19f"
|
||||
}
|
||||
]
|
||||
}
|
||||
*/
|
||||
var V7Id = new Guid(j["ID"].Value<string>());
|
||||
var RavenTagGroupId = importMap.Where(m => m.V7ObjectId == V7Id).First().NewObjectAyaTypeId.ObjectId;
|
||||
|
||||
foreach (JToken t in j["ScheduleableUsers"])
|
||||
{
|
||||
var techId = new Guid(t["ScheduleableUserID"].Value<String>());
|
||||
var RavenUserId = importMap.Where(m => m.V7ObjectId == techId).First().NewObjectAyaTypeId.ObjectId;
|
||||
var Creator = importMap.Where(m => m.V7ObjectId == new Guid(t["Creator"].Value<string>())).First().NewObjectAyaTypeId.ObjectId;
|
||||
|
||||
TagGroupMap tm = new TagGroupMap();
|
||||
tm.TagGroupToObjectId = RavenUserId;
|
||||
tm.TagGroupToObjectType=AyaType.User;
|
||||
tm.TagGroupId = RavenTagGroupId;
|
||||
tm.OwnerId = Creator;
|
||||
ct.TagGroupMap.Add(tm);
|
||||
}
|
||||
ct.SaveChanges();
|
||||
|
||||
#endregion
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
|
||||
//this is the equivalent of returning void for a Task signature with nothing to return
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
}//eoc
|
||||
|
||||
//
|
||||
}//eons
|
||||
|
||||
177
server/AyaNova/biz/TagGroupMapBiz.cs
Normal file
177
server/AyaNova/biz/TagGroupMapBiz.cs
Normal file
@@ -0,0 +1,177 @@
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.JsonPatch;
|
||||
using EnumsNET;
|
||||
using AyaNova.Util;
|
||||
using AyaNova.Api.ControllerHelpers;
|
||||
using AyaNova.Biz;
|
||||
using AyaNova.Models;
|
||||
using System.Collections.Generic;
|
||||
|
||||
|
||||
namespace AyaNova.Biz
|
||||
{
|
||||
|
||||
|
||||
internal class TagGroupMapBiz : BizObject
|
||||
{
|
||||
private readonly AyContext ct;
|
||||
public readonly long userId;
|
||||
private readonly AuthorizationRoles userRoles;
|
||||
|
||||
|
||||
internal TagGroupMapBiz(AyContext dbcontext, long currentUserId, AuthorizationRoles UserRoles)
|
||||
{
|
||||
ct = dbcontext;
|
||||
userId = currentUserId;
|
||||
userRoles = UserRoles;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//CREATE
|
||||
internal async Task<TagGroupMap> CreateAsync(TagGroupMapInfo inObj)
|
||||
{
|
||||
|
||||
Validate(inObj, true);
|
||||
if (HasErrors)
|
||||
return null;
|
||||
else
|
||||
{
|
||||
//do stuff with TagGroupMap
|
||||
TagGroupMap outObj = new TagGroupMap()
|
||||
{
|
||||
TagId = inObj.TagId,
|
||||
TagToObjectId = inObj.TagToObjectId,
|
||||
TagToObjectType = inObj.TagToObjectType,
|
||||
OwnerId = userId
|
||||
};
|
||||
|
||||
|
||||
await ct.TagGroupMap.AddAsync(outObj);
|
||||
return outObj;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// GET
|
||||
|
||||
//Get one
|
||||
internal async Task<TagGroupMap> GetAsync(long fetchId)
|
||||
{
|
||||
//This is simple so nothing more here, but often will be copying to a different output object or some other ops
|
||||
return await ct.TagGroupMap.SingleOrDefaultAsync(m => m.Id == fetchId);
|
||||
}
|
||||
|
||||
|
||||
internal async Task<List<NameIdItem>> GetTagsOnObjectListAsync(AyaTypeId tid)
|
||||
{
|
||||
/*
|
||||
|
||||
NOTES: This will be a bit of a "hot" path as every fetch of any main object will involve this
|
||||
for now, just make it work and later can improve performance
|
||||
|
||||
Also is sort going to be adequate, it's supposed to be based on invariant culture
|
||||
|
||||
*/
|
||||
|
||||
List<NameIdItem> l = new List<NameIdItem>();
|
||||
|
||||
//Get the list of tags on the object
|
||||
var TagGroupMapsOnObject = await ct.TagGroupMap
|
||||
.Where(m => m.TagToObjectId == tid.ObjectId && m.TagToObjectType == tid.ObjectType)
|
||||
.Select(m => m.TagId)
|
||||
.ToListAsync();
|
||||
|
||||
foreach (long tagId in TagGroupMapsOnObject)
|
||||
{
|
||||
var tagFromDb = await ct.Tag.SingleOrDefaultAsync(m => m.Id == tagId);
|
||||
if (tagFromDb != null)
|
||||
{
|
||||
l.Add(new NameIdItem() { Id = tagFromDb.Id, Name = tagFromDb.Name });
|
||||
}
|
||||
}
|
||||
|
||||
//Return the list sorted alphabetically
|
||||
//Note if this is commonly required then maybe make a helper / extension for it
|
||||
return (l.OrderBy(o => o.Name).ToList());
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//DELETE
|
||||
//
|
||||
|
||||
internal bool Delete(TagGroupMap dbObj)
|
||||
{
|
||||
//Determine if the object can be deleted, do the deletion tentatively
|
||||
|
||||
ValidateCanDelete(dbObj);
|
||||
if (HasErrors)
|
||||
return false;
|
||||
ct.TagGroupMap.Remove(dbObj);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//DELETE ALL TagGroupMapS FOR OBJECT
|
||||
//
|
||||
|
||||
static internal bool DeleteAllForObject(AyaTypeId parentObj, AyContext ct)
|
||||
{
|
||||
//Be careful in future, if you put ToString at the end of each object in the string interpolation
|
||||
//npgsql driver will assume it's a string and put quotes around it triggering an error that a string can't be compared to an int
|
||||
ct.Database.ExecuteSqlCommand($"delete from aTagGroupMap where tagtoobjectid={parentObj.ObjectId} and tagtoobjecttype={parentObj.ObjectTypeAsInt}");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//VALIDATION
|
||||
//
|
||||
|
||||
//Can save or update?
|
||||
private void Validate(TagGroupMapInfo inObj, bool isNew)
|
||||
{
|
||||
//run validation and biz rules
|
||||
|
||||
// //Name required
|
||||
// if (string.IsNullOrWhiteSpace(inObj))
|
||||
// AddError(ValidationErrorType.RequiredPropertyEmpty, "Name");
|
||||
|
||||
// //Name must be less than 255 characters
|
||||
// if (inObj.Length > 255)
|
||||
// AddError(ValidationErrorType.LengthExceeded, "Name", "255 char max");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//Can delete?
|
||||
private void ValidateCanDelete(TagGroupMap inObj)
|
||||
{
|
||||
//whatever needs to be check to delete this object
|
||||
|
||||
//See if any TagGroupMaps exist with this tag in which case it's not deleteable
|
||||
// if (ct.TagGroupMap.Any(e => e.TagGroupMapId == inObj.Id))
|
||||
// {
|
||||
// AddError(ValidationErrorType.ReferentialIntegrity, "object", "Can't be deleted while has relations");
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
}//eoc
|
||||
|
||||
|
||||
}//eons
|
||||
|
||||
@@ -16,6 +16,8 @@ namespace AyaNova.Models
|
||||
public virtual DbSet<FileAttachment> FileAttachment { get; set; }
|
||||
public virtual DbSet<Tag> Tag { get; set; }
|
||||
public virtual DbSet<TagMap> TagMap { get; set; }
|
||||
public virtual DbSet<TagGroup> TagGroup { get; set; }
|
||||
public virtual DbSet<TagGroupMap> TagGroupMap { get; set; }
|
||||
public virtual DbSet<OpsJob> OpsJob { get; set; }
|
||||
public virtual DbSet<OpsJobLog> OpsJobLog { get; set; }
|
||||
public virtual DbSet<Locale> Locale { get; set; }
|
||||
|
||||
21
server/AyaNova/models/TagGroup.cs
Normal file
21
server/AyaNova/models/TagGroup.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using AyaNova.Biz;
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace AyaNova.Models
|
||||
{
|
||||
|
||||
public partial class TagGroup
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public uint ConcurrencyToken { get; set; }
|
||||
|
||||
[Required]
|
||||
public long OwnerId { get; set; }
|
||||
[Required, MaxLength(255)]
|
||||
public string Name { get; set; }//max 255 characters ascii set
|
||||
|
||||
}
|
||||
}
|
||||
23
server/AyaNova/models/TagGroupMap.cs
Normal file
23
server/AyaNova/models/TagGroupMap.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using AyaNova.Biz;
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace AyaNova.Models
|
||||
{
|
||||
|
||||
public partial class TagGroupMap
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public uint ConcurrencyToken { get; set; }
|
||||
[Required]
|
||||
public long OwnerId { get; set; }
|
||||
|
||||
[Required]
|
||||
public long TagId { get; set; }
|
||||
[Required]
|
||||
public long TagGroupId { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -144,7 +144,7 @@ namespace AyaNova.Util
|
||||
"dlkey text, dlkeyexpire timestamp, usertype integer not null, employeenumber varchar(255), notes text, clientid bigint, headofficeid bigint, subvendorid bigint)");
|
||||
|
||||
//Add user options table
|
||||
exec("CREATE TABLE auseroptions (id BIGSERIAL PRIMARY KEY, ownerid bigint not null, "+
|
||||
exec("CREATE TABLE auseroptions (id BIGSERIAL PRIMARY KEY, ownerid bigint not null, " +
|
||||
"userid bigint not null, timezoneoffset decimal(19,5) not null default 0, emailaddress text, uicolor int not null default 0)");
|
||||
|
||||
|
||||
@@ -211,6 +211,10 @@ namespace AyaNova.Util
|
||||
exec("CREATE TABLE atagmap (id BIGSERIAL PRIMARY KEY, ownerid bigint not null," +
|
||||
"tagid bigint not null REFERENCES atag (id), tagtoobjectid bigint not null, tagtoobjecttype integer not null)");
|
||||
|
||||
//Taggroup
|
||||
exec("CREATE TABLE ataggroup (id BIGSERIAL PRIMARY KEY, ownerid bigint not null, name varchar(255) not null)");
|
||||
exec("CREATE TABLE ataggroupmap (id BIGSERIAL PRIMARY KEY, ownerid bigint not null, tagid bigint not null REFERENCES atag (id), taggroupid bigint not null)");
|
||||
|
||||
setSchemaLevel(++currentSchema);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user