using DS.Module.Core; using DS.Module.Core.Constants; using DS.Module.Core.Data; using DS.Module.Core.Extensions; using DS.WMS.Core.Check.Entity; using DS.WMS.Core.Fee.Dtos; using DS.WMS.Core.Fee.Entity; using DS.WMS.Core.Flow.Dtos; using DS.WMS.Core.Flow.Entity; using DS.WMS.Core.Flow.Interface; using DS.WMS.Core.Info.Dtos; using DS.WMS.Core.Info.Entity; using DS.WMS.Core.Info.Interface; using DS.WMS.Core.Op.Dtos.TaskInteraction; using DS.WMS.Core.Op.Entity; using DS.WMS.Core.Op.Interface.TaskInteraction; using DS.WMS.Core.Sys.Entity; using Fasterflect; using Mapster; using Masuit.Tools.Systems; using Microsoft.Extensions.DependencyInjection; using SqlSugar; namespace DS.WMS.Core.Info.Method; /// /// 往来单位服务 /// public class ClientInfoService : ServiceBase, IClientInfoService { const TaskBaseTypeEnum INFO_CLIENT_TASK = TaskBaseTypeEnum.INFO_CLIENT_AUDIT; Lazy flowService; Lazy taskService; /// /// 初始化 /// /// public ClientInfoService(IServiceProvider serviceProvider) : base(serviceProvider) { flowService = new Lazy(serviceProvider.GetRequiredService()); taskService = new Lazy(serviceProvider.GetRequiredService()); } #region 审核 /// /// 提交审核 /// /// /// public async Task SubmitAuditAsync(IdModel idModel) { var list = await TenantDb.Queryable().Where(x => idModel.Ids.Contains(x.Id)).Select(x => new { x.Id, x.AuditStatus, x.CodeName, x.ShortName, x.EnShortName }).ToListAsync(); if (list.Exists(x => x.AuditStatus == AuditStatusEnum.Auditing)) return DataResult.FailedWithDesc(nameof(MultiLanguageConst.ItemsAreAuditing)); var queryable = TenantDb.Queryable().Where(x => idModel.Ids.Contains(x.ClientId)); if (await queryable.AnyAsync(x => (SqlFunc.IsNullOrEmpty(x.Tel) && SqlFunc.IsNullOrEmpty(x.Mobile)) || (SqlFunc.IsNullOrEmpty(x.Email) && SqlFunc.IsNullOrEmpty(x.QQ)))) return DataResult.FailedWithDesc(nameof(MultiLanguageConst.ClientInfoIncomplete)); if (await taskService.Value.HasAuthorizedAsync()) { var requests = list.Select(x => new TaskCreationRequest { BusinessId = x.Id, TaskTypeName = INFO_CLIENT_TASK.ToString(), TaskTitle = $"【{INFO_CLIENT_TASK.GetDescription()}】{x.CodeName} {x.ShortName}" }); await TenantDb.Ado.BeginTranAsync(); try { DataResult result; foreach (var request in requests) { result = await taskService.Value.CreateTaskAsync(request, false); if (!result.Succeeded) return result; } await TenantDb.Updateable().Where(x => idModel.Ids.Contains(x.Id)) .SetColumns(x => x.AuditStatus == AuditStatusEnum.Auditing).ExecuteCommandAsync(); await TenantDb.Ado.CommitTranAsync(); return DataResult.Success; } catch (Exception ex) { await TenantDb.Ado.RollbackTranAsync(); await ex.LogAsync(Db); return DataResult.FailedWithDesc(nameof(MultiLanguageConst.Operation_Failed)); } } var template = await FindTemplateAsync(INFO_CLIENT_TASK); if (template == null) return DataResult.FailedWithDesc(nameof(MultiLanguageConst.TemplateNotFound)); for (int i = 0; i < idModel.Ids.Length; i++) { var id = idModel.Ids[i]; var result = flowService.Value.CreateFlowInstance(new CreateFlowInstanceReq { BusinessId = id, TemplateId = template.Id }); if (!result.Succeeded || result.Data is not FlowInstance instance) return result; result = flowService.Value.StartFlowInstance(instance.Id.ToString()); if (!result.Succeeded) return result; } var rows = await TenantDb.Updateable().Where(x => idModel.Ids.Contains(x.Id)) .SetColumns(x => x.AuditStatus == AuditStatusEnum.Auditing).ExecuteCommandAsync(); return rows > 0 ? DataResult.Success : DataResult.FailedWithDesc(nameof(MultiLanguageConst.Operation_Failed)); } /// /// 执行审核 /// /// /// public async Task AuditAsync(AuditRequest request) { if (await taskService.Value.HasAuthorizedAsync()) { return await taskService.Value.AuditAsync(new TaskAuditRequest { Ids = request.Ids, Remark = request.Remark, Result = request.Result, TaskTypeName = INFO_CLIENT_TASK.ToString() }); } var list = await flowService.Value.GetInstanceByBSIdAsync(INFO_CLIENT_TASK, ids: request.Ids); if (list.Count != request.Ids.Length) return DataResult.FailedWithDesc(nameof(MultiLanguageConst.NotInAudit)); foreach (var item in list) { var result = flowService.Value.AuditFlowInstance(new FlowAuditInfo { AuditNote = request.Remark, Status = request.Result, Instance = item }); if (!result.Succeeded) return result; } return DataResult.Success; } /// /// 撤销审核 /// /// /// public async Task WithdrawAsync(IdModel idModel) { DataResult result; if (await taskService.Value.HasAuthorizedAsync()) { await TenantDb.Ado.BeginTranAsync(); try { for (int i = 0; i < idModel.Ids.Length; i++) { result = await taskService.Value.WithdrawAsync(new TaskRequest { BusinessId = idModel.Ids[i], TaskTypeName = INFO_CLIENT_TASK.ToString() }, false); if (!result.Succeeded) { return result; } } await TenantDb.Updateable().Where(x => idModel.Ids.Contains(x.Id)) .SetColumns(x => x.AuditStatus == AuditStatusEnum.NoAudit) .SetColumns(x => x.AuditTime == null) .SetColumns(x => x.AuditNote == null) .ExecuteCommandAsync(); await TenantDb.Ado.CommitTranAsync(); return DataResult.Success; } catch { await TenantDb.Ado.RollbackTranAsync(); return DataResult.FailedWithDesc(nameof(MultiLanguageConst.Operation_Failed)); } } var list = await flowService.Value.GetInstanceByBSIdAsync(INFO_CLIENT_TASK, ids: idModel.Ids); if (list.Count != idModel.Ids.Length) return DataResult.FailedWithDesc(nameof(MultiLanguageConst.NotInAudit)); result = await flowService.Value.WithdrawAsync(idModel.Ids); if (!result.Succeeded) return result; int rows = await TenantDb.Updateable().Where(x => idModel.Ids.Contains(x.Id)) .SetColumns(x => x.AuditStatus == AuditStatusEnum.NoAudit).ExecuteCommandAsync(); return rows > 0 ? DataResult.Success : DataResult.FailedWithDesc(nameof(MultiLanguageConst.Operation_Failed)); } /// /// 审核完成回调 /// /// 回调信息 /// public async Task AuditCallbackAsync(FlowCallback callback) { if (callback.AuditType != INFO_CLIENT_TASK) return DataResult.FailedWithDesc(nameof(MultiLanguageConst.NoAuditItems)); InfoClient infoClient = new() { Id = callback.BusinessId, AuditNote = callback.RejectReason, AuditTime = DateTime.Now, AuditStatus = callback.FlowStatus == FlowStatusEnum.Approve ? AuditStatusEnum.Approve : AuditStatusEnum.Reject, Status = callback.FlowStatus == FlowStatusEnum.Approve ? 0 : 1 }; int rows = await TenantDb.Updateable(infoClient).UpdateColumns(x => new { x.AuditNote, x.AuditTime, x.AuditStatus, x.Status }).ExecuteCommandAsync(); return rows > 0 ? DataResult.Success : DataResult.FailedWithDesc(nameof(MultiLanguageConst.Operation_Failed)); } #endregion /// /// 列表 /// /// /// public async Task>> GetListAsync(PageRequest request) { //序列化查询条件 var whereList = request.GetConditionalModels(Db); var query = TenantDb.Queryable() .LeftJoin((c, c1) => c.Id == c1.ClientId) .LeftJoin((c, c1, c2) => c.Id == c2.ClientId) .InnerJoinIF(request.OtherQueryCondition?.ClientTag != null, (c, c1, c2, ct) => c.Id == ct.ClientId) .GroupBy((c, c1, c2) => c.Id); if (!string.IsNullOrEmpty(request.OtherQueryCondition?.ContactInfo)) query = query.Where((c, c1, c2) => c1.Tel.Contains(request.OtherQueryCondition.ContactInfo) || c1.Mobile.Contains(request.OtherQueryCondition.ContactInfo) || c1.Email.Contains(request.OtherQueryCondition.ContactInfo)); if (request.OtherQueryCondition != null && request.OtherQueryCondition.IsContractExpired.GetValueOrDefault()) query = query.Where((c, c1, c2) => SqlFunc.GetDate() > c2.EndDate); if (request.OtherQueryCondition?.ClientTag != null) { //合并到主查询条件 var props = Array.FindAll(request.OtherQueryCondition.ClientTag.GetType().GetProperties(), x => x.Name.StartsWith("Is") && x.PropertyType == typeof(bool)); List list = []; foreach (var prop in props) { object val = prop.Get(request.OtherQueryCondition.ClientTag); if (val != null && val is bool value && value) { list.Add(new ConditionalModel { ConditionalType = ConditionalType.Equal, FieldName = "ct." + prop.Name, FieldValue = "1" }); } } query = query.Where(list); } var result = await query.Select((c, c1, c2, ct) => new ClientInfoRes { CodeName = c.CodeName, Name = c.Name, ShortName = c.ShortName, EnShortName = c.EnShortName, EnFullName = c.EnFullName }, true).MergeTable().Where(whereList).ToQueryPageAsync(request.PageCondition); if (result.Data?.Count > 0) { var ids = result.Data.Select(x => x.Id); var contacts = TenantDb.Queryable().Where(x => ids.Contains(x.ClientId) && x.IsDefault) .Select().ToList(); var accountDates = TenantDb.Queryable().Where(x => ids.Contains(x.ClientId) && x.Id == SqlFunc.Subqueryable().Where(y => y.Id == x.Id).Select(y => SqlFunc.AggregateMax(y.Id)) ).Select().ToList(); var ids2 = result.Data.SelectMany(x => x.SaleOrgIdList).Distinct(); var orgs = Db.Queryable().Where(x => ids2.Contains(x.Id)).Select(x => new { x.Id, x.OrgName }).ToList(); foreach (var item in result.Data) { item.DefaultContact = contacts.Find(x => x.ClientId == item.Id); item.LastAccountDate = accountDates.Find(x => x.ClientId == item.Id); var list = orgs.FindAll(x => item.SaleOrgIdList.Contains(x.Id)); item.SaleOrgNames = string.Join(",", list.Select(x => x.OrgName)); } } return result; } /// /// 确定往来单位是否已使用 /// /// 往来单位ID /// public async Task>> GetUsageAsync(params long[] ids) { var list = await TenantDb.Queryable().Where(x => ids.Contains(x.Id)) .Select(c => new ClientUsage { Id = c.Id, Name = c.ShortName, IsUsed = SqlFunc.Subqueryable().Where(s => c.Id == s.CustomerId || c.Id == s.ForwarderId || c.Id == s.YardId || c.Id == s.ShipperCnId || c.Id == s.ContractClientId || c.Id == s.TruckerId || c.Id == s.AgentId || c.Id == s.ShipAgencyId || c.Id == s.CustomserId || c.Id == s.WareHouseId).Any() && SqlFunc.Subqueryable().Where(f => c.Id == f.CustomerId).Any() && SqlFunc.Subqueryable().Where(f => c.Id == f.CustomerId).Any() && SqlFunc.Subqueryable().Where(f => c.Id == f.CustomerId).Any() }).ToListAsync(); var result = DataResult>.Success(list); result.Count = list.Count; return result; } /// /// 编辑 /// /// /// public async Task EditAsync(ClientInfoReq req) { var data = req.Adapt(); data.Status = (int)StatusEnum.Disable; data.AuditStatus = AuditStatusEnum.NoAudit; data.OrgId = User.OrgId; if (string.IsNullOrEmpty(data.CodeName)) data.CodeName = PinYinUtil.GetFristLetter(data.ShortName); //助记码 if (req.ServiceItemCodes?.Length > 0) data.ServiceItem = string.Join(",", req.ServiceItemCodes); if (req.Id == 0) { if (TenantDb.Queryable().Where(x => (x.ShortName == req.ShortName.Trim() || x.Description == req.Description.Trim() || x.TaxNo == req.TaxNo.Trim())).Any()) return DataResult.Failed("客户信息已存在,请检查客户全称、简称或社会信用代码是否重复!", MultiLanguageConst.ClientInfoExist); var tag = req.ClientTag.Adapt(); var entity = await TenantDb.Insertable(data).ExecuteReturnEntityAsync(); tag.ClientId = entity.Id; await TenantDb.Insertable(tag).RemoveDataCache($"{SqlSugarCacheConst.InfoClient}{User.TenantId}").ExecuteCommandAsync(); return DataResult.Successed("添加成功!", entity.Id, MultiLanguageConst.DataCreateSuccess); } else { var model = await TenantDb.Queryable().Where(x => x.Id == req.Id).Select(x => new { x.Status, x.AuditStatus }).FirstAsync(); if (model != null && model.AuditStatus == AuditStatusEnum.Auditing) return DataResult.FailedWithDesc(nameof(MultiLanguageConst.ItemsAreAuditing)); var tag = TenantDb.Queryable().Where(x => x.ClientId == req.Id).First(); if (TenantDb.Queryable().Where(x => x.Id != data.Id && (x.ShortName == req.ShortName.Trim() || x.Description == req.Description.Trim() || x.TaxNo == req.TaxNo.Trim())).Any()) return DataResult.Failed("请检查客户全称、简称或社会信用代码是否重复!", MultiLanguageConst.ClientInfoExist); tag = req.ClientTag.Adapt(tag); data.ServiceItem = data.ServiceItem ?? string.Empty; var updateable = TenantDb.Updateable(data).RemoveDataCache($"{SqlSugarCacheConst.InfoClient}{User.TenantId}") .IgnoreColumns(ignoreAllNullColumns: true) .IgnoreColumns(x => new { x.Status, x.AuditStatus, x.AuditNote, x.AuditTime }); var list = (await GetUsageAsync(req.Id))?.Data; if (list != null && list.Exists(x => x.Id == req.Id && x.IsUsed)) updateable = updateable.IgnoreColumns(x => x.ShortName); await updateable.ExecuteCommandAsync(); await TenantDb.Updateable(tag).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync(); return DataResult.Successed("更新成功!", MultiLanguageConst.DataUpdateSuccess); } } /// /// 详情 /// /// /// public async Task> GetAsync(string id) { var entity = await TenantDb.Queryable() .Where(a => a.Id == long.Parse(id)) .FirstAsync(); if (entity == null) return DataResult.Success(null); var data = entity.Adapt(); data.ServiceItemCodes = entity.ServiceItem?.Split(',', StringSplitOptions.RemoveEmptyEntries); var tag = await TenantDb.Queryable().Select() .FirstAsync(a => a.ClientId == long.Parse(id)); data.ClientTag = tag; data.InvoiceHeaders ??= await TenantDb.Queryable().Where(x => x.RelativeId == data.Id).ToListAsync(); return DataResult.Success(data, MultiLanguageConst.DataQuerySuccess); } /// /// 批量删除发票抬头 /// /// /// public async Task DeleteInvoiceHeaderAsync(IdModel idModel) { int rows = await TenantDb.Deleteable().Where(x => idModel.Ids.Contains(x.Id)).ExecuteCommandAsync(); return rows > 0 ? DataResult.Success : DataResult.FailedWithDesc(nameof(MultiLanguageConst.Operation_Failed)); } /// /// 批量删除 /// /// /// public async Task DeleteAsync(IdModel req) { await TenantDb.Ado.BeginTranAsync(); try { var result = await GetUsageAsync(req.Ids); if (result.Data != null && result.Data.Exists(x => x.IsUsed)) return DataResult.FailedWithDesc(MultiLanguageConst.ClientIsUsed); //银行信息 await TenantDb.Deleteable().Where(x => req.Ids.Contains(x.ClientId)).ExecuteCommandAsync(); //联系人 await TenantDb.Deleteable().Where(x => req.Ids.Contains(x.ClientId)).ExecuteCommandAsync(); //合同信息 await TenantDb.Deleteable().Where(x => req.Ids.Contains(x.ClientId)).ExecuteCommandAsync(); //账期 await TenantDb.Deleteable().Where(x => req.Ids.Contains(x.ClientId)).ExecuteCommandAsync(); //收发货人 await TenantDb.Deleteable().Where(x => req.Ids.Contains(x.ClientId)).ExecuteCommandAsync(); //删除客户信息 await TenantDb.Deleteable().RemoveDataCache($"{SqlSugarCacheConst.InfoClient}{User.TenantId}").Where(x => req.Ids.Contains(x.Id)).ExecuteCommandAsync(); await TenantDb.Ado.CommitTranAsync(); return DataResult.Success; } catch (Exception ex) { await TenantDb.Ado.RollbackTranAsync(); await ex.LogAsync(Db); return DataResult.FailedWithDesc(nameof(MultiLanguageConst.Operation_Failed)); } } #region 获取往来单位详情(含有联系人列表) /// /// 获取往来单位详情(含有联系人列表) /// /// 查询往来单位 /// 返回往来单位详情 public async Task> GetClientInfoWithContact(QueryClientInfo query) { var data = await TenantDb.Queryable().InnerJoin((c, t) => c.Id == t.ClientId) .Where((c, t) => c.Id == query.ClientId) .WhereIF(query.IsController, (c, t) => t.IsController.HasValue && t.IsController.HasValue) .WhereIF(query.IsCarrier, (c, t) => t.IsCarrier.HasValue && t.IsCarrier.HasValue) .WhereIF(query.IsBooking, (c, t) => t.IsBooking.HasValue && t.IsBooking.HasValue) .WhereIF(query.IsYard, (c, t) => t.IsYard.HasValue && t.IsYard.HasValue) .WhereIF(query.IsTruck, (c, t) => t.IsTruck.HasValue && t.IsTruck.HasValue) .WhereIF(query.IsController, (c, t) => t.IsController.HasValue && t.IsController.HasValue) .WhereIF(query.IsCustom, (c, t) => t.IsCustom.HasValue && t.IsCustom.HasValue) .WhereIF(query.IsAgent, (c, t) => t.IsAgent.HasValue && t.IsAgent.HasValue) .WhereIF(query.IsAgentCn, (c, t) => t.IsAgentCn.HasValue && t.IsAgentCn.HasValue) .WhereIF(query.IsExpress, (c, t) => t.IsExpress.HasValue && t.IsExpress.HasValue) .WhereIF(query.IsAirLines, (c, t) => t.IsAirLines.HasValue && t.IsAirLines.HasValue) .WhereIF(query.IsShipper, (c, t) => t.IsShipper.HasValue && t.IsShipper.HasValue) .WhereIF(query.IsConsignee, (c, t) => t.IsConsignee.HasValue && t.IsConsignee.HasValue) .WhereIF(query.IsNotifyParty, (c, t) => t.IsNotifyParty.HasValue && t.IsNotifyParty.HasValue) .WhereIF(query.IsWareHouse, (c, t) => t.IsWareHouse.HasValue && t.IsWareHouse.HasValue) .WhereIF(query.IsWharf, (c, t) => t.IsWharf.HasValue && t.IsWharf.HasValue) .WhereIF(query.IsInsurer, (c, t) => t.IsInsurer.HasValue && t.IsInsurer.HasValue) .WhereIF(query.IsLeasing, (c, t) => t.IsLeasing.HasValue && t.IsLeasing.HasValue) .WhereIF(query.IsTradingAgency, (c, t) => t.IsTradingAgency.HasValue && t.IsTradingAgency.HasValue) .WhereIF(query.IsOther, (c, t) => t.IsOther.HasValue && t.IsOther.HasValue) .WhereIF(!string.IsNullOrWhiteSpace(query.Others), (c, t) => t.Others == query.Others) .WhereIF(query.IsShipAgency, (c, t) => t.IsShipAgency.HasValue && t.IsShipAgency.HasValue) .WhereIF(query.IsEnterprise, (c, t) => t.IsEnterprise.HasValue && t.IsEnterprise.HasValue) .Select((c, t) => new { Client = c, tag = t }) .FirstAsync(); var clientInfo = data.Client.Adapt(); clientInfo.ClientTag = data.tag.Adapt(); var contactList = TenantDb.Queryable() .Where(a => a.ClientId == clientInfo.Id && a.Status == StatusEnum.Enable).ToList(); if (contactList.Count > 0) clientInfo.ClientContactList = contactList.Adapt>(); if (clientInfo == null) return DataResult.FailedData(clientInfo); return DataResult.Success(clientInfo); } #endregion }