|
|
@ -1,5 +1,13 @@
|
|
|
|
using DS.Module.SqlSugar;
|
|
|
|
using DS.Module.Core;
|
|
|
|
|
|
|
|
using DS.Module.Core.Condition;
|
|
|
|
|
|
|
|
using DS.Module.Core.Data;
|
|
|
|
|
|
|
|
using DS.Module.SqlSugar;
|
|
|
|
|
|
|
|
using DS.WMS.Core.Fee.Entity;
|
|
|
|
|
|
|
|
using DS.WMS.Core.Invoice.Dtos;
|
|
|
|
|
|
|
|
using DS.WMS.Core.Op.Dtos;
|
|
|
|
|
|
|
|
using DS.WMS.Core.Op.Entity;
|
|
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
|
|
|
|
|
|
using Newtonsoft.Json;
|
|
|
|
using SqlSugar;
|
|
|
|
using SqlSugar;
|
|
|
|
|
|
|
|
|
|
|
|
namespace DS.WMS.Core.HangfireJob.Method
|
|
|
|
namespace DS.WMS.Core.HangfireJob.Method
|
|
|
@ -9,7 +17,7 @@ namespace DS.WMS.Core.HangfireJob.Method
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
public class FeeCustTemplateJobService
|
|
|
|
public class FeeCustTemplateJobService
|
|
|
|
{
|
|
|
|
{
|
|
|
|
ISqlSugarClient db;
|
|
|
|
ISqlSugarClient? db;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// <summary>
|
|
|
|
/// 初始化
|
|
|
|
/// 初始化
|
|
|
@ -27,10 +35,310 @@ namespace DS.WMS.Core.HangfireJob.Method
|
|
|
|
public async Task GenerateFeesAsync()
|
|
|
|
public async Task GenerateFeesAsync()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
var dbLinks = await db.Queryable<SysTenantLink>().ToListAsync();
|
|
|
|
var dbLinks = await db.Queryable<SysTenantLink>().ToListAsync();
|
|
|
|
foreach (var dbLink in dbLinks)
|
|
|
|
SqlSugarClient? tenantDb = null;
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
foreach (var dbLink in dbLinks)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
string configId = dbLinks.IndexOf(dbLink).ToString();
|
|
|
|
|
|
|
|
//if (db.IsAnyConnection(configId))
|
|
|
|
|
|
|
|
//{
|
|
|
|
|
|
|
|
// var config = new ConnectionConfig
|
|
|
|
|
|
|
|
// {
|
|
|
|
|
|
|
|
// ConfigId = configId,
|
|
|
|
|
|
|
|
// DbType = dbLink.DbType,
|
|
|
|
|
|
|
|
// IsAutoCloseConnection = true,
|
|
|
|
|
|
|
|
// ConnectionString = dbLink.Connection
|
|
|
|
|
|
|
|
// };
|
|
|
|
|
|
|
|
// db.AddConnection(config);
|
|
|
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
tenantDb = new SqlSugarClient(new ConnectionConfig
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
ConfigId = configId,
|
|
|
|
|
|
|
|
DbType = dbLink.DbType,
|
|
|
|
|
|
|
|
IsAutoCloseConnection = true,
|
|
|
|
|
|
|
|
ConnectionString = dbLink.Connection
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
tenantDb.QueryFilter.Clear<IOrgId>();
|
|
|
|
|
|
|
|
tenantDb.QueryFilter.Clear<ISharedOrgId>();
|
|
|
|
|
|
|
|
tenantDb.QueryFilter.Clear<ITenantId>();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
finally
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
tenantDb?.Dispose();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
|
|
/// 根据开船日生成费用
|
|
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
|
|
/// <param name="tenantDb"></param>
|
|
|
|
|
|
|
|
/// <param name="etd">开船日</param>
|
|
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
|
|
internal static async Task GenerateFeesCoreAsync(SqlSugarClient tenantDb, 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,
|
|
|
|
|
|
|
|
CarrierId = x.CarrierId,
|
|
|
|
|
|
|
|
ForwarderId = x.ForwarderId,
|
|
|
|
|
|
|
|
MBLFrtCode = x.MBLFrtCode,
|
|
|
|
|
|
|
|
Condition = x.Condition
|
|
|
|
|
|
|
|
}).ToListAsync();
|
|
|
|
|
|
|
|
if (list.Count == 0)
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (etd == default)
|
|
|
|
|
|
|
|
etd = DateTime.Now.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<SeaExportRes>().ToListAsync();
|
|
|
|
|
|
|
|
if (orders.Count == 0)
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<FeeRecord> feeList = [];
|
|
|
|
|
|
|
|
await tenantDb.Ado.BeginTranAsync();
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
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(tenantDb,order, template);
|
|
|
|
|
|
|
|
if (fees != null)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
feeList.AddRange(fees);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var record = new FeeCustTemplateRecord
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
BusinessId = order.CustomerId,
|
|
|
|
|
|
|
|
BusinessType = BusinessType.OceanShippingExport,
|
|
|
|
|
|
|
|
CreateTime = dt,
|
|
|
|
|
|
|
|
FeeCategoryId = 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(tenantDb, order, template);
|
|
|
|
|
|
|
|
if (fees != null)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
feeList.AddRange(fees);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var record = new FeeCustTemplateRecord
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
BusinessId = order.CustomerId,
|
|
|
|
|
|
|
|
BusinessType = BusinessType.OceanShippingExport,
|
|
|
|
|
|
|
|
CreateTime = dt,
|
|
|
|
|
|
|
|
FeeCategoryId = template.FeeCategoryId,
|
|
|
|
|
|
|
|
FeeType = template.FeeType,
|
|
|
|
|
|
|
|
TemplateId = template.Id
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
await tenantDb.Insertable(record).ExecuteCommandAsync();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//写入当前业务的费用
|
|
|
|
|
|
|
|
if (feeList.Count > 0)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
//var result = await feeService.Value.SaveAsync(tenantDb, 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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static async Task<List<FeeRecord>?> CreateFeesIfMatchAsync(SqlSugarClient tenantDb, SeaExportRes order, FeeCustTemplate template)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
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.MBLFrtCode)
|
|
|
|
|
|
|
|
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.ForwarderId.HasValue && template.ForwarderId != order.ForwarderId)
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrEmpty(template.Condition)) //设置了自定义匹配条件
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
var conditionModel = JsonConvert.DeserializeObject<ConditionContent>(template.Condition);
|
|
|
|
|
|
|
|
if (!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 details = await tenantDb.Queryable<FeeCustTemplateDetail>().Where(y => y.TemplateId == template.Id)
|
|
|
|
|
|
|
|
.Select(x => new FeeRecord
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
BusinessId = order.Id,
|
|
|
|
|
|
|
|
BusinessType = BusinessType.OceanShippingExport,
|
|
|
|
|
|
|
|
FeeType = template.FeeType,
|
|
|
|
|
|
|
|
FeeId = x.FeeId,
|
|
|
|
|
|
|
|
FeeCode = x.FeeCode,
|
|
|
|
|
|
|
|
FeeName = x.FeeName,
|
|
|
|
|
|
|
|
CustomerId = x.CustomerId,
|
|
|
|
|
|
|
|
CustomerName = x.CustomerName,
|
|
|
|
|
|
|
|
CustomerType = x.CustomerType,
|
|
|
|
|
|
|
|
Unit = x.Unit,
|
|
|
|
|
|
|
|
UnitPrice = SqlFunc.IsNull(x.UnitPrice.Value, 0),
|
|
|
|
|
|
|
|
//Quantity = x.IsCtn ? 1 : 0,
|
|
|
|
|
|
|
|
Currency = x.Currency,
|
|
|
|
|
|
|
|
ExchangeRate = x.ExchangeRate,
|
|
|
|
|
|
|
|
TaxRate = SqlFunc.IsNull(x.TaxRate.Value, 0),
|
|
|
|
|
|
|
|
AccTaxRate = SqlFunc.IsNull(x.AccTaxRate.Value, 0),
|
|
|
|
|
|
|
|
Tax = SqlFunc.IsNull(x.Tax.Value, 0),
|
|
|
|
|
|
|
|
TaxUnitPrice = SqlFunc.IsNull(x.TaxUnitPrice.Value, 0),
|
|
|
|
|
|
|
|
IsInvoice = x.IsInvoice,
|
|
|
|
|
|
|
|
IsAdvancedPay = x.IsAdvancedPay,
|
|
|
|
|
|
|
|
Remark = template.FeeCategoryName,
|
|
|
|
|
|
|
|
TemplateId = x.TemplateId,
|
|
|
|
|
|
|
|
InputMethod = InputMethod.Automatic
|
|
|
|
|
|
|
|
}).ToListAsync();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var detail in details)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (detail.CustomerId == 0)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
switch (detail.CustomerType)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
case "controller":
|
|
|
|
|
|
|
|
detail.CustomerId = order.CustomerId;
|
|
|
|
|
|
|
|
detail.CustomerName = order.CustomerName;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case "yard":
|
|
|
|
|
|
|
|
detail.CustomerId = order.YardId;
|
|
|
|
|
|
|
|
detail.CustomerName = order.Yard;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case "custom":
|
|
|
|
|
|
|
|
detail.CustomerId = order.CustomserId;
|
|
|
|
|
|
|
|
detail.CustomerName = order.Customser;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case "contract":
|
|
|
|
|
|
|
|
detail.CustomerId = order.ContractClientId;
|
|
|
|
|
|
|
|
detail.CustomerName = order.ContractClientName;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case "shipagency":
|
|
|
|
|
|
|
|
detail.CustomerId = order.ShipAgencyId;
|
|
|
|
|
|
|
|
detail.CustomerName = order.ShipAgency;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case "shipper":
|
|
|
|
|
|
|
|
detail.CustomerId = order.ShipperId.GetValueOrDefault();
|
|
|
|
|
|
|
|
detail.CustomerName = order.Shipper;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case "truck":
|
|
|
|
|
|
|
|
detail.CustomerId = order.TruckerId;
|
|
|
|
|
|
|
|
detail.CustomerName = order.Trucker;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case "booking":
|
|
|
|
|
|
|
|
detail.CustomerId = order.ForwarderId;
|
|
|
|
|
|
|
|
detail.CustomerName = order.Forwarder;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case "carrier":
|
|
|
|
|
|
|
|
detail.CustomerId = order.CarrierId;
|
|
|
|
|
|
|
|
detail.CustomerName = order.Carrier;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case "wareHouse":
|
|
|
|
|
|
|
|
detail.CustomerId = order.WareHouseId;
|
|
|
|
|
|
|
|
detail.CustomerName = order.WareHouse;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case "shippercn":
|
|
|
|
|
|
|
|
detail.CustomerId = order.ShipperCnId.GetValueOrDefault();
|
|
|
|
|
|
|
|
detail.CustomerName = order.ShipperCn;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case "agent":
|
|
|
|
|
|
|
|
detail.CustomerId = order.AgentId.GetValueOrDefault();
|
|
|
|
|
|
|
|
detail.CustomerName = order.Agent;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return details;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
|
|
/// 根据指定条件返回是否匹配的结果
|
|
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
|
|
/// <param name="source">要对比的数据源</param>
|
|
|
|
|
|
|
|
/// <param name="condition">匹配条件</param>
|
|
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
|
|
static bool IsMatch(object source, ConditionContent condition)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (source == null || condition == null)
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TaskFlowDataContext dataContext = new((TaskFlowDataNameConst.Business, source));
|
|
|
|
|
|
|
|
if (string.IsNullOrEmpty(condition.SourceName))
|
|
|
|
|
|
|
|
condition.SourceName = TaskFlowDataNameConst.Business;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return ConditionHelper.IsPass(condition, dataContext);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|