You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

545 lines
23 KiB
C#

using System.Text;
using DS.Module.Core;
using DS.Module.Core.Extensions;
using DS.Module.SqlSugar;
using DS.Module.UserModule;
using DS.WMS.Core.Fee.Dtos;
using DS.WMS.Core.Fee.Entity;
using DS.WMS.Core.Fee.Interface;
6 months ago
using DS.WMS.Core.Flow.Dtos;
using DS.WMS.Core.Flow.Entity;
using DS.WMS.Core.Flow.Interface;
using DS.WMS.Core.Op.Entity;
using DS.WMS.Core.Sys.Entity;
using Mapster;
using Microsoft.Extensions.DependencyInjection;
using SqlSugar;
namespace DS.WMS.Core.Fee.Method
{
public class FeeRecordService : IFeeRecordService
{
6 months ago
const long PERMISSION_ID = 1793490768447541248;
readonly string DefaultCurrency = "CNY";
private readonly IServiceProvider _serviceProvider;
private readonly ISqlSugarClient db;
private readonly IUser user;
private readonly ISaasDbService saasService;
6 months ago
readonly IClientFlowInstanceService flowService;
public FeeRecordService(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
db = _serviceProvider.GetRequiredService<ISqlSugarClient>();
user = _serviceProvider.GetRequiredService<IUser>();
saasService = _serviceProvider.GetRequiredService<ISaasDbService>();
6 months ago
6 months ago
flowService = _serviceProvider.GetRequiredService<IClientFlowInstanceService>();
}
/// <summary>
/// 列表
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public DataResult<List<FeeRecordRes>> GetListByPage(PageRequest request)
{
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
//序列化查询条件
var whereList = db.ConfigQuery.Context.Utilities.JsonToConditionalModels(request.QueryCondition);
var data = tenantDb.Queryable<FeeRecord>()
.Where(whereList)
.Select<FeeRecordRes>()
.ToQueryPage(request.PageCondition);
//关联用户名称
var userIds = data.Data.Where(x => x.UpdateBy.HasValue).Select(x => x.UpdateBy.Value).Distinct().ToList();
var users = db.Queryable<SysUser>().Where(x => userIds.Contains(x.Id)).Select(x => new { x.Id, x.UserName }).ToList();
foreach (var item in data.Data)
{
if (item.UpdateBy.HasValue)
{
item.UpdateByName = users.Find(x => x.Id == item.UpdateBy.Value)?.UserName;
}
}
return data;
}
/// <summary>
/// 列表
/// </summary>
/// <param name="query"></param>
/// <returns></returns>
public DataResult<List<FeeRecord>> GetList(string query)
{
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
var src = tenantDb.Queryable<FeeRecord>();
if (!query.IsNullOrEmpty())
{
//序列化查询条件
var whereList = db.ConfigQuery.Context.Utilities.JsonToConditionalModels(query);
src = src.Where(whereList);
}
var data = src.ToList();
return new DataResult<List<FeeRecord>>(ResultCode.Success) { Data = data };
}
/// <summary>
/// 检查业务是否已费用锁定
/// </summary>
/// <param name="bid">业务ID</param>
/// <returns></returns>
bool IsFeeLocked(long bid)
{
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
var entity = tenantDb.Queryable<SeaExport>().Where(x => x.Id == bid).Select(x => new { x.IsFeeLocking }).First();
return entity == null ? false : entity.IsFeeLocking.GetValueOrDefault();
}
/// <summary>
/// 提交
/// </summary>
/// <param name="bid">业务ID</param>
/// <param name="items">要提交的费用记录</param>
/// <returns></returns>
public DataResult InsertOrUpdate(long bid, IEnumerable<FeeRecord> items)
{
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
if (IsFeeLocked(bid))
return DataResult.Failed("当前业务已费用锁定,禁止修改", MultiLanguageConst.Operation_Failed);
try
{
tenantDb.Ado.BeginTran();
DateTime dtNow = DateTime.Now;
var feeIds = items.Where(x => x.Id > 0).Select(x => x.Id).ToArray();
//包含修改的项,需要检测费用状态再修改
if (feeIds.Length > 0)
{
var fees = tenantDb.Queryable<FeeRecord>().Where(x => feeIds.Contains(x.Id)).Select(x => new FeeRecord
{
Id = x.Id,
FeeName = x.FeeName,
FeeStatus = x.FeeStatus
}).ToList();
StringBuilder sb = new StringBuilder();
foreach (var fe in fees)
{
if (fe.FeeStatus != FeeStatus.Entering || fe.FeeStatus != FeeStatus.AuditPassed)
{
sb.Append($"费用【{fe.FeeName}】状态不正确,无法修改;");
continue;
}
}
if (sb.Length > 0)
return DataResult.Failed(sb.ToString(), MultiLanguageConst.Operation_Failed);
}
foreach (var item in items)
{
item.SubmitDate = dtNow;
item.FeeStatus = FeeStatus.Entering;
if (item.Id == 0)
{
item.BusinessId = bid;
tenantDb.Insertable(item).ExecuteCommand();
}
else
{
tenantDb.Updateable(item).IgnoreColumns(x => new
{
//x.FeeStatus,
x.CreateBy,
x.CreateTime,
x.BusinessId,
x.DeleteBy,
x.Deleted,
x.DeleteTime
}).ExecuteCommand();
}
}
tenantDb.Ado.CommitTran();
var list = items.Select(x => x.Adapt<FeeRecordRes>()).ToList();
return DataResult.Successed("保存成功", list, MultiLanguageConst.DataUpdateSuccess);
}
catch
{
tenantDb.Ado.RollbackTran();
//throw;
return DataResult.Failed("保存失败", MultiLanguageConst.DataUpdateFailed);
}
}
/// <summary>
/// 根据模板ID创建
/// </summary>
/// <param name="bid">业务ID</param>
6 months ago
/// <param name="tidArray">模板ID</param>
/// <returns></returns>
public DataResult CreateByTemplate(long bid, params long[] tidArray)
{
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
bool hasExists = tenantDb.Queryable<FeeRecord>().LeftJoin<FeeTemplateDetail>((x, y) =>
x.FeeId == y.FeeId && x.FeeType == y.FeeType).Any((x, y) =>
x.BusinessId == bid && tidArray.Contains(y.TemplateId) && !y.Deleted);
if (hasExists)
return DataResult.Failed("费用记录已存在", MultiLanguageConst.FeeRecordExist);
var details = tenantDb.Queryable<FeeTemplateDetail>().Where(x => tidArray.Contains(x.TemplateId) && !x.Deleted).Select(x => new
{
x.FeeType,
x.FeeId,
x.FeeCode,
x.FeeName,
x.FeeFrt,
x.FeeGroup,
x.CustomerName,
x.CustomerType,
x.CustomerId,
x.Unit,
x.UnitPrice,
x.Currency,
x.ExchangeRate,
x.Tax,
x.TaxRate,
x.AccTaxRate,
x.IsAdvancedPay,
x.IsInvoice,
x.SaleOrgId,
x.Note
}).ToList();
6 months ago
List<FeeRecord> records = new List<FeeRecord>(details.Count);
foreach (var item in details)
{
var record = item.Adapt<FeeRecord>();
record.BusinessId = bid;
record.SubmitDate = DateTime.Now;
records.Add(record);
}
//若计价货币单位不等于默认货币则尝试获取最新汇率
var exRecords = records.FindAll(x => !x.ExchangeRate.HasValue && x.Currency != DefaultCurrency);
if (exRecords.Count > 0)
{
var codes = exRecords.Select(x => x.Currency).Distinct().ToList();
var currencies = tenantDb.Queryable<FeeCurrency>().Where(x => codes.Contains(x.CodeName)).Includes(x => x.Exchanges).ToList();
6 months ago
DateTime dtNow = DateTime.Now;
foreach (var item in exRecords)
{
var currency = currencies.Find(x => x.CodeName == item.Currency);
6 months ago
if (currency != null)
{
item.ExchangeRate = currency.DefaultRate;
if (currency.Exchanges != null)
{
//取当前时间范围内的最新一条
var exchange = currency.Exchanges.FindAll(x => x.Status == StatusEnum.Enable &&
x.StartDate >= dtNow && x.EndDate <= dtNow).OrderByDescending(x => x.UpdateTime).FirstOrDefault();
if (exchange != null)
item.ExchangeRate = item.FeeType == 1 ? exchange.DRValue : exchange.CRValue;
}
}
}
}
int result = tenantDb.Insertable(records).ExecuteCommand();
return result > 0 ? DataResult.Successed("保存成功", records, MultiLanguageConst.DataCreateSuccess) : DataResult.Successed("操作失败!", MultiLanguageConst.Operation_Failed);
}
/// <summary>
/// 根据费用明细转换为模板明细
/// </summary>
/// <param name="idArray">费用明细ID</param>
/// <returns></returns>
public DataResult<List<FeeTemplateDetailRes>> ReadAsTemplate(params long[] idArray)
{
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
var list = tenantDb.Queryable<FeeRecord>().Where(x => idArray.Contains(x.Id)).Select<FeeTemplateDetailRes>().ToList();
return new DataResult<List<FeeTemplateDetailRes>>(ResultCode.Success) { Data = list };
}
/// <summary>
/// 删除
/// </summary>
/// <param name="ids">费用记录ID</param>
/// <returns></returns>
public DataResult Delete(params long[] ids)
{
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
var bid = tenantDb.Queryable<FeeRecord>().Where(x => ids.Contains(x.Id)).Select(x => x.BusinessId).First();
if (IsFeeLocked(bid))
return DataResult.Failed("当前业务已费用锁定,禁止修改", MultiLanguageConst.Operation_Failed);
if (tenantDb.Queryable<FeeRecord>().Any(x => ids.Contains(x.Id) && (x.FeeStatus != FeeStatus.Entering || x.FeeStatus != FeeStatus.AuditPassed)))
return DataResult.Failed("只能删除状态为‘录入’或‘审核通过’的费用", MultiLanguageConst.FeeRecordDelete);
int result = tenantDb.Deleteable<FeeRecord>(x => ids.Contains(x.Id)).ExecuteCommand();
6 months ago
return result > 0 ? DataResult.Successed("删除成功!", MultiLanguageConst.DataDelSuccess) : DataResult.Failed("删除失败!", MultiLanguageConst.Operation_Failed);
}
/// <summary>
/// 发起审批工作流
/// </summary>
/// <param name="auditType">审批类型</param>
/// <param name="idArray">费用记录ID</param>
/// <returns></returns>
public DataResult SubmitForApproval(FeeAuditType auditType, params long[] idArray)
{
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
var fees = tenantDb.Queryable<FeeRecord>().Where(x => idArray.Contains(x.Id)).Select(x => new FeeRecord
{
Id = x.Id,
FeeName = x.FeeName,
6 months ago
FeeStatus = x.FeeStatus,
FlowId = x.FlowId,
BusinessId = x.BusinessId
}).ToList();
if (fees.IsNullOrEmpty())
return DataResult.Failed($"未能获取费用信息,提交失败", MultiLanguageConst.Operation_Failed);
if (IsFeeLocked(fees[0].BusinessId))
return DataResult.Failed("当前业务已费用锁定,禁止修改", MultiLanguageConst.Operation_Failed);
6 months ago
if (fees.Any(x => x.FlowId.HasValue))
return DataResult.Failed($"当前费用包含正在审批中的费用,无法提交", MultiLanguageConst.Operation_Failed);
if (fees.Any(x => x.FeeStatus == FeeStatus.PartialSettlement || x.FeeStatus == FeeStatus.SettlementCompleted))
return DataResult.Failed($"当前审批费用包含已结算/部分结算的费用,无法提交", MultiLanguageConst.Operation_Failed);
DataResult result;
if (auditType == FeeAuditType.ApplyAudit)
{
result = ApplyAudit(auditType, fees);
}
else
{
result = ApplyModification(auditType, fees);
}
if (!result.Succeeded)
return result;
6 months ago
int rows = tenantDb.Updateable(fees).UpdateColumns(x => new { x.Id, x.FeeStatus, x.UpdateBy, x.UpdateTime, x.FlowId }).ExecuteCommand();
return rows > 0 ? DataResult.Successed("提交成功!", MultiLanguageConst.DataUpdateSuccess) : DataResult.Failed("提交失败!", MultiLanguageConst.Operation_Failed);
}
//录入->提交审核
DataResult ApplyAudit(FeeAuditType auditType, List<FeeRecord> fees)
{
StringBuilder sb = new StringBuilder();
foreach (var fe in fees)
{
if (fe.FeeStatus != FeeStatus.Entering && fe.FeeStatus != FeeStatus.RejectSubmission)
{
sb.Append($"费用【{fe.FeeName}】状态不正确,无法提交审批;");
continue;
}
}
if (sb.Length > 0)
return DataResult.Failed(sb.ToString(), MultiLanguageConst.Operation_Failed);
var template = FindTemplate(auditType.ToString());
if (template == null)
return DataResult.Failed("未能找到审批模板", MultiLanguageConst.Operation_Failed);
DateTime dtNow = DateTime.Now;
foreach (var item in fees)
{
var result = flowService.CreateFlowInstance(new CreateFlowInstanceReq { BusinessId = item.Id, TemplateId = template.Id });
if (result.Succeeded)
{
var instance = result.Data as FlowInstance;
flowService.StartFlowInstance(instance.Id.ToString());
//变更状态为提交审核
item.FeeStatus = FeeStatus.AuditSubmitted;
item.UpdateBy = long.Parse(user.UserId);
item.UpdateTime = dtNow;
6 months ago
item.FlowId = instance.Id;
}
}
return DataResult.Success;
}
//审核通过->申请修改/删除
DataResult ApplyModification(FeeAuditType auditType, List<FeeRecord> fees)
{
StringBuilder sb = new StringBuilder();
foreach (var fe in fees)
{
if (fe.FeeStatus != FeeStatus.AuditPassed && fe.FeeStatus != FeeStatus.RejectApplication)
{
sb.Append($"费用【{fe.FeeName}】状态不正确,无法提交审批;");
continue;
}
}
if (sb.Length > 0)
return DataResult.Failed(sb.ToString(), MultiLanguageConst.Operation_Failed);
6 months ago
var template = FindTemplate(auditType.ToString());
if (template == null)
return DataResult.Failed("未能找到审批模板", MultiLanguageConst.Operation_Failed);
DateTime dtNow = DateTime.Now;
foreach (var item in fees)
6 months ago
{
var result = flowService.CreateFlowInstance(new CreateFlowInstanceReq { BusinessId = item.Id, TemplateId = template.Id });
6 months ago
if (result.Succeeded)
{
var instance = result.Data as FlowInstance;
flowService.StartFlowInstance(instance.Id.ToString());
//变更状态为申请删除/修改
item.FeeStatus = auditType == FeeAuditType.ApplyDeletion ? FeeStatus.ApplyDeletion : FeeStatus.ApplyModification;
item.UpdateBy = long.Parse(user.UserId);
item.UpdateTime = dtNow;
6 months ago
item.FlowId = instance.Id;
6 months ago
}
}
return DataResult.Success;
}
/// <summary>
/// 根据审批结果更新审批状态
/// </summary>
/// <param name="id">费用ID</param>
/// <param name="flowStatus">审批结果</param>
/// <returns></returns>
public DataResult UpdateAuditStatus(long id, FlowStatusEnum flowStatus)
{
6 months ago
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
var fee = tenantDb.Queryable<FeeRecord>().Where(x => x.Id == id).Select(x => new { x.Id, x.FeeStatus }).First();
if (fee == null)
return DataResult.Failed("未能找到费用记录,更新状态失败", MultiLanguageConst.Operation_Failed);
FeeStatus? targetStatus = null;
switch (fee.FeeStatus)
{
case FeeStatus.AuditSubmitted:
if (flowStatus == FlowStatusEnum.Approve)
targetStatus = FeeStatus.AuditPassed;
else if (flowStatus == FlowStatusEnum.Reject)
targetStatus = FeeStatus.RejectSubmission;
break;
case FeeStatus.ApplyModification:
if (flowStatus == FlowStatusEnum.Approve)
targetStatus = FeeStatus.AuditPassed;
else if (flowStatus == FlowStatusEnum.Reject)
targetStatus = FeeStatus.RejectApplication;
break;
case FeeStatus.ApplyDeletion:
if (flowStatus == FlowStatusEnum.Approve)
targetStatus = FeeStatus.AuditPassed;
else if (flowStatus == FlowStatusEnum.Reject)
targetStatus = FeeStatus.RejectApplication;
break;
default:
return DataResult.Failed("费用未处于审批状态,更新状态失败", MultiLanguageConst.Operation_Failed);
}
//状态无变化
if (targetStatus == null)
return DataResult.NoChanged;
var entity = new FeeRecord
{
Id = fee.Id,
FeeStatus = targetStatus.Value,
6 months ago
UpdateBy = long.Parse(user.UserId),
UpdateTime = DateTime.Now,
FlowId = null
};
6 months ago
int rows = tenantDb.Updateable(entity).UpdateColumns(x => new { x.Id, x.FeeStatus, x.UpdateBy, x.UpdateTime, x.FlowId }).ExecuteCommand();
return rows > 0 ? DataResult.Successed("提交成功!", MultiLanguageConst.DataUpdateSuccess) : DataResult.Failed("提交失败!", MultiLanguageConst.Operation_Failed);
}
/// <summary>
/// 撤销审批
/// </summary>
/// <param name="idArray">费用记录ID</param>
/// <returns></returns>
public DataResult Withdraw(params long[] idArray)
{
var tenantDb = saasService.GetBizDbScopeById(user.TenantId);
var fees = tenantDb.Queryable<FeeRecord>().Where(x => idArray.Contains(x.Id)).Select(x => new FeeRecord
{
Id = x.Id,
FeeName = x.FeeName,
6 months ago
FeeStatus = x.FeeStatus,
FlowId = x.FlowId
}).ToList();
//未在审批状态中
6 months ago
var fees2 = fees.FindAll(x => x.FlowId == null || x.FeeStatus != FeeStatus.AuditSubmitted ||
x.FeeStatus != FeeStatus.ApplyModification || x.FeeStatus != FeeStatus.ApplyDeletion).ToList();
if (fees2.Count > 0)
{
string msg = string.Join("; ", fees2.Select(x => $"{x.FeeName}"));
return DataResult.Failed($"以下费用项:{msg} 未在审批状态中,无需撤销", MultiLanguageConst.Operation_Failed);
}
6 months ago
var fIdList = fees.Select(x => x.FlowId);
foreach (var id in fIdList)
{
flowService.CancelFlowInstance(new CancelFlowInstanceReq { Id = id.Value });
}
DateTime dtNow = DateTime.Now;
foreach (var item in fees)
{
switch (item.FeeStatus)
{
case FeeStatus.AuditSubmitted:
item.FeeStatus = FeeStatus.Entering;
break;
case FeeStatus.ApplyModification:
6 months ago
item.FeeStatus = FeeStatus.AuditPassed;
break;
case FeeStatus.ApplyDeletion:
6 months ago
item.FeeStatus = FeeStatus.AuditPassed;
break;
}
item.UpdateBy = long.Parse(user.UserId);
item.UpdateTime = dtNow;
6 months ago
item.FlowId = null;
}
6 months ago
int rows = tenantDb.Updateable(fees).UpdateColumns(x => new { x.Id, x.FeeStatus, x.UpdateBy, x.UpdateTime, x.FlowId }).ExecuteCommand();
6 months ago
return rows > 0 ? DataResult.Successed("提交成功!", MultiLanguageConst.DataUpdateSuccess) : DataResult.Failed("提交失败!", MultiLanguageConst.Operation_Failed);
}
/// <summary>
/// 查找模板
/// </summary>
/// <param name="auditType">审批类型</param>
/// <returns></returns>
FlowTemplateTenant FindTemplate(string auditType)
6 months ago
{
return db.Queryable<FlowTemplateTenant>().Where(x =>
x.Status == StatusEnum.Enable &&
x.PermissionId == PERMISSION_ID &&
x.AuditType == auditType).First();
}
}
}