using CloudBuilder.Core.DatabaseAccessor; using CloudBuilder.Core.DatabaseAccessor.Entity; using CloudBuilder.Core.Service; using CloudBuilder.Master.Data; using CloudBuilder.Master.Entity; using CloudBuilder.Master.Policy; using CloudBuilder.Master.SearchCriteria; using CloudBuilder.Master.Service.FamilyTreeUtility; using CloudBuilder.Security.Data; using CloudBuilder.Security.Entity; using CloudBuilder.Security.Policy; using CloudBuilder.Security.Service; using CloudBuilder.Security.Utility; using Microsoft.AspNetCore.Authorization; using Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal; using Microsoft.Extensions.DependencyInjection; using System.Collections.Generic; namespace CloudBuilder.Master.Service { public class FamilyTreeService : IFamilyTreeService { /// 头像上传目录,与前端 FileUpload 的 file-path 保持一致 private const string AVATAR_FOLDER_NAME = "FamilyPersonAvatar"; private readonly IApplicationService service; private IRepository repository; public FamilyTreeService(IApplicationService service) { this.service = service; repository = service.GetRepository>(); } /// 把 AvatarFilename 拼装成可访问的 AvatarUrl,供谱系图卡片显示头像 private void FillAvatarUrl(FamilyPersonDisplayData person) { if (person == null) return; person.AvatarUrl = FileTypePolicy.PackAvatarUrl(service, AVATAR_FOLDER_NAME, person.AvatarFilename); } /// 批量填充头像访问地址 private void FillAvatarUrl(FamilyPersonDisplayData[] persons) { if (persons == null || persons.Length == 0) return; foreach (FamilyPersonDisplayData person in persons) { FillAvatarUrl(person); } } [PermissionOperate(name: MasterPermissionPolicy.FamilyTree, operate: Operate.Find)] public FamilyTreeData FindAllByTreeId(string treeId) { FamilyTreeData data = new FamilyTreeData(); if (string.IsNullOrEmpty(treeId)) return data; FamilyTreeEntity d = repository.DetachedEntities.Where(x => x.TreeId == treeId).FirstOrDefault(); if (d == null) return data; data.FamilyTree = new FamilyTreeDisplayData(d); data.CurrentPerson = new FamilyPersonData(); IRepository repositoryFamilyPerson = repository.GetRepository>(); var currentPerson = d.AncestorPersonId; data.CurrentPerson.FamilyPerson = new FamilyPersonDisplayData(repositoryFamilyPerson.DetachedEntities.Where(x => x.PersonId == currentPerson).FirstOrDefault()!); FillAvatarUrl(data.CurrentPerson.FamilyPerson); data.FamilyTree.AncestorPersonGenealogyName = data.CurrentPerson.FamilyPerson.GenealogyName; IRepository repositoryChildrenMap = repository.GetRepository>(); IRepository repositorySpouseMap = repository.GetRepository>(); data.CurrentPerson.FamilyTreeSpouseMaps = repositorySpouseMap.GetRepository>().DetachedEntities.Where(x => x.TreeId == treeId).OrderBy(x => x.Orderby).ToArray(); data.CurrentPerson.FamilyTreeChildrenMaps = repositoryChildrenMap.GetRepository>().DetachedEntities.Where(x => x.TreeId == treeId).OrderBy(x => x.Orderby).ToArray(); List ps = new List(); ps.Add(d.AncestorPersonId); if (data.CurrentPerson.FamilyTreeSpouseMaps != null && data.CurrentPerson.FamilyTreeSpouseMaps.Length > 0) { ps.AddRange(data.CurrentPerson.FamilyTreeSpouseMaps.Select(x => x.SpouseId).ToArray()); } if (data.CurrentPerson.FamilyTreeChildrenMaps != null && data.CurrentPerson.FamilyTreeChildrenMaps.Length > 0) { ps.AddRange(data.CurrentPerson.FamilyTreeChildrenMaps.Select(x => x.ChildrenId).ToArray()); } ps = ps.Distinct().ToList(); FamilyPersonEntity[] families = repositoryFamilyPerson.DetachedEntities.Where(x => ps.AsQueryable().Contains(x.PersonId)).ToArray(); if (families != null && families.Length > 0) { data.CurrentPerson.FamilyTreePersons = families.Select(x => new FamilyPersonDisplayData(x)).ToArray(); FillAvatarUrl(data.CurrentPerson.FamilyTreePersons); } return data; } [PermissionOperate(name: MasterPermissionPolicy.FamilyTree, operate: Operate.Find)] public FamilyTreeData FindByKey(string key) { return FindByCurrentPerson(key, null); } [PermissionOperate(name: MasterPermissionPolicy.FamilyTree, operate: Operate.Find)] public FamilyTreeData FindByCurrentPerson(string key, string personId) { FamilyTreeData data = new FamilyTreeData(); if (string.IsNullOrEmpty(key)) return data; FamilyTreeEntity d = repository.DetachedEntities.Where(x => x.TreeId == key).FirstOrDefault(); if (d == null) return data; IRepository repositoryPermission = repository.GetRepository>(); data.FamilyTree = new FamilyTreeDisplayData(d); data.CurrentPerson = new FamilyPersonData(); data.FamilyTreePermissions = repositoryPermission.DetachedEntities.Where(x => x.TreeId == key).ToArray(); if (data.FamilyTreePermissions.Any()) { data.IsManager = data.FamilyTreePermissions.Where(x => x.UserName == service.UserId && x.ManagerIndc == YesNoPolicy.YES).Any(); if (data.IsManager) data.IsCanAmend = true; } if (!data.IsManager && data.FamilyTreePermissions.Any()) { data.FamilyTreePermissions = data.FamilyTreePermissions.Where(x => x.UserName == service.UserId && x.ValidIndc == YesNoPolicy.NO).ToArray(); } IRepository repositoryFamilyPerson = repository.GetRepository>(); var currentPerson = personId; if (string.IsNullOrEmpty(personId)) { currentPerson = d.AncestorPersonId; data.CurrentPerson.FamilyPerson = new FamilyPersonDisplayData(repositoryFamilyPerson.DetachedEntities.Where(x => x.PersonId == currentPerson).FirstOrDefault()!); data.FamilyTree.AncestorPersonGenealogyName = data.CurrentPerson.FamilyPerson.GenealogyName; } else { data.CurrentPerson.FamilyPerson = new FamilyPersonDisplayData(repositoryFamilyPerson.DetachedEntities.Where(x => x.PersonId == d.AncestorPersonId).FirstOrDefault()!); data.FamilyTree.AncestorPersonGenealogyName = data.CurrentPerson.FamilyPerson.GenealogyName; data.CurrentPerson.FamilyPerson = new FamilyPersonDisplayData(repositoryFamilyPerson.DetachedEntities.Where(x => x.PersonId == personId).FirstOrDefault()!); } FillAvatarUrl(data.CurrentPerson.FamilyPerson); IRepository repositoryChildrenMap = repository.GetRepository>(); IRepository repositorySpouseMap = repository.GetRepository>(); data.CurrentPerson.FamilyTreeSpouseMaps = repositorySpouseMap.GetRepository>().DetachedEntities.Where(x => x.PersonId == currentPerson).OrderBy(x => x.Orderby).ToArray(); //data.CurrentPerson.FamilyTreeParentMaps = repositoryChildrenMap.GetRepository>().DetachedEntities.Where(x => x.ChildrenId == key).OrderBy(x => x.Orderby).ToArray(); data.CurrentPerson.FamilyTreeChildrenMaps = repositoryChildrenMap.GetRepository>().DetachedEntities.Where(x => x.PersonId == currentPerson).OrderBy(x => x.Orderby).ToArray(); // 补充当前人员及其配偶、子女的人员信息(含头像地址),供谱系图卡片显示头像 List ps = new List(); if (!string.IsNullOrEmpty(currentPerson)) ps.Add(currentPerson); if (data.CurrentPerson.FamilyTreeSpouseMaps != null) { ps.AddRange(data.CurrentPerson.FamilyTreeSpouseMaps.Select(x => x.SpouseId).ToArray()); } if (data.CurrentPerson.FamilyTreeChildrenMaps != null) { ps.AddRange(data.CurrentPerson.FamilyTreeChildrenMaps.Select(x => x.ChildrenId).ToArray()); } ps = ps.Where(x => !string.IsNullOrEmpty(x)).Distinct().ToList(); FamilyPersonEntity[] families = repositoryFamilyPerson.DetachedEntities.Where(x => ps.AsQueryable().Contains(x.PersonId)).ToArray(); if (families != null && families.Length > 0) { data.CurrentPerson.FamilyTreePersons = families.Select(x => new FamilyPersonDisplayData(x)).ToArray(); FillAvatarUrl(data.CurrentPerson.FamilyTreePersons); } if (!data.IsCanAmend) data.IsCanAmend = new FamilyTreePermissionHelper(service).HasPermission(data.FamilyTree.TreeId, currentPerson); return data; } [PermissionOperate(name: MasterPermissionPolicy.FamilyTree, operate: Operate.Find)] public FamilyTreeResultData FindBySearchCriteria(FamilyTreeSearchCriteria criteria) { FamilyTreeResultData data = new FamilyTreeResultData(); FamilyTreeViewEntity[] list = null; Int64 count = 0; string sqlWhere = null; if (criteria.Filter != null && criteria.Filter.Length > 0) { sqlWhere = SearchFilter.ComposeWhereClause(criteria.Filter); } FamilyTreeViewEntity entity = FamilyTreeViewEntity.GetInstance(repository.GetDbContext().Database.ProviderName); string sql = entity.GetSelectTopFrom(criteria.limit, criteria.page, criteria.orderby.StringToDbField(), criteria.orderbytag, sqlWhere); IRepository repositoryView = repository.GetRepository>(); string err = null; try { list = repositoryView.FromSql(sql).ToArray(); } catch (System.Exception ex) { err = ex.Message; } if (list != null && list.Length > 0) { sql = entity.GetSelectCountFrom(sqlWhere); count = Convert.ToInt64(repository.ExecuteScalar(sql)); } data.Limit = criteria.limit; data.Page = criteria.page; data.Datas = list; data.Total = count; //data.Sql = sql; data.ErrorMessage = err; return data; } //[PermissionOperate(name: MasterPermissionPolicy.FamilyTree, operate: Operate.Print)] public dynamic PrintBySearchCriteria(FamilyTreeSearchCriteria criteria) { throw new NotImplementedException(); } [PermissionOperate(name: MasterPermissionPolicy.FamilyTree, operate: Operate.Insert)] [UnitOfWork] public FamilyTreeData Insert(FamilyTreeData data) { FamilyTreeEntity d = repository.DetachedEntities.Where(x => x.TreeName == data.FamilyTree.TreeName).FirstOrDefault(); if (d != null) { throw new ValidatedException("家族名称已存在."); } Validate(data.FamilyTree); d = new FamilyTreeEntity(); ObjectCopyHelper.Copy(data.FamilyTree, d); ISecurityGeneratorNumberService securityGeneratorNumberService = service.ServiceProvider.GetService()!; d.TreeId = securityGeneratorNumberService.GetNo(MasterPrefixPolicy.FAMILY_TREE, MasterPrefixPolicy.FAMILY_TREE_TREE_ID, MasterPrefixPolicy.FAMILY_TREE_PREFIX, YesNoPolicy.NO, MasterPrefixPolicy.FAMILY_TREE_FORMAT); repository.InsertNow(d); FamilyTreePermissionEntity treePermissionEntity = new FamilyTreePermissionEntity(); treePermissionEntity.TreeId = d.TreeId; treePermissionEntity.PersonId = d.AncestorPersonId; treePermissionEntity.UserName = service.UserId; treePermissionEntity.ManagerIndc = YesNoPolicy.YES; treePermissionEntity.ValidIndc = YesNoPolicy.YES; InsertFamilyTreePermission(treePermissionEntity); IRepository repositoryPerson = repository.GetRepository>(); FamilyPersonEntity familyPerson; familyPerson = repositoryPerson.DetachedEntities.Where(x => x.PersonId == d.AncestorPersonId).FirstOrDefault()!; familyPerson.TreeId = d.TreeId; repositoryPerson.UpdateNow(familyPerson); var currentPerson = d.AncestorPersonId; if (data.CurrentPerson != null && data.CurrentPerson.FamilyPerson != null && !string.IsNullOrEmpty(data.CurrentPerson.FamilyPerson.PersonId)) { currentPerson = data.CurrentPerson.FamilyPerson.PersonId; } if (data.CurrentPerson != null && data.CurrentPerson.FamilyTreeSpouseMaps != null && data.CurrentPerson.FamilyTreeSpouseMaps.Length > 0) data.CurrentPerson.FamilyTreeSpouseMaps.ToLookup(x => x.TreeId = d.TreeId); if (data.CurrentPerson != null && data.CurrentPerson.FamilyTreeChildrenMaps != null && data.CurrentPerson.FamilyTreeChildrenMaps.Length > 0) data.CurrentPerson.FamilyTreeChildrenMaps.ToLookup(x => x.TreeId = d.TreeId); SaveSpouseMaps(currentPerson, data.CurrentPerson.FamilyTreeSpouseMaps); //SaveParentMaps(data.CurrentPerson.FamilyPerson.PersonId, data.CurrentPerson.FamilyTreeParentMaps); SaveSonMaps(currentPerson, data.CurrentPerson.FamilyTreeChildrenMaps); return FindByCurrentPerson(d.TreeId, currentPerson); } public void InsertFamilyTreePermission(FamilyTreePermissionEntity treePermissionEntity) { IRepository repositoryPermission = repository.GetRepository>(); repositoryPermission.InsertNow(treePermissionEntity); } [PermissionOperate(name: MasterPermissionPolicy.FamilyTree, operate: Operate.Find)] [UnitOfWork] public void RequestFamilyTreePermission(string treeId, string currentPersonId) { IRepository repositoryPermission = repository.GetRepository>(); FamilyTreePermissionEntity treePermissionEntity = repositoryPermission.DetachedEntities.Where(x => x.TreeId == treeId && x.PersonId == currentPersonId && service.UserId == x.UserName).FirstOrDefault()!; if (treePermissionEntity != null) return; treePermissionEntity = new FamilyTreePermissionEntity(); treePermissionEntity.TreeId = treeId; treePermissionEntity.PersonId = currentPersonId; treePermissionEntity.UserName = service.UserId; treePermissionEntity.ManagerIndc = YesNoPolicy.NO; treePermissionEntity.ValidIndc = YesNoPolicy.NO; InsertFamilyTreePermission(treePermissionEntity); } [PermissionOperate(name: MasterPermissionPolicy.FamilyTree, operate: Operate.Find)] [UnitOfWork] public void ApproveFamilyTreePermission(string treeId, string currentPersonId, string userName, string managerIndc) { IRepository repositoryPermission = repository.GetRepository>(); FamilyTreePermissionEntity treePermissionEntity = repositoryPermission.DetachedEntities.Where(x => x.TreeId == treeId && x.PersonId == currentPersonId && userName == x.UserName).FirstOrDefault()!; if (treePermissionEntity == null) return; treePermissionEntity.ManagerIndc = managerIndc; treePermissionEntity.ValidIndc = YesNoPolicy.YES; repositoryPermission.UpdateNow(treePermissionEntity); } [PermissionOperate(name: MasterPermissionPolicy.FamilyTree, operate: Operate.Find)] [UnitOfWork] public void RejectFamilyTreePermission(string treeId, string currentPersonId, string userName) { IRepository repositoryPermission = repository.GetRepository>(); FamilyTreePermissionEntity treePermissionEntity = repositoryPermission.DetachedEntities.Where(x => x.TreeId == treeId && x.PersonId == currentPersonId && userName == x.UserName).FirstOrDefault()!; if (treePermissionEntity == null) return; repositoryPermission.DeleteNow(treePermissionEntity); } private void SaveSpouseMaps(string personId, FamilyTreeSpouseMapViewEntity[] maps) { IRepository repositoryMapView = repository.GetRepository>(); IRepository repositoryMap = repository.GetRepository>(); IRepository repositoryPerson = repository.GetRepository>(); FamilyPersonEntity familyPerson; FamilyTreeSpouseMapViewEntity[] olds = repositoryMapView.Entities.Where(x => x.PersonId == personId).ToArray(); if (olds != null && olds.Length > 0) { foreach (FamilyTreeSpouseMapViewEntity old in olds) { familyPerson = repositoryPerson.DetachedEntities.Where(x => x.PersonId == old.PersonId).FirstOrDefault()!; if (familyPerson != null) { repositoryPerson.DeleteNow(familyPerson); } repositoryMap.DeleteNow(new FamilyTreeSpouseMapEntity() { TreeId = old.TreeId, PersonId = personId, SpouseId = old.SpouseId }); } } if (maps == null || maps.Length == 0) return; int i = 1; foreach (FamilyTreeSpouseMapViewEntity map in maps.OrderBy(x => x.Orderby).ToArray()) { familyPerson = repositoryPerson.DetachedEntities.Where(x => x.PersonId == map.PersonId && string.IsNullOrEmpty(x.TreeId)).FirstOrDefault()!; if (familyPerson != null) { familyPerson.TreeId = map.TreeId; repositoryPerson.Update(familyPerson); } repositoryMap.InsertNow(new FamilyTreeSpouseMapEntity() { TreeId = map.TreeId, PersonId = personId, SpouseId = map.SpouseId, MarryDateText = map.MarryDateText, MarryDate = map.MarryDate, DivorceDateText = map.DivorceDateText, DivorceDate = map.DivorceDate, MarryType = map.MarryType, IsCurrent = map.IsCurrent, Remark = map.Remark, Orderby = i++ }); } } private void SaveSonMaps(string personId, FamilyTreeChildrenMapViewEntity[] maps) { IRepository repositoryMapView = repository.GetRepository>(); IRepository repositoryMap = repository.GetRepository>(); IRepository repositoryPerson = repository.GetRepository>(); FamilyPersonEntity familyPerson; FamilyTreeChildrenMapViewEntity[] olds = repositoryMapView.Entities.Where(x => x.PersonId == personId).ToArray(); if (olds != null && olds.Length > 0) { foreach (FamilyTreeChildrenMapViewEntity old in olds) { familyPerson = repositoryPerson.DetachedEntities.Where(x => x.PersonId == old.PersonId).FirstOrDefault()!; if (familyPerson != null) { repositoryPerson.DeleteNow(familyPerson); } repositoryMap.DeleteNow(new FamilyTreeChildrenMapEntity() { TreeId = old.TreeId, PersonId = personId, ChildrenId = old.ChildrenId }); } } if (maps == null || maps.Length == 0) return; int i = 1; foreach (FamilyTreeChildrenMapViewEntity map in maps.OrderBy(x => x.Orderby).ToArray()) { familyPerson = repositoryPerson.DetachedEntities.Where(x => x.PersonId == map.PersonId && string.IsNullOrEmpty(x.TreeId)).FirstOrDefault()!; if (familyPerson != null) { familyPerson.TreeId = map.TreeId; repositoryPerson.Update(familyPerson); } repositoryMap.InsertNow(new FamilyTreeChildrenMapEntity() { TreeId = map.TreeId, PersonId = personId, SpouseId = map.SpouseId, ChildrenId = map.ChildrenId, RelationType = map.RelationType, Remark = map.Remark, Orderby = i++ }); } } private void Validate(FamilyTreeEntity d) { List sysTableSchemas = service.ServiceProvider.GetRequiredService().FindByTableName(FamilyTreeEntity.DB_NAME_FAMILY_TREE); ValidateHelper.ValidateString(d, sysTableSchemas.ToArray()); } [PermissionOperate(name: MasterPermissionPolicy.FamilyTree, operate: Operate.Update)] [UnitOfWork] public FamilyTreeData Update(FamilyTreeData data) { FamilyTreeEntity d = null; if (data.FamilyTree.TreeName != data.FamilyTree.OrgTreeName) { d = repository.DetachedEntities.Where(x => x.TreeName == data.FamilyTree.TreeName).FirstOrDefault(); if (d != null) { throw new ValidatedException("家族名称已存在."); } } d = repository.DetachedEntities.Where(x => x.TreeId == data.FamilyTree.TreeId).FirstOrDefault(); Validate(data.FamilyTree); var has = new FamilyTreePermissionHelper(service).HasPermission(d.TreeId, d.AncestorPersonId); if (!has) { throw new ValidatedException("您没有修改权限."); } ObjectCopyHelper.Copy(data.FamilyTree, d); repository.UpdateNow(d); var currentPerson = data.CurrentPerson != null ? data.CurrentPerson.FamilyPerson.PersonId : null; if (string.IsNullOrEmpty(currentPerson)) currentPerson = d.AncestorPersonId; if (data.CurrentPerson != null && data.CurrentPerson.FamilyTreeSpouseMaps != null && data.CurrentPerson.FamilyTreeSpouseMaps.Length > 0) data.CurrentPerson.FamilyTreeSpouseMaps.ToLookup(x => x.TreeId = d.TreeId); if (data.CurrentPerson != null && data.CurrentPerson.FamilyTreeChildrenMaps != null && data.CurrentPerson.FamilyTreeChildrenMaps.Length > 0) data.CurrentPerson.FamilyTreeChildrenMaps.ToLookup(x => x.TreeId = d.TreeId); SaveSpouseMaps(data.CurrentPerson.FamilyPerson.PersonId, data.CurrentPerson.FamilyTreeSpouseMaps); //SaveParentMaps(data.CurrentPerson.FamilyPerson.PersonId, data.CurrentPerson.FamilyTreeParentMaps); SaveSonMaps(data.CurrentPerson.FamilyPerson.PersonId, data.CurrentPerson.FamilyTreeChildrenMaps); return FindByCurrentPerson(data.FamilyTree.TreeId, currentPerson); } [PermissionOperate(name: MasterPermissionPolicy.FamilyTree, operate: Operate.Delete)] [UnitOfWork] public void Delete(string key) { var ent = repository.DetachedEntities.Where(x => x.TreeId == key).FirstOrDefault()!; if (ent == null) return; var has = new FamilyTreePermissionHelper(service).HasPermission(ent.TreeId, ent.AncestorPersonId); if(!has) { throw new ValidatedException("您没有删除权限."); } repository.DeleteNow(ent); IRepository repositoryPerson = repository.GetRepository>(); FamilyPersonEntity familyPerson; familyPerson = repositoryPerson.DetachedEntities.Where(x => x.PersonId == ent.AncestorPersonId).FirstOrDefault()!; if (familyPerson != null) { repositoryPerson.DeleteNow(familyPerson); } DeleteSpouses(ent.AncestorPersonId); DeleteChildrens(ent.AncestorPersonId); } private void DeleteSpouses(string personId) { IRepository repositoryMap = repository.GetRepository>(); FamilyTreeSpouseMapEntity[] olds = repositoryMap.Entities.Where(x => x.PersonId == personId).ToArray(); if (olds != null && olds.Length > 0) { repositoryMap.DeleteNow(olds); } } private void DeleteChildrens(string personId) { IRepository repositoryMap = repository.GetRepository>(); FamilyTreeChildrenMapEntity[] olds = repositoryMap.Entities.Where(x => x.PersonId == personId).ToArray(); if (olds != null && olds.Length > 0) { repositoryMap.DeleteNow(olds); } foreach (FamilyTreeChildrenMapEntity old in olds) { DeleteChildrens(old.ChildrenId); DeleteSpouses(old.ChildrenId); } } [PermissionOperate(name: MasterPermissionPolicy.FamilyTree, operate: Operate.Delete)] [UnitOfWork] public void Deletes(string[] keys) { foreach (string key in keys) { Delete(key); } } } }