|
|
|
|
using DS.Module.Core;
|
|
|
|
|
using DS.Module.Core.Condition;
|
|
|
|
|
using DS.Module.Core.Extensions;
|
|
|
|
|
using DS.WMS.Core.Code.Entity;
|
|
|
|
|
using DS.WMS.Core.Fee.Dtos;
|
|
|
|
|
using DS.WMS.Core.Fee.Entity;
|
|
|
|
|
using DS.WMS.Core.Fee.Interface;
|
|
|
|
|
using DS.WMS.Core.Info.Entity;
|
|
|
|
|
using DS.WMS.Core.Op.Dtos;
|
|
|
|
|
using DS.WMS.Core.Op.Entity;
|
|
|
|
|
using DS.WMS.Core.Sys.Entity;
|
|
|
|
|
using DS.WMS.Core.TaskInteraction.Interface;
|
|
|
|
|
using Masuit.Tools;
|
|
|
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
|
|
|
using Newtonsoft.Json;
|
|
|
|
|
using SqlSugar;
|
|
|
|
|
|
|
|
|
|
namespace DS.WMS.Core.Fee.Method
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 往来单位费用模板
|
|
|
|
|
/// </summary>
|
|
|
|
|
public class FeeCustTemplateService : FeeServiceBase, IFeeCustTemplateService
|
|
|
|
|
{
|
|
|
|
|
Lazy<IActionManagerService> actionService;
|
|
|
|
|
Lazy<IFeeRecordService> feeService;
|
|
|
|
|
Lazy<IFeeCurrencyExchangeService> exchangeService;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 初始化
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="serviceProvider"></param>
|
|
|
|
|
public FeeCustTemplateService(IServiceProvider serviceProvider) : base(serviceProvider)
|
|
|
|
|
{
|
|
|
|
|
actionService = new Lazy<IActionManagerService>(serviceProvider.GetRequiredService<IActionManagerService>());
|
|
|
|
|
feeService = new Lazy<IFeeRecordService>(serviceProvider.GetRequiredService<IFeeRecordService>());
|
|
|
|
|
exchangeService = new Lazy<IFeeCurrencyExchangeService>(serviceProvider.GetRequiredService<IFeeCurrencyExchangeService>());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 根据开船日生成费用
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="etd">开船日</param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public async Task GenerateFeesAsync(DateTime etd)
|
|
|
|
|
{
|
|
|
|
|
DateTime dt = DateTime.Now;
|
|
|
|
|
var list = await TenantDb.Queryable<FeeCustTemplate>()
|
|
|
|
|
.Where(x => !x.IsDisabled && SqlFunc.Between(dt, x.StartTime, x.EndTime) && (x.IsShared || x.CustomerId != null))
|
|
|
|
|
.Select(x => new FeeCustTemplate
|
|
|
|
|
{
|
|
|
|
|
Id = x.Id,
|
|
|
|
|
CustomerId = x.CustomerId,
|
|
|
|
|
FeeType = x.FeeType,
|
|
|
|
|
FeeCategoryId = x.FeeCategoryId,
|
|
|
|
|
FeeCategoryName = x.FeeCategoryName,
|
|
|
|
|
Priority = x.Priority,
|
|
|
|
|
IsShared = x.IsShared,
|
|
|
|
|
POLCode = x.POLCode,
|
|
|
|
|
PODCode = x.PODCode,
|
|
|
|
|
LaneId = x.LaneId,
|
|
|
|
|
SourceId = x.SourceId,
|
|
|
|
|
SourceDetailId = x.SourceDetailId,
|
|
|
|
|
CarrierId = x.CarrierId,
|
|
|
|
|
ForwarderId = x.ForwarderId,
|
|
|
|
|
DeptOrgId = x.DeptOrgId,
|
|
|
|
|
MBLFrtCode = x.MBLFrtCode,
|
|
|
|
|
Condition = x.Condition
|
|
|
|
|
}).ToListAsync();
|
|
|
|
|
if (list.Count == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (etd == default)
|
|
|
|
|
etd = dt.Date;
|
|
|
|
|
|
|
|
|
|
var tids = list.Select(x => x.Id);
|
|
|
|
|
var orders = await TenantDb.Queryable<SeaExport>().Where(x => SqlFunc.DateIsSame(x.ETD, etd) &&
|
|
|
|
|
SqlFunc.Subqueryable<FeeCustTemplateRecord>().Where(y => y.BusinessId == x.Id && y.BusinessType == BusinessType.OceanShippingExport && tids.Contains(y.TemplateId)).NotAny())
|
|
|
|
|
.Select(x => new SeaExportRes
|
|
|
|
|
{
|
|
|
|
|
CtnInfo = SqlFunc.Subqueryable<OpCtn>().Where(y => y.BSNO == x.Id.ToString()).ToList(y => new OpCtnRes
|
|
|
|
|
{
|
|
|
|
|
Ctn = y.Ctn,
|
|
|
|
|
CtnNum = SqlFunc.IsNull(y.CtnNum.Value, 0)
|
|
|
|
|
})
|
|
|
|
|
}, true).ToListAsync();
|
|
|
|
|
if (orders.Count == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
List<FeeRecord> feeList = [];
|
|
|
|
|
await TenantDb.Ado.BeginTranAsync();
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var localCurrecy = await Db.Queryable<SysOrg>().Where(x => x.Id == User.OrgId).Select(x => x.LocalCurrency).FirstAsync();
|
|
|
|
|
|
|
|
|
|
foreach (var order in orders)
|
|
|
|
|
{
|
|
|
|
|
var custList = list.Where(x => x.CustomerId == order.CustomerId).OrderBy(x => x.Priority);
|
|
|
|
|
foreach (var template in custList) //遍历客户费用模板,查找匹配项
|
|
|
|
|
{
|
|
|
|
|
var fees = await CreateFeesIfMatchAsync(order, template, localCurrecy);
|
|
|
|
|
if (fees != null)
|
|
|
|
|
{
|
|
|
|
|
feeList.AddRange(fees);
|
|
|
|
|
|
|
|
|
|
var record = new FeeCustTemplateRecord
|
|
|
|
|
{
|
|
|
|
|
BusinessId = order.Id,
|
|
|
|
|
BusinessType = BusinessType.OceanShippingExport,
|
|
|
|
|
CreateBy = long.Parse(User.UserId),
|
|
|
|
|
CreateTime = dt,
|
|
|
|
|
FeeCategoryId = string.IsNullOrEmpty(template.FeeCategoryId) ? null : template.FeeCategoryId,
|
|
|
|
|
FeeType = template.FeeType,
|
|
|
|
|
TemplateId = template.Id
|
|
|
|
|
};
|
|
|
|
|
await TenantDb.Insertable(record).ExecuteCommandAsync();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//未找到客户模板,开始匹配共享模板
|
|
|
|
|
if (feeList.Count == 0)
|
|
|
|
|
{
|
|
|
|
|
var sharedList = list.Where(x => x.IsShared).OrderBy(x => x.Priority).ToList();
|
|
|
|
|
foreach (var template in sharedList)
|
|
|
|
|
{
|
|
|
|
|
var fees = await CreateFeesIfMatchAsync(order, template, localCurrecy);
|
|
|
|
|
if (fees != null)
|
|
|
|
|
{
|
|
|
|
|
feeList.AddRange(fees);
|
|
|
|
|
|
|
|
|
|
var record = new FeeCustTemplateRecord
|
|
|
|
|
{
|
|
|
|
|
BusinessId = order.Id,
|
|
|
|
|
BusinessType = BusinessType.OceanShippingExport,
|
|
|
|
|
CreateBy = long.Parse(User.UserId),
|
|
|
|
|
CreateTime = dt,
|
|
|
|
|
FeeCategoryId = string.IsNullOrEmpty(template.FeeCategoryId) ? null : template.FeeCategoryId,
|
|
|
|
|
FeeType = template.FeeType,
|
|
|
|
|
TemplateId = template.Id
|
|
|
|
|
};
|
|
|
|
|
await TenantDb.Insertable(record).ExecuteCommandAsync();
|
|
|
|
|
//break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//写入当前业务的费用
|
|
|
|
|
if (feeList.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
var result = await feeService.Value.SaveAsync(feeList, true, false);
|
|
|
|
|
if (!result.Succeeded)
|
|
|
|
|
{
|
|
|
|
|
//记录失败日志
|
|
|
|
|
await new ApplicationException(result.Message).LogAsync(Db);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
feeList.Clear();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await TenantDb.Ado.CommitTranAsync();
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
await TenantDb.Ado.RollbackTranAsync();
|
|
|
|
|
await ex.LogAsync(Db);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async Task<List<FeeRecord>?> CreateFeesIfMatchAsync(SeaExportRes order, FeeCustTemplate template, string localCurrecy)
|
|
|
|
|
{
|
|
|
|
|
if (!string.IsNullOrEmpty(template.POLCode) && template.POLCode != order.LoadPortCode)
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrEmpty(template.PODCode) && template.PODCode != order.DischargePortCode)
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrEmpty(template.MBLFrtCode) && template.MBLFrtCode != order.MBLFrt)
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
if (template.LaneId.HasValue && template.LaneId != order.LaneId)
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
if (template.CarrierId.HasValue && template.CarrierId != order.CarrierId)
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
if (template.SourceId.HasValue && template.SourceId != order.SourceId)
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
if (template.SourceDetailId.HasValue && template.SourceDetailId != order.SourceDetailId)
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
if (template.ForwarderId.HasValue && template.ForwarderId != order.ForwarderId)
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
//if (template.DeptOrgId.HasValue && template.DeptOrgId != order.DeptOrgId)
|
|
|
|
|
// return null;
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrEmpty(template.Condition)) //设置了自定义匹配条件
|
|
|
|
|
{
|
|
|
|
|
var conditionModel = JsonConvert.DeserializeObject<ConditionContent>(template.Condition);
|
|
|
|
|
if (!actionService.Value.IsMatch(order, conditionModel))
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (await TenantDb.Queryable<FeeCustTemplateRecord>().AnyAsync(x => x.BusinessId == order.Id && x.BusinessType == BusinessType.OceanShippingExport &&
|
|
|
|
|
x.FeeType == template.FeeType && x.FeeCategoryId == template.FeeCategoryId))
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
var templateDetails = await TenantDb.Queryable<FeeCustTemplateDetail>().Where(y => y.TemplateId == template.Id).ToListAsync();
|
|
|
|
|
var groups = templateDetails.GroupBy(x => new
|
|
|
|
|
{
|
|
|
|
|
x.FeeId,
|
|
|
|
|
x.Unit
|
|
|
|
|
}).ToList();
|
|
|
|
|
|
|
|
|
|
List<FeeRecord> fees = new(groups.Count);
|
|
|
|
|
foreach (var g in groups)
|
|
|
|
|
{
|
|
|
|
|
FeeCustTemplateDetail? detail = null;
|
|
|
|
|
int qty = 0;
|
|
|
|
|
if (string.Equals(g.Key.Unit, "P", StringComparison.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
detail = g.FirstOrDefault()!;
|
|
|
|
|
qty = detail.IsCtn ? 0 : 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
var ctnList = order.CtnInfo?.FindAll(x => x.Ctn == g.Key.Unit);
|
|
|
|
|
if (ctnList == null || ctnList.Count == 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
detail = g.FirstOrDefault(x => x.Unit == g.Key.Unit);
|
|
|
|
|
qty = ctnList.Sum(x => x.CtnNum);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var fee = new FeeRecord
|
|
|
|
|
{
|
|
|
|
|
BusinessId = order.Id,
|
|
|
|
|
BusinessType = BusinessType.OceanShippingExport,
|
|
|
|
|
FeeType = template.FeeType,
|
|
|
|
|
FeeId = g.Key.FeeId,
|
|
|
|
|
Unit = g.Key.Unit,
|
|
|
|
|
Remark = template.FeeCategoryName,
|
|
|
|
|
TemplateId = template.Id,
|
|
|
|
|
CustomerId = detail.CustomerId,
|
|
|
|
|
CustomerName = detail.CustomerName,
|
|
|
|
|
CustomerType = detail.CustomerType,
|
|
|
|
|
InputMethod = InputMethod.Automatic,
|
|
|
|
|
Quantity = qty,
|
|
|
|
|
FeeCode = detail.FeeCode,
|
|
|
|
|
FeeName = detail.FeeName,
|
|
|
|
|
UnitPrice = detail.UnitPrice.GetValueOrDefault(),
|
|
|
|
|
Currency = detail.Currency,
|
|
|
|
|
ExchangeRate = detail.ExchangeRate,
|
|
|
|
|
TaxRate = detail.TaxRate.GetValueOrDefault(),
|
|
|
|
|
AccTaxRate = detail.AccTaxRate.GetValueOrDefault(),
|
|
|
|
|
Tax = detail.Tax.GetValueOrDefault(),
|
|
|
|
|
TaxUnitPrice = detail.TaxUnitPrice.GetValueOrDefault(),
|
|
|
|
|
IsInvoice = detail.IsInvoice,
|
|
|
|
|
IsAdvancedPay = detail.IsAdvancedPay,
|
|
|
|
|
CreateBy = order.OperatorId,
|
|
|
|
|
CreateUserName = order.OperatorName
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (fee.ExchangeRate.GetValueOrDefault() == 0 && fee.Currency != localCurrecy)
|
|
|
|
|
{
|
|
|
|
|
var er = await exchangeService.Value.GetExchangeRateAsync(new ExchangeRate
|
|
|
|
|
{
|
|
|
|
|
CurrencyFrom = detail.Currency,
|
|
|
|
|
CurrencyTo = localCurrecy,
|
|
|
|
|
FeeType = template.FeeType
|
|
|
|
|
});
|
|
|
|
|
fee.ExchangeRate = er.Data?.Rate;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (fee.CustomerId == 0)
|
|
|
|
|
{
|
|
|
|
|
switch (fee.CustomerType)
|
|
|
|
|
{
|
|
|
|
|
case "controller":
|
|
|
|
|
fee.CustomerId = order.CustomerId;
|
|
|
|
|
fee.CustomerName = order.CustomerName;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case "yard":
|
|
|
|
|
fee.CustomerId = order.YardId;
|
|
|
|
|
fee.CustomerName = order.Yard;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case "custom":
|
|
|
|
|
fee.CustomerId = order.CustomserId;
|
|
|
|
|
fee.CustomerName = order.Customser;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case "contract":
|
|
|
|
|
fee.CustomerId = order.ContractClientId;
|
|
|
|
|
fee.CustomerName = order.ContractClientName;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case "shipagency":
|
|
|
|
|
fee.CustomerId = order.ShipAgencyId;
|
|
|
|
|
fee.CustomerName = order.ShipAgency;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case "shipper":
|
|
|
|
|
fee.CustomerId = order.ShipperId.GetValueOrDefault();
|
|
|
|
|
fee.CustomerName = order.Shipper;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case "truck":
|
|
|
|
|
fee.CustomerId = order.TruckerId;
|
|
|
|
|
fee.CustomerName = order.Trucker;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case "booking":
|
|
|
|
|
fee.CustomerId = order.ForwarderId;
|
|
|
|
|
fee.CustomerName = order.Forwarder;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case "wareHouse":
|
|
|
|
|
fee.CustomerId = order.WareHouseId;
|
|
|
|
|
fee.CustomerName = order.WareHouse;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case "shippercn":
|
|
|
|
|
fee.CustomerId = order.ShipperCnId.GetValueOrDefault();
|
|
|
|
|
fee.CustomerName = order.ShipperCn;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case "agent":
|
|
|
|
|
fee.CustomerId = order.AgentId.GetValueOrDefault();
|
|
|
|
|
fee.CustomerName = order.Agent;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fees.Add(fee);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return fees;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 导入费用模板
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="models"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public async Task<DataResult> ImportAsync(IEnumerable<FeeCustTemplateModel> models)
|
|
|
|
|
{
|
|
|
|
|
ArgumentNullException.ThrowIfNull(models, nameof(models));
|
|
|
|
|
long userId = long.Parse(User.UserId);
|
|
|
|
|
|
|
|
|
|
var custNames = models.Select(x => x.CustomerName).Distinct();
|
|
|
|
|
var custList = await TenantDb.Queryable<InfoClient>().Where(x => custNames.Contains(x.Name) && x.Status == 0).Select(x => new
|
|
|
|
|
{
|
|
|
|
|
x.Id,
|
|
|
|
|
x.Name
|
|
|
|
|
}).ToListAsync();
|
|
|
|
|
|
|
|
|
|
var feeNames = models.Select(x => x.FeeName).Distinct();
|
|
|
|
|
var fees = await TenantDb.Queryable<FeeCode>().Where(x => feeNames.Contains(x.Name)).Select(x => new
|
|
|
|
|
{
|
|
|
|
|
x.Id,
|
|
|
|
|
x.Code,
|
|
|
|
|
x.Name
|
|
|
|
|
}).ToListAsync();
|
|
|
|
|
|
|
|
|
|
var carrierCodes = models.Select(x => x.CarrierName).Distinct();
|
|
|
|
|
var carriers = await TenantDb.Queryable<CodeCarrier>().Where(x => carrierCodes.Contains(x.Code)).Select(x => new
|
|
|
|
|
{
|
|
|
|
|
x.Id,
|
|
|
|
|
x.Code
|
|
|
|
|
}).ToListAsync();
|
|
|
|
|
|
|
|
|
|
var laneCodes = models.Select(x => x.LaneName).Distinct();
|
|
|
|
|
var lanes = await TenantDb.Queryable<CodeLanes>().Where(x => laneCodes.Contains(x.LaneName)).Select(x => new
|
|
|
|
|
{
|
|
|
|
|
x.Id,
|
|
|
|
|
x.LaneName
|
|
|
|
|
}).ToListAsync();
|
|
|
|
|
|
|
|
|
|
var ptCodes = models.Select(x => x.PaymentType).Distinct();
|
|
|
|
|
var frtList = await TenantDb.Queryable<CodeFrt>().Where(x => ptCodes.Contains(x.CnName)).Select(x => new
|
|
|
|
|
{
|
|
|
|
|
x.CnName,
|
|
|
|
|
x.FrtName
|
|
|
|
|
}).ToListAsync();
|
|
|
|
|
|
|
|
|
|
var sourceCodes = models.Select(x => x.SourceCode).Distinct();
|
|
|
|
|
var sources = await TenantDb.Queryable<CodeSource>().Where(x => sourceCodes.Contains(x.SourceCode)).Select(x => new
|
|
|
|
|
{
|
|
|
|
|
x.Id,
|
|
|
|
|
x.SourceCode
|
|
|
|
|
}).ToListAsync();
|
|
|
|
|
|
|
|
|
|
List<FeeCustTemplate> list = [];
|
|
|
|
|
var groups = models.GroupBy(x => new { x.CarrierName, x.POL, x.POD, x.LaneName, x.PaymentType, x.CustomerName, x.SourceCode }).ToList();
|
|
|
|
|
foreach (var g in groups)
|
|
|
|
|
{
|
|
|
|
|
var first = g.First();
|
|
|
|
|
FeeCustTemplate template = new FeeCustTemplate
|
|
|
|
|
{
|
|
|
|
|
Name = g.Key.SourceCode + "-" + "导入费用模板" + groups.IndexOf(g),
|
|
|
|
|
BusinessType = BusinessType.OceanShippingExport,
|
|
|
|
|
CustomerId = custList.Find(x => x.Name == g.Key.CustomerName)?.Id,
|
|
|
|
|
CustomerName = g.Key.CustomerName,
|
|
|
|
|
FeeType = FeeType.Receivable,
|
|
|
|
|
IsDisabled = first.StatusText != "有效",
|
|
|
|
|
StartTime = first.StartTime,
|
|
|
|
|
EndTime = first.EndTime,
|
|
|
|
|
IsShared = string.IsNullOrEmpty(g.Key.CustomerName),
|
|
|
|
|
Priority = 1,
|
|
|
|
|
CarrierId = carriers.Find(x => x.Code == g.Key.CarrierName)?.Id,
|
|
|
|
|
LaneId = lanes.Find(x => x.LaneName == g.Key.LaneName)?.Id,
|
|
|
|
|
MBLFrtCode = frtList.Find(x => x.CnName == g.Key.PaymentType)?.FrtName,
|
|
|
|
|
POLCode = g.Key.POL,
|
|
|
|
|
PODCode = g.Key.POD,
|
|
|
|
|
SourceId = sources.Find(x => x.SourceCode == g.Key.SourceCode)?.Id,
|
|
|
|
|
CreateBy = userId,
|
|
|
|
|
Note = "系统导入",
|
|
|
|
|
Details = []
|
|
|
|
|
};
|
|
|
|
|
list.Add(template);
|
|
|
|
|
|
|
|
|
|
foreach (var item in g)
|
|
|
|
|
{
|
|
|
|
|
var detail = new FeeCustTemplateDetail
|
|
|
|
|
{
|
|
|
|
|
CustomerId = template.CustomerId.GetValueOrDefault(),
|
|
|
|
|
CustomerName = template.CustomerName,
|
|
|
|
|
CustomerType = template.FeeType == FeeType.Receivable ? "controller" : null,
|
|
|
|
|
Currency = item.Currency,
|
|
|
|
|
FeeId = (fees.Find(x => x.Name == item.FeeName)?.Id).GetValueOrDefault(),
|
|
|
|
|
FeeCode = fees.Find(x => x.Name == item.FeeName)?.Code,
|
|
|
|
|
FeeName = item.FeeName,
|
|
|
|
|
IsCtn = item.UnitPrice == null,
|
|
|
|
|
Tax = 0,
|
|
|
|
|
TaxRate = 0,
|
|
|
|
|
AccTaxRate = 0,
|
|
|
|
|
ExchangeRate = item.Currency == FeeCurrency.RMB_CODE ? 1 : null,
|
|
|
|
|
IsInvoice = true,
|
|
|
|
|
CreateBy = userId
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (item.UnitPrice.HasValue)
|
|
|
|
|
{
|
|
|
|
|
detail.UnitPrice = detail.TaxUnitPrice = item.UnitPrice.Value;
|
|
|
|
|
detail.Unit = "P";
|
|
|
|
|
template.Details.Add(detail);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (item.GP20.HasValue)
|
|
|
|
|
{
|
|
|
|
|
var copiedDetail = detail.DeepClone();
|
|
|
|
|
copiedDetail.Unit = "20GP";
|
|
|
|
|
copiedDetail.UnitPrice = copiedDetail.TaxUnitPrice = item.GP20.Value;
|
|
|
|
|
template.Details.Add(copiedDetail);
|
|
|
|
|
}
|
|
|
|
|
if (item.GP40.HasValue)
|
|
|
|
|
{
|
|
|
|
|
var copiedDetail = detail.DeepClone();
|
|
|
|
|
copiedDetail.Unit = "40GP";
|
|
|
|
|
copiedDetail.UnitPrice = copiedDetail.TaxUnitPrice = item.GP40.Value;
|
|
|
|
|
template.Details.Add(copiedDetail);
|
|
|
|
|
}
|
|
|
|
|
if (item.HQ40.HasValue)
|
|
|
|
|
{
|
|
|
|
|
var copiedDetail = detail.DeepClone();
|
|
|
|
|
copiedDetail.Unit = "40HQ";
|
|
|
|
|
copiedDetail.UnitPrice = copiedDetail.TaxUnitPrice = item.HQ40.Value;
|
|
|
|
|
template.Details.Add(copiedDetail);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
await TenantDb.InsertNav(list).Include(x => x.Details).ExecuteCommandAsync();
|
|
|
|
|
return DataResult.Success;
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
await ex.LogAsync(Db);
|
|
|
|
|
return DataResult.Failed(ex.Message);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 列表
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="request"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public async Task<DataResult<List<FeeCustTemplate>>> GetListAsync(PageRequest request)
|
|
|
|
|
{
|
|
|
|
|
var whereList = request.GetConditionalModels(Db);
|
|
|
|
|
return await TenantDb.Queryable<FeeCustTemplate>().Where(whereList).ToQueryPageAsync(request.PageCondition);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 视图列表
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="request"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public async Task<DataResult<List<FeeCustTemplateView>>> GetListViewAsync(PageRequest request)
|
|
|
|
|
{
|
|
|
|
|
var query = TenantDb.Queryable<FeeCustTemplateDetail>()
|
|
|
|
|
.InnerJoin<FeeCustTemplate>((d, t) => d.TemplateId == t.Id)
|
|
|
|
|
.LeftJoin<CodeCarrier>((d, t, cc) => t.CarrierId == cc.Id)
|
|
|
|
|
.LeftJoin<CodeLanes>((d, t, cc, cl) => t.LaneId == cl.Id)
|
|
|
|
|
.LeftJoin<CodeSource>((d, t, cc, cl, cs) => t.SourceId == cs.Id)
|
|
|
|
|
.LeftJoin<CodeSourceDetail>((d, t, cc, cl, cs, csd) => t.SourceDetailId == csd.Id)
|
|
|
|
|
.LeftJoin<InfoClient>((d, t, cc, cl, cs, csd, c) => t.ForwarderId == c.Id)
|
|
|
|
|
.LeftJoin<SysOrg>((d, t, cc, cl, cs, csd, c, so) => t.DeptOrgId == so.Id, "shippingweb8_dev.sys_org")
|
|
|
|
|
.GroupBy((d, t, cc, cl, cs, csd, c, so) => new
|
|
|
|
|
{
|
|
|
|
|
d.TemplateId,
|
|
|
|
|
d.FeeId,
|
|
|
|
|
d.FeeName,
|
|
|
|
|
d.CustomerType,
|
|
|
|
|
d.CustomerId,
|
|
|
|
|
d.CustomerName,
|
|
|
|
|
|
|
|
|
|
//t.BusinessType,
|
|
|
|
|
//t.FeeType,
|
|
|
|
|
//t.StartTime,
|
|
|
|
|
//t.EndTime,
|
|
|
|
|
//t.FeeCategoryName,
|
|
|
|
|
//t.Priority,
|
|
|
|
|
//t.POLCode,
|
|
|
|
|
//t.PODCode,
|
|
|
|
|
//t.MBLFrtCode,
|
|
|
|
|
|
|
|
|
|
//cl.LaneName,
|
|
|
|
|
//CarrierName = cc.CnName,
|
|
|
|
|
//cs.SourceName,
|
|
|
|
|
//SourceDetailName = csd.DetailName,
|
|
|
|
|
//ForwarderName = c.ShortName,
|
|
|
|
|
//DeptOrgName = so.OrgName
|
|
|
|
|
}).Select((d, t, cc, cl, cs, csd, c, so) => new FeeCustTemplateView
|
|
|
|
|
{
|
|
|
|
|
Id = d.Id,
|
|
|
|
|
TemplateId = d.TemplateId,
|
|
|
|
|
CustomerType = d.CustomerType,
|
|
|
|
|
CustomerId = d.CustomerId,
|
|
|
|
|
CustomerName = d.CustomerName,
|
|
|
|
|
FeeId = d.FeeId,
|
|
|
|
|
FeeName = d.FeeName,
|
|
|
|
|
Currency = d.Currency,
|
|
|
|
|
ExchangeRate = d.ExchangeRate,
|
|
|
|
|
TaxRate = d.TaxRate,
|
|
|
|
|
AccTaxRate = d.AccTaxRate,
|
|
|
|
|
Tax = d.Tax,
|
|
|
|
|
IsInvoice = d.IsInvoice,
|
|
|
|
|
IsAdvancedPay = d.IsAdvancedPay,
|
|
|
|
|
|
|
|
|
|
Unit20GP = SqlFunc.AggregateSum(d.Unit == "20GP" ? SqlFunc.Round(d.TaxUnitPrice, 2) : null),
|
|
|
|
|
Unit40GP = SqlFunc.AggregateSum(d.Unit == "40GP" ? SqlFunc.Round(d.TaxUnitPrice, 2) : null),
|
|
|
|
|
Unit40HC = SqlFunc.AggregateSum(d.Unit == "40HC" ? SqlFunc.Round(d.TaxUnitPrice, 2) : null),
|
|
|
|
|
Unit45G0 = SqlFunc.AggregateSum(d.Unit == "45G0" ? SqlFunc.Round(d.TaxUnitPrice, 2) : null),
|
|
|
|
|
UnitTEU = SqlFunc.AggregateSum(d.Unit == "TEU" ? SqlFunc.Round(d.TaxUnitPrice, 2) : null),
|
|
|
|
|
UnitP = SqlFunc.AggregateSum(d.Unit == "P" ? SqlFunc.Round(d.TaxUnitPrice, 2) : null),
|
|
|
|
|
|
|
|
|
|
TemplateName = t.Name,
|
|
|
|
|
BusinessType = t.BusinessType,
|
|
|
|
|
FeeType = t.FeeType,
|
|
|
|
|
StartTime = t.StartTime,
|
|
|
|
|
EndTime = t.EndTime,
|
|
|
|
|
IsDisabled = t.IsDisabled,
|
|
|
|
|
IsShared = t.IsShared,
|
|
|
|
|
FeeCategoryName = t.FeeCategoryName,
|
|
|
|
|
Priority = t.Priority,
|
|
|
|
|
POLCode = t.POLCode,
|
|
|
|
|
PODCode = t.PODCode,
|
|
|
|
|
MBLFrtCode = t.MBLFrtCode,
|
|
|
|
|
CreateUserName = t.CreateUserName,
|
|
|
|
|
CreateTime = t.CreateTime,
|
|
|
|
|
LaneName = cl.LaneName,
|
|
|
|
|
CarrierName = cc.CnName,
|
|
|
|
|
SourceName = cs.SourceName,
|
|
|
|
|
SourceDetailName = csd.DetailName,
|
|
|
|
|
ForwarderName = c.ShortName,
|
|
|
|
|
DeptOrgName = so.OrgName
|
|
|
|
|
}).MergeTable();
|
|
|
|
|
|
|
|
|
|
var whereList = request.GetConditionalModels(Db);
|
|
|
|
|
return await query.Where(whereList).ToQueryPageAsync(request.PageCondition);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 详情
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="id"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public async Task<DataResult<FeeCustTemplate>> GetAsync(long id)
|
|
|
|
|
{
|
|
|
|
|
var data = await TenantDb.Queryable<FeeCustTemplate>().Where(x => x.Id == id).FirstAsync();
|
|
|
|
|
if (data != null)
|
|
|
|
|
data.Details = await TenantDb.Queryable<FeeCustTemplateDetail>().Where(x => x.TemplateId == data.Id).ToListAsync();
|
|
|
|
|
|
|
|
|
|
return DataResult<FeeCustTemplate>.Success(data, MultiLanguageConst.DataQuerySuccess);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 编辑
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="model"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public async Task<DataResult> EditAsync(FeeCustTemplate model)
|
|
|
|
|
{
|
|
|
|
|
if (model.Details.Count > 0)
|
|
|
|
|
{
|
|
|
|
|
long userId = long.Parse(User.UserId);
|
|
|
|
|
DateTime dt = DateTime.Now;
|
|
|
|
|
foreach (var item in model.Details)
|
|
|
|
|
{
|
|
|
|
|
item.TemplateId = model.Id;
|
|
|
|
|
|
|
|
|
|
item.TaxRate ??= 0;
|
|
|
|
|
item.AccTaxRate ??= 0;
|
|
|
|
|
item.Tax = Math.Round(item.TaxUnitPrice.GetValueOrDefault() - item.TaxRate.GetValueOrDefault() / 100 * item.TaxUnitPrice.GetValueOrDefault(), 2, MidpointRounding.AwayFromZero);
|
|
|
|
|
item.UnitPrice = item.TaxUnitPrice - item.Tax.GetValueOrDefault();
|
|
|
|
|
|
|
|
|
|
if (item.ExchangeRate == null)
|
|
|
|
|
{
|
|
|
|
|
if (item.Currency == FeeCurrency.RMB_CODE)
|
|
|
|
|
{
|
|
|
|
|
item.ExchangeRate = 1m;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
var er = await exchangeService.Value.GetExchangeRateAsync(new ExchangeRate
|
|
|
|
|
{
|
|
|
|
|
CurrencyFrom = item.Currency,
|
|
|
|
|
CurrencyTo = FeeCurrency.RMB_CODE,
|
|
|
|
|
FeeType = model.FeeType
|
|
|
|
|
});
|
|
|
|
|
item.ExchangeRate = er.Data?.Rate;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (item.CustomerId == 0 && model.CustomerId.HasValue)
|
|
|
|
|
item.CustomerId = model.CustomerId.Value;
|
|
|
|
|
|
|
|
|
|
if (string.IsNullOrEmpty(item.CustomerName))
|
|
|
|
|
item.CustomerName = model.CustomerName;
|
|
|
|
|
|
|
|
|
|
item.CreateBy = userId;
|
|
|
|
|
item.CreateTime = dt;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await TenantDb.Ado.BeginTranAsync();
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
if (model.Id == 0)
|
|
|
|
|
{
|
|
|
|
|
model.DeptOrgId ??= User.OrgId;
|
|
|
|
|
await TenantDb.InsertNav(model).Include(x => x.Details).ExecuteCommandAsync();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
await TenantDb.Updateable(model).ExecuteCommandAsync();
|
|
|
|
|
|
|
|
|
|
if (model.Details.Count > 0)
|
|
|
|
|
await TenantDb.Storageable(model.Details).DefaultAddElseUpdate().ExecuteCommandAsync();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await TenantDb.Ado.CommitTranAsync();
|
|
|
|
|
return DataResult.Successed("提交成功", model.Id, MultiLanguageConst.DataCreateSuccess);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
await TenantDb.Ado.RollbackTranAsync();
|
|
|
|
|
await ex.LogAsync(Db);
|
|
|
|
|
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.Operation_Failed));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 批量编辑模板
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="list"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public async Task<DataResult> BulkEditAsync(List<FeeCustTemplate> list)
|
|
|
|
|
{
|
|
|
|
|
int rows = await TenantDb.Updateable(list).UpdateColumns(x => new
|
|
|
|
|
{
|
|
|
|
|
x.CustomerId,
|
|
|
|
|
x.CustomerName,
|
|
|
|
|
x.StartTime,
|
|
|
|
|
x.EndTime,
|
|
|
|
|
x.IsDisabled,
|
|
|
|
|
x.FeeCategoryId,
|
|
|
|
|
x.FeeCategoryName,
|
|
|
|
|
x.Priority,
|
|
|
|
|
x.PODCode,
|
|
|
|
|
x.POLCode,
|
|
|
|
|
x.LaneId,
|
|
|
|
|
x.CarrierId,
|
|
|
|
|
x.MBLFrtCode,
|
|
|
|
|
x.SourceId,
|
|
|
|
|
x.SourceDetailId,
|
|
|
|
|
x.ForwarderId,
|
|
|
|
|
x.DeptOrgId
|
|
|
|
|
}).ExecuteCommandAsync();
|
|
|
|
|
return rows > 0 ? DataResult.Success : DataResult.FailedWithDesc(nameof(MultiLanguageConst.Operation_Failed));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 批量编辑模板明细
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="details"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public async Task<DataResult> BulkEditDetailsAsync(List<FeeCustTemplateDetail> details)
|
|
|
|
|
{
|
|
|
|
|
var model = await TenantDb.Queryable<FeeCustTemplate>()
|
|
|
|
|
.Where(x => x.Id == details[0].TemplateId).Select(x => new
|
|
|
|
|
{
|
|
|
|
|
x.CustomerId,
|
|
|
|
|
x.CustomerName,
|
|
|
|
|
x.FeeType
|
|
|
|
|
}).FirstAsync();
|
|
|
|
|
if (model == null)
|
|
|
|
|
return DataResult.FailedWithDesc(nameof(MultiLanguageConst.EmptyData));
|
|
|
|
|
|
|
|
|
|
foreach (var item in details)
|
|
|
|
|
{
|
|
|
|
|
item.TaxRate ??= 0;
|
|
|
|
|
item.AccTaxRate ??= 0;
|
|
|
|
|
item.Tax = Math.Round(item.TaxUnitPrice.GetValueOrDefault() - item.TaxRate.GetValueOrDefault() / 100 * item.TaxUnitPrice.GetValueOrDefault(), 2, MidpointRounding.AwayFromZero);
|
|
|
|
|
item.UnitPrice = item.TaxUnitPrice - item.Tax.GetValueOrDefault();
|
|
|
|
|
|
|
|
|
|
if (item.ExchangeRate == null)
|
|
|
|
|
{
|
|
|
|
|
if (item.Currency == FeeCurrency.RMB_CODE)
|
|
|
|
|
{
|
|
|
|
|
item.ExchangeRate = 1m;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
var er = await exchangeService.Value.GetExchangeRateAsync(new ExchangeRate
|
|
|
|
|
{
|
|
|
|
|
CurrencyFrom = item.Currency,
|
|
|
|
|
CurrencyTo = FeeCurrency.RMB_CODE,
|
|
|
|
|
FeeType = model.FeeType
|
|
|
|
|
});
|
|
|
|
|
item.ExchangeRate = er.Data?.Rate;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (item.CustomerId == 0 && model.CustomerId.HasValue)
|
|
|
|
|
item.CustomerId = model.CustomerId.Value;
|
|
|
|
|
|
|
|
|
|
if (string.IsNullOrEmpty(item.CustomerName))
|
|
|
|
|
item.CustomerName = model.CustomerName;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int rows = await TenantDb.Updateable(details).IgnoreColumns(x => new
|
|
|
|
|
{
|
|
|
|
|
x.TemplateId,
|
|
|
|
|
x.CreateTime,
|
|
|
|
|
x.CreateBy
|
|
|
|
|
}).ExecuteCommandAsync();
|
|
|
|
|
return rows > 0 ? DataResult.Success : DataResult.FailedWithDesc(nameof(MultiLanguageConst.Operation_Failed));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 复制模板
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="ids"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public async Task<DataResult> CopyAsync(params long[] ids)
|
|
|
|
|
{
|
|
|
|
|
long userId = long.Parse(User.UserId);
|
|
|
|
|
DateTime dt = DateTime.Now;
|
|
|
|
|
|
|
|
|
|
var list = await TenantDb.Queryable<FeeCustTemplate>().Where(x => ids.Contains(x.Id))
|
|
|
|
|
.Includes(x => x.Details).ToListAsync();
|
|
|
|
|
|
|
|
|
|
foreach (var item in list)
|
|
|
|
|
{
|
|
|
|
|
item.Id = 0;
|
|
|
|
|
item.CreateTime = dt;
|
|
|
|
|
item.CreateBy = userId;
|
|
|
|
|
item.UpdateBy = null;
|
|
|
|
|
item.UpdateTime = null;
|
|
|
|
|
item.Name += "-Copy";
|
|
|
|
|
item.DeptOrgId ??= User.OrgId;
|
|
|
|
|
|
|
|
|
|
foreach (var detail in item.Details)
|
|
|
|
|
{
|
|
|
|
|
detail.Id = 0;
|
|
|
|
|
detail.TemplateId = 0;
|
|
|
|
|
detail.CreateBy = userId;
|
|
|
|
|
detail.CreateTime = dt;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var boolValue = await TenantDb.InsertNav(list).Include(x => x.Details).ExecuteCommandAsync();
|
|
|
|
|
return boolValue ? DataResult.Success : DataResult.FailedWithDesc(nameof(MultiLanguageConst.Operation_Failed));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 根据ID批量删除
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="ids"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public async Task<DataResult> DeleteAsync(params long[] ids)
|
|
|
|
|
{
|
|
|
|
|
bool flag = await TenantDb.DeleteNav<FeeCustTemplate>(x => ids.Contains(x.Id))
|
|
|
|
|
.Include(x => x.Details).ExecuteCommandAsync();
|
|
|
|
|
return flag ? DataResult.Success : DataResult.FailedWithDesc(nameof(MultiLanguageConst.Operation_Failed));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|