Files
zszq-trs/YLErpDAL/Modules/ClientModule/ClientSaveApiV2Service.cs
T
2024-05-09 14:06:26 +08:00

778 lines
30 KiB
C#

using Newtonsoft.Json.Linq;
using Org.BouncyCastle.Ocsp;
using System.Text.Json;
using System.Text.Json.Nodes;
using YieldChain.Helpers;
using YLErp.DBModels;
using YLErp.Model.Enum;
using YLErp.Models;
using YLErp.Modules.SystemModule;
namespace YLErp.Modules.ClientModule
{
/// <summary>
/// 保存客户信息
/// </summary>
public class ClientSaveApiV2Service : ClientBaseService
{
const string ConsKey_Action = "_action";
const string ConsKey_Duties = "duties";
const string ConsKey_Bankcards = "bankcards";
const string ConsKey_Files = "files";
public ClientSaveApiV2Service(OptUserInfo userInfo) : base(userInfo)
{
}
/// <summary>
/// 保存客户信息
/// </summary>
public ClientSaveApiV2Result Save(Dictionary<string, object> dic)
{
if (dic is null)
{
throw new ServiceException("缺少输入参数");
}
var result = new ClientSaveApiV2Result();
var dicData = new DicData(dic);
var duties = dicData.GetSubDics(ConsKey_Duties);
var bankcards = dicData.GetSubDics(ConsKey_Bankcards);
var files = dicData.GetSubDics(ConsKey_Files);
using var dbTrans = DbContext.Database.BeginTransaction();
var dbClient = SaveClient(dicData, out var isNew, out var resultMessage);
var innerClient = new InnerClient
{
IsNew = isNew,
ClientId = dbClient.id
};
//保存客户联系人
if (duties != null && duties.Any())
{
result.DutyResults = SaveClientDuties(innerClient, duties);
}
//保存客户银行账号
if (bankcards != null && bankcards.Any())
{
result.BankcardResults = SaveClientBankcards(innerClient, bankcards);
}
//保存客户文件
if (files != null && files.Any())
{
result.FileResults = SaveClientFiles(innerClient, files);
}
dbTrans.Commit();
result.ClientId = dbClient.id;
result.ClientNumber = dbClient.Number;
result.ResultMessage = resultMessage;
return result;
}
//保存客户信息
private Client SaveClient(DicData dicData, out bool isNew, out string resultMessage)
{
Client client = null;
switch (dicData.Action)
{
case ActionType.create:
client = new Client();
break;
case ActionType.update:
{
isNew = false;
var clientNumber = dicData.GetStringValue(nameof(client.Number));
if (string.IsNullOrEmpty(clientNumber))
{
throw new ServiceException("客户编号 必须填写");
}
client = DbContext.client.AsNoTracking().FirstOrDefault(n => n.Number == clientNumber);
if (client == null)
{
throw new ServiceException("要更新的客户信息不存在,客户编号:" + clientNumber);
}
}
break;
case ActionType.updateOrCreate:
{
var clientNumber = dicData.GetStringValue(nameof(client.Number));
if (!string.IsNullOrEmpty(clientNumber))
{
client = DbContext.client.AsNoTracking().FirstOrDefault(n => n.Number == clientNumber);
}
client ??= new Client();
}
break;
case ActionType.delete:
throw new ServiceException("不支持删除客户信息");
}
isNew = client.id == 0;
dicData.MapToClient(client, out var upset);
if (isNew || upset.Count > 0)
{
resultMessage = isNew ? "客户新增成功" : "客户更新成功";
CheckClientModel(client);
return new ClientSaveService(this).SaveData(client, upset, out bool blAudit);
}
resultMessage = string.Empty;
return client;
}
#region----保存客户联系人----
private List<ClientDutySaveApiV2Result> SaveClientDuties(InnerClient client, IEnumerable<IDictionary<string, object>> dutyDics)
{
var dbContactTypeList = new Lazy<contactype[]>(() =>
{
return DbContext.contactype.AsNoTracking().ToArray();
});
var seq = 0;
var resultList = new List<ClientDutySaveApiV2Result>(dutyDics.Count());
foreach (var dic in dutyDics)
{
seq++;
if (dic == null)
{
continue;
}
var dicData = new DicData(dic, client.IsNew);
var idCardNo = dicData.GetStringValue(nameof(ClientDuty.IdCardNo));
if (string.IsNullOrWhiteSpace(idCardNo))
{
throw new ServiceException($"创建、更新或删除客户人员信息时,证件号码不能为空,索引:第{seq}条");
}
if (dicData.Action == ActionType.delete)
{
var dbDuty = DbContext.clientduty.FirstOrDefault(n => n.ApprovalOrder < 1 && n.ClientId == client.ClientId && n.IdCardNo == idCardNo);
if (dbDuty != null)
{
new ClientDutyService(this).RemoveClientDuty(dbDuty.id);
}
resultList.Add(new ClientDutySaveApiV2Result
{
IdCardNo = idCardNo,
ResultMessage = dbDuty == null ? "要删除的客户人员信息不存在" : "客户人员信息删除成功"
});
}
else
{
var result = SaveClientDuty(client: client, dicData: dicData, idCardNo: idCardNo, seq: seq, dbContactTypeList: dbContactTypeList);
resultList.Add(result);
}
}
return resultList;
}
private ClientDutySaveApiV2Result SaveClientDuty(InnerClient client, DicData dicData, string idCardNo, int seq, Lazy<contactype[]> dbContactTypeList)
{
ClientDuty clientDuty;
var predicate = PredicateBuilder.Create<ClientDuty>(n => n.ApprovalOrder < 1 && n.ClientId == client.ClientId && n.IdCardNo == idCardNo);
switch (dicData.Action)
{
case ActionType.create:
clientDuty = new ClientDuty();
if (!client.IsNew && DbContext.clientduty.Any(predicate))
{
throw new ServiceException($"新增客户人员信息时,与已有客户人员的证件号码重复,证件号码:{idCardNo},索引:第{seq}条");
}
break;
case ActionType.update:
if (client.IsNew)
{
throw new ServiceException("新增客户时,客户人员信息不支持更新");
}
else
{
clientDuty = DbContext.clientduty.AsNoTracking().FirstOrDefault(predicate)
?? throw new ServiceException($"要更新的客户人员信息不存在,证件号码:{idCardNo},索引:第{seq}条");
}
break;
case ActionType.updateOrCreate:
clientDuty = client.IsNew
? new ClientDuty()
: DbContext.clientduty.AsNoTracking().FirstOrDefault(predicate) ?? new ClientDuty();
break;
default: throw new ServiceException("[客户人员信息]不支持此操作:" + dicData.Action);
}
var isNew = clientDuty.id == 0;
// 保存数据时联系人类型必填
var contactType1 = dicData.GetStringValue(nameof(clientDuty.ContactType));
if (isNew ? string.IsNullOrEmpty(contactType1) : contactType1 == string.Empty)
{
throw new ServiceException($"保存客户时,联系人类型不能为空,证件号码:{idCardNo},索引:第{seq}条");
}
// 保存数据时联系人名称必填
var contactName1 = dicData.GetStringValue(nameof(clientDuty.ContactName));
if (isNew ? string.IsNullOrEmpty(contactName1) : contactName1 == string.Empty)
{
throw new ServiceException($"保存客户时,联系人名称不能为空,证件号码:{idCardNo},索引:第{seq}条");
}
//职责类型
var contactType = dicData.GetStringValue(nameof(clientDuty.ContactType));
if (!string.IsNullOrEmpty(contactType))
{
var dbContactType = dbContactTypeList.Value.FirstOrDefault(n => n.ContactType == contactType);
if (dbContactType == null)
{
throw new ServiceException("[客户人员信息,ContactType未预期的职责类型:" + contactType);
}
else
{
dicData[nameof(clientDuty.ContactTypeId)] = dbContactType.id;
}
}
//证件类型
var idCardType = dicData.GetStringValue(nameof(clientDuty.IdCardType));
if (!string.IsNullOrEmpty(idCardType))
{
if (Enum.TryParse<IdCardTypeEnum>(idCardType, out var type))
{
dicData[nameof(clientDuty.IdCardType)] = type;
}
else
{
throw new ServiceException("[客户人员信息,idCardType未预期的证件类型:" + idCardType);
}
}
dicData[nameof(ClientDuty.ClientId)] = client.ClientId;
//map and save
dicData.MapToClientDuty(clientDuty, out var upset);
new ClientDutyService(this).SaveClientDuty(clientDuty, upset);
return new ClientDutySaveApiV2Result
{
IdCardNo = idCardNo,
ResultMessage = isNew ? "客户人员信息新增成功" : "客户人员信息更新成功"
};
}
#endregion
#region----保存客户银行卡----
private List<ClientBankCardSaveApiV2Result> SaveClientBankcards(InnerClient client, IEnumerable<IDictionary<string, object>> bankcardDics)
{
var useList = new Lazy<List<SelectItem>>(() =>
{
return BLL.DictionaryBLL.GetList("资金用途", false);
});
var seq = 0;
var resultList = new List<ClientBankCardSaveApiV2Result>(bankcardDics.Count());
foreach (var dic in bankcardDics)
{
seq++;
if (dic == null)
{
continue;
}
var dicData = new DicData(dic, client.IsNew);
var cardNo = dicData.GetStringValue(nameof(ClientBankCard.Card));
if (string.IsNullOrWhiteSpace(cardNo))
{
throw new ServiceException($"创建、更新或删除客户的银行卡信息时,银行账号不能为空,索引:第{seq}条");
}
if (dicData.Action == ActionType.delete)
{
var cardNoR = cardNo.Replace(" ", "");
var dbBankcard = DbContext.bankcard.FirstOrDefault(n => n.ApprovalOrder < 1 && n.ClientId == client.ClientId && n.Card == cardNoR);
if (dbBankcard != null)
{
new ClientBankCardService(this).InvalidBankcard(dbBankcard.id, out _);
}
resultList.Add(new ClientBankCardSaveApiV2Result
{
Card = cardNo,
ResultMessage = dbBankcard == null ? "要删除的客户银行卡信息不存在" : "客户银行卡信息删除成功"
});
}
else
{
var result = SaveBankcard(client, dicData, cardNo, seq,useList:useList);
resultList.Add(result);
}
}
return resultList;
}
private ClientBankCardSaveApiV2Result SaveBankcard(InnerClient client, DicData dicData, string cardNo, int seq, Lazy<List<SelectItem>> useList)
{
ClientBankCard bankcard;
var predicate = PredicateBuilder.Create<ClientBankCard>(n => n.ApprovalOrder < 1 && n.ClientId == client.ClientId && n.Card == cardNo && n.ValidState != ConsGlobal.InValid);
switch (dicData.Action)
{
case ActionType.create:
bankcard = new ClientBankCard();
if (!client.IsNew && DbContext.bankcard.Any(predicate))
{
throw new ServiceException($"新增客户银行卡时,与已有客户银行卡的银行账号重复,银行账号:{cardNo},索引:第{seq}条");
}
break;
case ActionType.update:
if (client.IsNew)
{
throw new ServiceException("新增客户时,客户银行卡信息不支持更新");
}
else
{
bankcard = DbContext.bankcard.AsNoTracking().FirstOrDefault(predicate)
?? throw new ServiceException($"要更新的客户银行卡信息不存在或已无效,银行账号:{cardNo},索引:第{seq}条");
}
break;
case ActionType.updateOrCreate:
bankcard = client.IsNew
? new ClientBankCard()
: DbContext.bankcard.AsNoTracking().FirstOrDefault(predicate) ?? new ClientBankCard();
break;
default: throw new ServiceException("[客户银行卡信息]不支持此操作:" + dicData.Action);
}
var isNew = bankcard.id == 0;
// 保存客户时开户行型必填
var bank = dicData.GetStringValue(nameof(bankcard.Bank));
if (isNew ? string.IsNullOrEmpty(bank) : bank == string.Empty)
{
throw new ServiceException($"保存客户时,开户行不能为空,银行账号:{cardNo},索引:第{seq}条");
}
// 保存客户时银行账号称必填
var card = dicData.GetStringValue(nameof(bankcard.Card));
if (isNew ? string.IsNullOrEmpty(card) : card == string.Empty)
{
throw new ServiceException($"保存客户时,银行账号不能为空,银行账号:{cardNo},索引:第{seq}条");
}
// 保存客户时户名称必填
var clientName = dicData.GetStringValue(nameof(bankcard.ClientName));
if (isNew ? string.IsNullOrEmpty(clientName) : clientName == string.Empty)
{
throw new ServiceException($"保存客户时,户名不能为空,银行账号:{cardNo},索引:第{seq}条");
}
// 保存客户时validState状态验证
var validState = dicData.GetStringValue(nameof(bankcard.ValidState));
if (isNew ? string.IsNullOrEmpty(validState) : validState == string.Empty)
{
throw new ServiceException($"保存客户时,validState不能为空,银行账号:{cardNo},索引:第{seq}条");
}
if (!string.IsNullOrEmpty(validState) && validState != "Valid" && validState!= "InValid")
{
throw new ServiceException($"保存客户时,validState不符合预期[Valid/InValid],注意大小写,银行账号:{cardNo},索引:第{seq}条");
}
// 保存客户时,验证资金用途
var use = dicData.GetStringValue(nameof(bankcard.Use));
if (!string.IsNullOrEmpty(use) && !useList.Value.Exists(g => g.Value == use))
{
throw new ServiceException($"保存客户时,Use(资金用途)不符合预期,银行账号:{cardNo},索引:第{seq}条");
}
dicData[nameof(ClientBankCard.ClientId)] = client.ClientId;
dicData.MapToClientBankcard(bankcard, out var upset);
new ClientBankCardService(this).SaveBankCard(bankcard, out _, upset);
return new ClientBankCardSaveApiV2Result
{
Card = cardNo,
ResultMessage = isNew ? "客户银行卡信息新增成功" : "客户银行卡信息更新成功"
};
}
#endregion
#region----保存客户文件----
private List<ClientFileSaveApiV2Result> SaveClientFiles(InnerClient client, IEnumerable<IDictionary<string, object>> fileDics)
{
var signTypeList = new Lazy<List<SelectItem>>(() =>
{
return BLL.DictionaryBLL.GetList("权益类签署版本", false);
});
var fileTypeList = new Lazy<List<SelectItem>>(() =>
{
return BLL.DictionaryBLL.GetList("文件类型", false);
});
var seq = 0;
var resultList = new List<ClientFileSaveApiV2Result>(fileDics.Count());
foreach (var dic in fileDics)
{
seq++;
if (dic == null)
{
continue;
}
var dicData = new DicData(dic, client.IsNew);
var fileName = dicData.GetStringValue(nameof(client_file.FileName));
if (string.IsNullOrWhiteSpace(fileName))
{
throw new ServiceException($"上传客户文件出错,文件名称不能为空,索引:第{seq}条");
}
if (dicData.Action == ActionType.delete)
{
var protocolNumber = dicData.GetStringValue(nameof(client_file.ProtocolNumber));
var ret = new ClientFileService(this).DeleteFile(client.ClientId, fileName, protocolNumber);
if (ret.IsSuccess)
{
resultList.Add(new ClientFileSaveApiV2Result { FileName = fileName, ResultMessage = ret.Message });
}
else
{
throw new ServiceException($"删除客户文件出错,索引:第{seq}条," + ret.Message);
}
}
else
{
var result = SaveClientFile(client, dicData, fileName, seq, signTypeList: signTypeList, fileTypeList: fileTypeList);
resultList.Add(result);
}
}
return resultList;
}
private ClientFileSaveApiV2Result SaveClientFile(InnerClient client, DicData dicData, string fileName, int seq, Lazy<List<SelectItem>> signTypeList, Lazy<List<SelectItem>> fileTypeList)
{
//// 校验权益类签署版本
//var signType = dicData.GetStringValue("FileTypeName");
//if (!string.IsNullOrEmpty(signType) && !signTypeList.Value.Exists(g => g.Value == signType))
//{
// throw new ServiceException($"上传客户文件出错,权益类签署版本不符合预期,索引:第{seq}条");
//}
//// 校验文件类型
//var fileTypeName = dicData.GetStringValue("FileTypeName");
//if (!string.IsNullOrEmpty(fileTypeName)&&!fileTypeList.Value.Exists(g => g.Value == fileTypeName))
//{
// throw new ServiceException($"上传客户文件出错,文件类型不符合预期,索引:第{seq}条");
//}
// 校验文件内容
var fileContent = dicData.GetStringValue("FileContent");
if (string.IsNullOrWhiteSpace(fileContent))
{
throw new ServiceException($"上传客户文件出错,文件内容不能为空,索引:第{seq}条");
}
byte[] bytes;
try
{
bytes = Convert.FromBase64String(fileContent);
}
catch (Exception ex)
{
throw new ServiceException($"解析客户文件内容出错,索引:第{seq}条,{ex.Message}");
}
// 校验操作时间
var optDate = dicData.GetStringValue(nameof(client_file.OptDate));
if (string.IsNullOrWhiteSpace(optDate))
{
dicData[nameof(Client.OptDate)] = DateTime.Now;
}
var clientFile = DbContext.client_file.AsNoTracking()
.FirstOrDefault(n => n.ApprovalOrder < 1 && n.ClientId == client.ClientId && n.FileName == fileName && n.IsValid) ?? new client_file();
dicData[nameof(client_file.ClientId)] = client.ClientId;
dicData.MapToClientFile(clientFile, out var upset);
try
{
clientFile.FlagStr = "FromWebAPI";
var ret = new ClientFileService(this).SaveClientFiles(clientFile
, dicData.GetStringValue("SideProtocolNumber")
, new List<YLErp.Models.UploadFileModel>
{
new YLErp.Models.UploadFileModel{
FileName = fileName,
OpenReadStream = ()=> new MemoryStream(bytes),
Length = bytes.Length,
ContentType = fileName.EndsWith(".pdf",StringComparison.OrdinalIgnoreCase)?"application/pdf":""
}
});
return new ClientFileSaveApiV2Result { FileName = fileName, ResultMessage = ret };
}
catch (Exception ex)
{
throw new ServiceException($"保存客户文件出错,索引:第{seq}条,{ex.Message}");
}
}
#endregion
private void CheckClientModel(Client client)
{
var propertys = client.GetType().GetProperties();
var config = ClientEditConfigService.GetConfig(true);
var selectFields = ClientEditConfigService.GetAllFormEditFieldByTableId("basic").Where(g => g.type == "select"|| g.type == "select-m" || g.type == "select-sm");
foreach (var field in selectFields)
{
var prop = propertys.Where(a => a.Name == field.name).FirstOrDefault();
if (prop == null)
{
continue;
}
var value = prop.GetValue(client, null);
if (value != null)
{
if (field.appendBlank && (prop.PropertyType == typeof(int) && (int)value == 0))
{
continue;
}
var selectValues = config.selects.Where(a => a.Key == field.name).SelectMany(a => a.Value).Select(a => a.Value);
if (selectValues?.Count() == 0)
{
continue;
}
var item = selectValues.FirstOrDefault(g => g == value.ToString());
if (item == null)
{
throw new ServiceException($"[客户人员信息,[{field.name}]非预期的选项");
}
}
}
}
class InnerClient
{
/// <summary>
/// 是否新增
/// </summary>
public bool IsNew { get; set; }
public int ClientId { get; set; }
}
enum ActionType { update, create, updateOrCreate, delete }
class DicData : Dictionary<string, object>
{
public DicData(IDictionary<string, object> dic) : base(dic, StringComparer.OrdinalIgnoreCase)
{
Action = GetAction(GetStringValue("_action"));
}
public DicData(IDictionary<string, object> dic, bool isNewClient) : base(dic, StringComparer.OrdinalIgnoreCase)
{
Action = isNewClient ? ActionType.create : GetAction(GetStringValue("_action"));
}
public ActionType Action { get; }
private static ActionType GetAction(string action) => action switch
{
"update" => ActionType.update,
"create" => ActionType.create,
"updateOrCreate" => ActionType.updateOrCreate,
"delete" => ActionType.delete,
_ => string.IsNullOrEmpty(action) ? ActionType.create : throw new ServiceException("未预期的'_action'值:" + action)
};
public string GetStringValue(string key)
{
return TryGetValue(key, out var val) ? val?.ToString() : null;
}
public IEnumerable<IDictionary<string, object>> GetSubDics(string key)
{
if (TryGetValue(key, out var arr))
{
if (arr is IEnumerable<IDictionary<string, object>> t1)
{
return t1;
}
if (arr is IEnumerable<IDictionary<string, string>> t2)
{
return t2.Cast<IDictionary<string, object>>();
}
if (arr is JArray jarr)
{
return jarr.ToObject<Dictionary<string, string>[]>()
.Select(n => new Dictionary<string, object>(n.Select(m => new KeyValuePair<string, object>(m.Key, m.Value))))
.ToArray();
}
if (arr is JsonArray jsarr)
{
return jsarr.Deserialize<Dictionary<string, string>[]>()
.Select(n => new Dictionary<string, object>(n.Select(m => new KeyValuePair<string, object>(m.Key, m.Value))))
.ToArray();
}
throw new ServiceException("解析数据失败,参数名称:" + key);
}
return null;
}
/// <summary>
/// 将字典数据映射到客户数据对象
/// </summary>
public void MapToClient(Client client, out HashSet<string> upset) => InnerMap(client, out upset);
/// <summary>
/// 将字典数据映射到客户人员信息数据对象
/// </summary>
public void MapToClientDuty(ClientDuty duty, out HashSet<string> upset) => InnerMap(duty, out upset);
/// <summary>
/// 将字典数据映射到客户银行卡信息数据对象
/// </summary>
public void MapToClientBankcard(ClientBankCard bankcard, out HashSet<string> upset) => InnerMap(bankcard, out upset);
/// <summary>
/// 将字典数据映射到客户文件信息数据对象
/// </summary>
public void MapToClientFile(client_file file, out HashSet<string> upset) => InnerMap(file, out upset);
private void InnerMap<T>(T target, out HashSet<string> upset) where T : DBModelBase
{
upset = new HashSet<string>(Keys, StringComparer.OrdinalIgnoreCase);
upset.Remove(ConsKey_Action);
upset.Remove(ConsKey_Duties);
upset.Remove(ConsKey_Bankcards);
upset.Remove(ConsKey_Files);
upset.Remove(nameof(DBModelBase.id));
if (target.id > 0)
{
if (typeof(T) == typeof(Client))
{
upset.Remove(nameof(Client.Number));
}
else if (typeof(T) == typeof(ClientDuty))
{
upset.Remove(nameof(ClientDuty.IdCardNo));
}
else if (typeof(T) == typeof(ClientBankCard))
{
upset.Remove(nameof(ClientBankCard.Card));
}
}
if (upset.Count > 0)
{
var set = upset;
ObjectHelper.MapToObject(this, target, pname => set.Contains(pname));
}
}
}
}
public class ClientSaveApiV2Result
{
public int ClientId { get; set; }
public string ClientNumber { get; set; }
public string ResultMessage { get; set; }
public IEnumerable<ClientDutySaveApiV2Result> DutyResults { get; set; }
public IEnumerable<ClientBankCardSaveApiV2Result> BankcardResults { get; set; }
public IEnumerable<ClientFileSaveApiV2Result> FileResults { get; set; }
}
public class ClientDutySaveApiV2Result
{
public string IdCardNo { get; set; }
public string ResultMessage { get; set; }
}
public class ClientBankCardSaveApiV2Result
{
public string Card { get; set; }
public string ResultMessage { get; set; }
}
public class ClientFileSaveApiV2Result
{
public string FileName { get; set; }
public string ResultMessage { get; set; }
}
}