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.Entity ;
using DS.WMS.Core.Sys.Entity ;
using DS.WMS.Core.Sys.Interface ;
using DS.WMS.Core.TaskInteraction.Dtos ;
using DS.WMS.Core.TaskInteraction.Interface ;
using Fasterflect ;
using Mapster ;
using Masuit.Tools.Systems ;
using Microsoft.Extensions.DependencyInjection ;
using SqlSugar ;
namespace DS.WMS.Core.Info.Method ;
/// <summary>
/// 往来单位服务
/// </summary>
public class ClientInfoService : ServiceBase , IClientInfoService
{
const TaskBaseTypeEnum INFO_CLIENT_TASK = TaskBaseTypeEnum . INFO_CLIENT_AUDIT ;
Lazy < IClientFlowInstanceService > flowService ;
Lazy < IAuditTaskService > taskService ;
private readonly ICommonService commonService ;
/// <summary>
/// 初始化
/// </summary>
/// <param name="serviceProvider"></param>
public ClientInfoService ( IServiceProvider serviceProvider ) : base ( serviceProvider )
{
flowService = new Lazy < IClientFlowInstanceService > ( serviceProvider . GetRequiredService < IClientFlowInstanceService > ( ) ) ;
taskService = new Lazy < IAuditTaskService > ( serviceProvider . GetRequiredService < IAuditTaskService > ( ) ) ;
commonService = serviceProvider . GetRequiredService < ICommonService > ( ) ;
TenantDb . QueryFilter . Clear < IOrgId > ( ) ;
TenantDb . QueryFilter . Clear < ISharedOrgId > ( ) ;
}
#region 审核
/// <summary>
/// 提交审核
/// </summary>
/// <param name="idModel"></param>
/// <returns></returns>
public async Task < DataResult > SubmitAuditAsync ( IdModel idModel )
{
var list = await TenantDb . Queryable < InfoClient > ( ) . 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 < InfoClientContact > ( ) . 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 < InfoClient > ( ) . 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 < InfoClient > ( ) . 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 ) ) ;
}
/// <summary>
/// 执行审核
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public async Task < DataResult > 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 = await flowService . Value . AuditAsync ( new FlowAuditInfo
{
AuditNote = request . Remark ,
Status = request . Result ,
Instance = item
} ) ;
if ( ! result . Succeeded )
return result ;
}
return DataResult . Success ;
}
/// <summary>
/// 撤销审核
/// </summary>
/// <param name="idModel"></param>
/// <returns></returns>
public async Task < DataResult > 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 < InfoClient > ( ) . 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 < InfoClient > ( ) . 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 ) ) ;
}
/// <summary>
/// 审核完成回调
/// </summary>
/// <param name="callback">回调信息</param>
/// <returns></returns>
public async Task < DataResult > 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
/// <summary>
/// 导入
/// </summary>
/// <param name="list"></param>
/// <returns></returns>
public async Task < DataResult > ImportAsync ( List < InfoClientModel > list )
{
long userId = long . Parse ( User . UserId ) ;
DateTime dtNow = DateTime . Now ;
TenantDb . QueryFilter . Clear < IOrgId > ( ) ;
TenantDb . QueryFilter . Clear < ISharedOrgId > ( ) ;
var clientNames1 = list . Select ( x = > x . ShortName ) . Distinct ( ) ;
var clientNames2 = list . Select ( x = > x . CNName ) . Distinct ( ) ;
var clients = await TenantDb . Queryable < InfoClient > ( ) . Where ( x = > clientNames1 . Contains ( x . ShortName ) | | clientNames2 . Contains ( x . Description ) )
. Select ( x = > new InfoClient
{
Id = x . Id ,
ShortName = x . ShortName ,
Description = x . Description ,
IsCustomer = x . IsCustomer ,
IsSupplier = x . IsSupplier
} ) . ToListAsync ( ) ;
var attrbutes = list . SelectMany ( x = > x . AttributeNames ) . Where ( x = > ! string . IsNullOrEmpty ( x ) ) . Distinct ( ) ;
var dicList = await Db . Queryable < SysDictData > ( ) . InnerJoin < SysDictType > ( ( d , t ) = > d . TypeId = = t . Id )
. Where ( ( d , t ) = > t . Code = = "infoclient-ArrclientTag" & & attrbutes . Contains ( d . Name ) )
. Select ( ( d , t ) = > new
{
d . Name ,
d . Value
} ) . ToListAsync ( ) ;
var saleNames = list . Select ( x = > x . Sale ) ;
var userNames = list . Select ( x = > x . Business )
. Union ( list . Select ( x = > x . OP ) )
. Union ( list . Select ( x = > x . CustomerService ) )
. Union ( saleNames )
. Where ( x = > ! string . IsNullOrEmpty ( x ) )
. Distinct ( ) ;
var users = await Db . Queryable < SysUser > ( ) . Where ( x = > userNames . Contains ( x . UserName ) ) . Select ( x = > new
{
x . Id ,
x . UserName ,
x . DefaultOrgId
} ) . ToListAsync ( ) ;
List < InfoClient > newClients = new ( list . Count ) ;
List < InfoClient > existClients = [ ] ;
foreach ( var model in list )
{
InfoClient ? client = clients . Find ( x = > x . ShortName = = model . ShortName & & x . Description = = model . CNName ) ;
if ( client ! = null )
{
client . IsSupplier = model . IsSupplier ;
existClients . Add ( client ) ;
continue ;
}
client = new ( )
{
Address = model . Address ,
AuditStatus = model . StatusText = = "认证" ? AuditStatusEnum . Approve : AuditStatusEnum . NoAudit ,
Status = model . StatusText = = "认证" ? 0 : 1 ,
CodeName = model . Code ,
Chief = model . LegalPerson ,
CreateBy = userId ,
CreateUserName = User . UserName ,
CreateTime = dtNow ,
Email = model . Email ,
EnFullName = model . ENName ,
EnShortName = model . ENName ,
Grade = model . Class ,
IsCustomer = model . IsCustomer ,
IsSupplier = model . IsSupplier ,
Country = model . Country ,
OperatorId = users . Find ( x = > x . UserName = = model . OP ) ? . Id ,
OperatorName = users . Find ( x = > x . UserName = = model . OP ) ? . UserName ,
OrgId = ( users . Find ( x = > x . UserName = = model . Sale ) ? . DefaultOrgId ) . GetValueOrDefault ( ) ,
SaleOrgId = users . Find ( x = > x . UserName = = model . Sale ) ? . DefaultOrgId . ToString ( ) ,
SaleId = users . Find ( x = > x . UserName = = model . Sale ) ? . Id ,
Sale = users . Find ( x = > x . UserName = = model . Sale ) ? . UserName ,
CustomerService = users . Find ( x = > x . UserName = = model . CustomerService ) ? . Id ,
CustomerServiceName = users . Find ( x = > x . UserName = = model . CustomerService ) ? . UserName ,
QQ = model . QQ ,
ShortName = model . ShortName ,
Description = model . CNName ,
Tel = model . Tel ,
IsOverdueDeduction = model . IsCustomer ,
IsMortgageLastOrder = model . IsCustomer ,
Note = "系统导入" ,
ClientTag = new InfoClientTag { IsController = model . IsCustomer } ,
AccountDates = [ ]
} ;
if ( model . AttributeNames . Length = = 0 )
{
client . ClientTag . IsOther = model . IsSupplier ;
}
else
{
var dicValues = dicList . FindAll ( x = > model . AttributeNames . Contains ( x . Name ) ) ;
foreach ( var item in dicValues )
{
var dicValue = item . Value . ToUpperCamelCase ( ) ;
PropertyExtensions . SetPropertyValue ( client . ClientTag , dicValue , true ) ;
}
}
client . AccountDates . Add ( new InfoClientAccountDate
{
AccountType = model . StlType ,
BusinessType = ( ( int ) BusinessType . OceanShippingExport ) . ToString ( ) ,
AllowAmount = model . Quota ,
OrgId = client . OrgId ,
CreateBy = userId ,
CreateUserName = User . UserName ,
CreateTime = dtNow ,
} ) ;
newClients . Add ( client ) ;
}
await TenantDb . Ado . BeginTranAsync ( ) ;
try
{
if ( existClients . Count > 0 )
await TenantDb . Updateable ( existClients ) . UpdateColumns ( x = > new { x . IsCustomer , x . IsSupplier } ) . ExecuteCommandAsync ( ) ;
await TenantDb . Fastest < InfoClient > ( ) . RemoveDataCache ( $"{SqlSugarCacheConst.InfoClient}{User.TenantId}" ) . BulkCopyAsync ( newClients ) ;
foreach ( var client in newClients )
{
client . ClientTag . ClientId = client . Id ;
foreach ( var item in client . AccountDates )
item . ClientId = client . Id ;
}
var tags = newClients . Select ( x = > x . ClientTag ) . ToList ( ) ;
await TenantDb . Fastest < InfoClientTag > ( ) . BulkMergeAsync ( tags ) ;
var accountDates = newClients . SelectMany ( x = > x . AccountDates ) . ToList ( ) ;
await TenantDb . Fastest < InfoClientAccountDate > ( ) . BulkMergeAsync ( accountDates ) ;
await TenantDb . Ado . CommitTranAsync ( ) ;
var result = DataResult . Success ;
result . Message = $"新增往来单位:{newClients.Count}项,更新往来单位:{existClients.Count}项" ;
return result ;
}
catch ( Exception ex )
{
await TenantDb . Ado . RollbackTranAsync ( ) ;
await ex . LogAsync ( Db ) ;
return DataResult . Failed ( "导入失败:" + ex . Message ) ;
}
}
/// <summary>
/// 导入并更新
/// </summary>
/// <param name="list"></param>
/// <returns></returns>
public async Task < DataResult > ImportUpdateAsync ( List < InfoClientModel > list )
{
TenantDb . QueryFilter . Clear < IOrgId > ( ) ;
TenantDb . QueryFilter . Clear < ISharedOrgId > ( ) ;
var clientNames1 = list . Select ( x = > x . ShortName ) . Distinct ( ) ;
var clientNames2 = list . Select ( x = > x . CNName ) . Distinct ( ) ;
var dbList = await TenantDb . Queryable < InfoClient > ( ) . Where ( x = > clientNames1 . Contains ( x . ShortName ) | | clientNames2 . Contains ( x . Description ) )
. Select ( x = > new InfoClient
{
Id = x . Id ,
ShortName = x . ShortName ,
Description = x . Description
} ) . ToListAsync ( ) ;
List < InfoClient > newclients = [ ] ;
List < InfoClient > existClients = new ( dbList . Count ) ;
foreach ( var item in list )
{
var client = dbList . Find ( x = > x . ShortName = = item . ShortName & & x . Description = = item . CNName ) ;
client ? ? = new InfoClient ( ) ;
client . RegisteredCapital = item . RegisteredCapital ;
client . RegistrationTime = item . RegistrationTime ;
if ( client . Id = = 0 )
{
newclients . Add ( client ) ;
}
else
{
existClients . Add ( client ) ;
}
}
await TenantDb . Ado . BeginTranAsync ( ) ;
try
{
await TenantDb . Fastest < InfoClient > ( ) . BulkUpdateAsync ( existClients , [ nameof ( InfoClient . Id ) ] ,
[nameof(InfoClient.RegisteredCapital), nameof(InfoClient.RegistrationTime)] ) ;
await TenantDb . Ado . CommitTranAsync ( ) ;
return DataResult . Success ;
}
catch ( Exception ex )
{
await TenantDb . Ado . RollbackTranAsync ( ) ;
await ex . LogAsync ( Db ) ;
return DataResult . Failed ( "导入失败:" + ex . Message ) ;
}
}
/// <summary>
/// 列表
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public async Task < DataResult < List < ClientInfoRes > > > GetListAsync ( PageRequest < ClientQuery > request )
{
//序列化查询条件
var whereList = request . GetConditionalModels ( Db ) ;
#region 数据权限
var queryData = TenantDb . Queryable < InfoClient > ( ) ;
var conditions = new List < IConditionalModel > ( ) ;
var otherConditions = new List < IConditionalModel > ( ) ;
var scope = string . Empty ;
( conditions , scope , otherConditions ) = await commonService . GetSpecialVisibleDataRuleFilter < InfoClient > ( queryData , TenantDb ) ;
var userids = new List < string > ( ) ;
if ( otherConditions . Count > 0 )
{
foreach ( ConditionalTree item in otherConditions )
{
if ( item . ConditionalList . Count > 0 )
{
foreach ( var item1 in item . ConditionalList )
{
var temp = item1 . Value as ConditionalModel ;
if ( temp . FieldName = = "Stakeholders" )
{
userids = temp . FieldValue . Split ( ',' ) . ToList ( ) ;
}
}
}
}
}
if ( userids . Count = = 0 )
{
userids . Add ( User . UserId ) ;
}
# endregion
//干系人合集
var exp = Expressionable . Create < InfoClient > ( ) ;
exp = exp . And ( c = > SqlFunc . Subqueryable < InfoClientStakeholder > ( ) . Where ( "SYSDATE() BETWEEN StartDate and EndDate" ) . Where ( x = > userids . Contains ( x . UserId . ToString ( ) ) & & x . ClientId = = c . Id ) . Any ( ) ) ;
var queryData1 = TenantDb . Queryable < InfoClient > ( ) . ClearFilter < ISharedOrgId > ( ) . Where ( exp . ToExpression ( ) ) ;
var queryData2 = queryData . Where ( conditions ) ;
var queryData0 = TenantDb . UnionAll ( queryData1 , queryData2 ) ;
var query = queryData0 //.Where(c => c.Status == StatusEnum.Enable.ToEnumInt())//TenantDb.Queryable<InfoClient>()
. LeftJoin < InfoClientContact > ( ( c , c1 ) = > c . Id = = c1 . ClientId )
. LeftJoin < InfoClientContract > ( ( c , c1 , c2 ) = > c . Id = = c2 . ClientId )
. InnerJoinIF < InfoClientTag > ( 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 < IConditionalModel > 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 ) ;
}
#region 判断权限范围
if ( scope = = "all" )
{
query = query . ClearFilter < ISharedOrgId > ( ) ;
}
# endregion
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 ( ) . Distinct ( ) . Where ( whereList ) . ToQueryPageAsync ( request . PageCondition ) ;
if ( result . Data ? . Count > 0 )
{
var ids = result . Data . Select ( x = > x . Id ) ;
var contacts = TenantDb . Queryable < InfoClientContact > ( ) . Where ( x = > ids . Contains ( x . ClientId ) & & x . IsDefault )
. Select < ClientContactRes > ( ) . ToList ( ) ;
var accountDates = TenantDb . Queryable < InfoClientAccountDate > ( ) . Where ( x = > ids . Contains ( x . ClientId ) & & x . Id = =
SqlFunc . Subqueryable < InfoClientAccountDate > ( ) . Where ( y = > y . Id = = x . Id ) . Select ( y = > SqlFunc . AggregateMax ( y . Id ) )
) . Select < ClientAccountDateRes > ( ) . ToList ( ) ;
var ids2 = result . Data . SelectMany ( x = > x . SaleOrgIdList ) . Distinct ( ) ;
var orgs = Db . Queryable < SysOrg > ( ) . 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 ;
}
/// <summary>
/// 列表
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public async Task < DataResult < List < ClientInfoRes > > > GetSupplierListAsync ( PageRequest < ClientQuery > request )
{
//序列化查询条件
var whereList = request . GetConditionalModels ( Db ) ;
var query = TenantDb . Queryable < InfoClient > ( )
. LeftJoin < InfoClientContact > ( ( c , c1 ) = > c . Id = = c1 . ClientId )
. LeftJoin < InfoClientContract > ( ( c , c1 , c2 ) = > c . Id = = c2 . ClientId )
. InnerJoinIF < InfoClientTag > ( 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 < IConditionalModel > 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 ) ;
}
//查询所有机构
query = query . ClearFilter < ISharedOrgId > ( ) ;
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 < InfoClientContact > ( ) . Where ( x = > ids . Contains ( x . ClientId ) & & x . IsDefault )
. Select < ClientContactRes > ( ) . ToList ( ) ;
var accountDates = TenantDb . Queryable < InfoClientAccountDate > ( ) . Where ( x = > ids . Contains ( x . ClientId ) & & x . Id = =
SqlFunc . Subqueryable < InfoClientAccountDate > ( ) . Where ( y = > y . Id = = x . Id ) . Select ( y = > SqlFunc . AggregateMax ( y . Id ) )
) . Select < ClientAccountDateRes > ( ) . ToList ( ) ;
var ids2 = result . Data . SelectMany ( x = > x . SaleOrgIdList ) . Distinct ( ) ;
var orgs = Db . Queryable < SysOrg > ( ) . 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 ;
}
/// <summary>
/// 确定往来单位是否已使用
/// </summary>
/// <param name="ids">往来单位ID</param>
/// <returns></returns>
public async Task < DataResult < List < ClientUsage > > > GetUsageAsync ( params long [ ] ids )
{
TenantDb . QueryFilter . Clear < ISharedOrgId > ( ) ;
var list = await TenantDb . Queryable < InfoClient > ( ) . Where ( x = > ids . Contains ( x . Id ) )
. Select ( c = > new ClientUsage
{
Id = c . Id ,
Name = c . ShortName ,
IsUsed = SqlFunc . Subqueryable < SeaExport > ( ) . 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 < FeeRecord > ( ) . Where ( f = > c . Id = = f . CustomerId ) . Any ( ) & &
SqlFunc . Subqueryable < CheckBill > ( ) . Where ( f = > c . Id = = f . CustomerId ) . Any ( ) & &
SqlFunc . Subqueryable < CheckBillAuto > ( ) . Where ( f = > c . Id = = f . CustomerId ) . Any ( )
} ) . ToListAsync ( ) ;
var result = DataResult < List < ClientUsage > > . Success ( list ) ;
result . Count = list . Count ;
return result ;
}
/// <summary>
/// 编辑
/// </summary>
/// <param name="req"></param>
/// <returns></returns>
public async Task < DataResult > EditAsync ( ClientInfoReq req )
{
var data = req . Adapt < InfoClient > ( ) ;
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 ) ;
var result = await IsAvailableAsync ( req ) ;
if ( ! result . Succeeded )
return result ;
if ( req . Id = = 0 )
{
var tag = req . ClientTag . Adapt < InfoClientTag > ( ) ;
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 < InfoClient > ( ) . ClearFilter < ISharedOrgId > ( ) . 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 < InfoClientTag > ( ) . Where ( x = > x . ClientId = = req . Id ) . First ( ) ;
tag = req . ClientTag . Adapt ( tag ) ;
data . ServiceItem ? ? = string . Empty ;
var updateable = TenantDb . Updateable ( data ) . RemoveDataCache ( $"{SqlSugarCacheConst.InfoClient}{User.TenantId}" )
. IgnoreColumns ( x = > new
{
x . OrgId ,
x . Status ,
x . ETD ,
x . AuditStatus ,
x . AuditNote ,
x . AuditTime ,
x . DeleteBy ,
x . Deleted ,
x . DeleteTime
} ) ;
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 ( x = > new
{
x . ClientId ,
x . OrgId ,
x . DeleteBy ,
x . Deleted ,
x . DeleteTime
} ) . ExecuteCommandAsync ( ) ;
return DataResult . Successed ( "更新成功!" , MultiLanguageConst . DataUpdateSuccess ) ;
}
}
/// <summary>
/// 检查客户信息是否重复
/// </summary>
/// <param name="req"></param>
/// <returns></returns>
public async Task < DataResult > IsAvailableAsync ( ClientInfoReq req )
{
req . ShortName = req . ShortName . Trim ( ) ;
req . Description = req . Description . Trim ( ) ;
TenantDb . QueryFilter . ClearAndBackup < IOrgId > ( ) ;
TenantDb . QueryFilter . ClearAndBackup < ISharedOrgId > ( ) ;
var expr = Expressionable . Create < InfoClient > ( )
. And ( x = > x . ShortName = = req . ShortName | | x . Description = = req . Description )
. AndIF ( req . Id > 0 , x = > x . Id ! = req . Id ) ;
var client = await TenantDb . Queryable < InfoClient > ( ) . Where ( expr . ToExpression ( ) ) . Select ( x = > new
{
ClientId = x . Id ,
x . ShortName ,
x . Description
} ) . FirstAsync ( ) ;
if ( client ! = null )
{
var result = DataResult . Failed ( "客户信息已存在,请检查客户全称/简称是否重复!" , MultiLanguageConst . ClientInfoExist ) ;
result . Code = ResultCode . Fail ;
result . Data = client ;
return result ;
}
TenantDb . QueryFilter . Restore ( ) ;
return DataResult . Success ;
}
/// <summary>
/// 详情
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public async Task < DataResult < ClientInfoRes > > GetAsync ( long id )
{
TenantDb . QueryFilter . Clear < ISharedOrgId > ( ) ;
var entity = await TenantDb . Queryable < InfoClient > ( ) . Where ( a = > a . Id = = id ) . FirstAsync ( ) ;
if ( entity = = null )
return DataResult < ClientInfoRes > . Success ( null ) ;
var data = entity . Adapt < ClientInfoRes > ( ) ;
data . ServiceItemCodes = entity . ServiceItem ? . Split ( ',' , StringSplitOptions . RemoveEmptyEntries ) ;
data . ClientTag = await TenantDb . Queryable < InfoClientTag > ( ) . Select < ClientTagRes > ( ) . FirstAsync ( a = > a . ClientId = = id ) ;
data . InvoiceHeaders ? ? = await TenantDb . Queryable < InvoiceHeader > ( ) . Where ( x = > x . RelativeId = = data . Id ) . ToListAsync ( ) ;
return DataResult < ClientInfoRes > . Success ( data , MultiLanguageConst . DataQuerySuccess ) ;
}
/// <summary>
/// 批量删除发票抬头
/// </summary>
/// <param name="idModel"></param>
/// <returns></returns>
public async Task < DataResult > DeleteInvoiceHeaderAsync ( IdModel idModel )
{
int rows = await TenantDb . Deleteable < InvoiceHeader > ( ) . Where ( x = > idModel . Ids . Contains ( x . Id ) ) . ExecuteCommandAsync ( ) ;
return rows > 0 ? DataResult . Success : DataResult . FailedWithDesc ( nameof ( MultiLanguageConst . Operation_Failed ) ) ;
}
/// <summary>
/// 批量删除
/// </summary>
/// <param name="req"></param>
/// <returns></returns>
public async Task < DataResult > 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 < InfoClientBank > ( ) . Where ( x = > req . Ids . Contains ( x . ClientId ) ) . ExecuteCommandAsync ( ) ;
//联系人
await TenantDb . Deleteable < InfoClientContact > ( ) . Where ( x = > req . Ids . Contains ( x . ClientId ) ) . ExecuteCommandAsync ( ) ;
//合同信息
await TenantDb . Deleteable < InfoClientContract > ( ) . Where ( x = > req . Ids . Contains ( x . ClientId ) ) . ExecuteCommandAsync ( ) ;
//账期
await TenantDb . Deleteable < InfoClientAccountDate > ( ) . Where ( x = > req . Ids . Contains ( x . ClientId ) ) . ExecuteCommandAsync ( ) ;
//收发货人
await TenantDb . Deleteable < InfoClientShipper > ( ) . Where ( x = > req . Ids . Contains ( x . ClientId ) ) . ExecuteCommandAsync ( ) ;
//删除客户信息
await TenantDb . Deleteable < InfoClient > ( ) . 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 获取往来单位详情(含有联系人列表)
/// <summary>
/// 获取往来单位详情(含有联系人列表)
/// </summary>
/// <param name="query">查询往来单位</param>
/// <returns>返回往来单位详情</returns>
public async Task < DataResult < ClientInfoRes > > GetClientInfoWithContact ( QueryClientInfo query )
{
var data = await TenantDb . Queryable < InfoClient > ( ) . InnerJoin < InfoClientTag > ( ( c , t ) = > c . Id = = t . ClientId )
. Where ( ( c , t ) = > c . Id = = query . ClientId )
. WhereIF ( query . IsController , ( c , t ) = > t . IsController )
. WhereIF ( query . IsCarrier , ( c , t ) = > t . IsCarrier )
. WhereIF ( query . IsBooking , ( c , t ) = > t . IsBooking )
. WhereIF ( query . IsYard , ( c , t ) = > t . IsYard )
. WhereIF ( query . IsTruck , ( c , t ) = > t . IsTruck )
. WhereIF ( query . IsCustom , ( c , t ) = > t . IsCustom )
. WhereIF ( query . IsAgent , ( c , t ) = > t . IsAgent )
. WhereIF ( query . IsAgentCn , ( c , t ) = > t . IsAgentCn )
. WhereIF ( query . IsExpress , ( c , t ) = > t . IsExpress )
. WhereIF ( query . IsAirLines , ( c , t ) = > t . IsAirLines )
. WhereIF ( query . IsShipper , ( c , t ) = > t . IsShipper )
. WhereIF ( query . IsConsignee , ( c , t ) = > t . IsConsignee )
. WhereIF ( query . IsNotifyParty , ( c , t ) = > t . IsNotifyParty )
. WhereIF ( query . IsWareHouse , ( c , t ) = > t . IsWareHouse )
. WhereIF ( query . IsWharf , ( c , t ) = > t . IsWharf )
. WhereIF ( query . IsInsurer , ( c , t ) = > t . IsInsurer )
. WhereIF ( query . IsLeasing , ( c , t ) = > t . IsLeasing )
. WhereIF ( query . IsTradingAgency , ( c , t ) = > t . IsTradingAgency )
. WhereIF ( query . IsOther , ( c , t ) = > t . IsOther )
. WhereIF ( ! string . IsNullOrWhiteSpace ( query . Others ) , ( c , t ) = > t . Others = = query . Others )
. WhereIF ( query . IsShipAgency , ( c , t ) = > t . IsShipAgency )
. WhereIF ( query . IsEnterprise , ( c , t ) = > t . IsEnterprise )
. Select ( ( c , t ) = > new { Client = c , tag = t } )
. FirstAsync ( ) ;
var clientInfo = data . Client . Adapt < ClientInfoRes > ( ) ;
clientInfo . ClientTag = data . tag . Adapt < ClientTagRes > ( ) ;
var contactList = TenantDb . Queryable < InfoClientContact > ( )
. Where ( a = > a . ClientId = = clientInfo . Id & & a . Status = = StatusEnum . Enable ) . ToList ( ) ;
if ( contactList . Count > 0 )
clientInfo . ClientContactList = contactList . Adapt < List < ClientContactRes > > ( ) ;
if ( clientInfo = = null )
return DataResult < ClientInfoRes > . FailedData ( clientInfo ) ;
return DataResult < ClientInfoRes > . Success ( clientInfo ) ;
}
# endregion
}