@ -1,9 +1,9 @@
using DS.Module.Core ;
using DS.Module.Core.Condition ;
using DS.Module.Core.Data ;
using DS. Module.SqlSugar ;
using DS. WMS.Core.Fee.Dtos ;
using DS.WMS.Core.Fee.Entity ;
using DS.WMS.Core. Invoice.Dtos ;
using DS.WMS.Core. HangfireJob.Interface ;
using DS.WMS.Core.Op.Dtos ;
using DS.WMS.Core.Op.Entity ;
using Microsoft.Extensions.DependencyInjection ;
@ -15,7 +15,7 @@ namespace DS.WMS.Core.HangfireJob.Method
/// <summary>
/// 自动费用模板后台任务
/// </summary>
public class FeeCustTemplateJobService
public class FeeCustTemplateJobService : IFeeCustTemplateJobService
{
ISqlSugarClient ? db ;
@ -34,7 +34,7 @@ namespace DS.WMS.Core.HangfireJob.Method
/// <returns></returns>
public async Task GenerateFeesAsync ( )
{
var dbLinks = await db . Queryable < SysTenantLink> ( ) . ToListAsync ( ) ;
var dbLinks = await db . Queryable < Module. SqlSugar . SysTenantLink> ( ) . ToListAsync ( ) ;
SqlSugarClient ? tenantDb = null ;
try
{
@ -59,11 +59,8 @@ namespace DS.WMS.Core.HangfireJob.Method
IsAutoCloseConnection = true ,
ConnectionString = dbLink . Connection
} ) ;
tenantDb . QueryFilter . Clear < IOrgId > ( ) ;
tenantDb . QueryFilter . Clear < ISharedOrgId > ( ) ;
tenantDb . QueryFilter . Clear < ITenantId > ( ) ;
await GenerateFeesCoreAsync ( tenantDb , DateTime . Now . Date ) ;
}
}
finally
@ -79,7 +76,7 @@ namespace DS.WMS.Core.HangfireJob.Method
/// <param name="tenantDb"></param>
/// <param name="etd">开船日</param>
/// <returns></returns>
internal static async Task GenerateFeesCoreAsync ( SqlSugarClient tenantDb , DateTime etd )
internal async Task GenerateFeesCoreAsync ( SqlSugarClient tenantDb , DateTime etd )
{
DateTime dt = DateTime . Now ;
var list = await tenantDb . Queryable < FeeCustTemplate > ( )
@ -104,8 +101,6 @@ namespace DS.WMS.Core.HangfireJob.Method
} ) . 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 ) & &
@ -123,7 +118,7 @@ namespace DS.WMS.Core.HangfireJob.Method
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 ) ;
var fees = await CreateFeesIfMatchAsync ( tenantDb , order , template ) ;
if ( fees ! = null )
{
feeList . AddRange ( fees ) ;
@ -169,13 +164,7 @@ namespace DS.WMS.Core.HangfireJob.Method
//写入当前业务的费用
if ( feeList . Count > 0 )
{
//var result = await feeService.Value.SaveAsync(tenantDb, feeList, true, false);
//if (!result.Succeeded)
//{
// //记录失败日志
// //await new ApplicationException(result.Message).LogAsync(Db);
//}
await SaveAsync ( tenantDb , feeList ) ;
feeList . Clear ( ) ;
}
}
@ -185,8 +174,215 @@ namespace DS.WMS.Core.HangfireJob.Method
catch ( Exception ex )
{
await tenantDb . Ado . RollbackTranAsync ( ) ;
//await ex.LogAsync(Db);
await ex . LogAsync ( db ) ;
}
}
/// <summary>
/// 费用保存
/// </summary>
/// <param name="tenantDb"></param>
/// <param name="items">要提交的费用记录</param>
/// <returns></returns>
static async Task SaveAsync ( SqlSugarClient tenantDb , List < FeeRecord > items )
{
var first = items . Select ( x = > new { x . BusinessType , x . BusinessId } ) . FirstOrDefault ( ) ;
//if (await IsFeeLockedAsync(first.BusinessId, first.BusinessType))
// return DataResult.FailedWithDesc(nameof(MultiLanguageConst.FeeLocked));
var order = await tenantDb . Queryable < SeaExport > ( ) . Where ( x = > x . Id = = first . BusinessId ) . Select ( x = > new
{
x . TEU ,
x . KGS , //毛重
x . PKGS , //件数
x . CBM //尺码
} ) . FirstAsync ( ) ;
if ( order = = null )
return ;
//获取订单箱型箱量
string bsNo = first . BusinessId . ToString ( ) ;
var ctns = await tenantDb . Queryable < OpCtn > ( ) . Where ( y = > y . BSNO = = bsNo ) . Select ( x = > new
{
x . CtnCode ,
x . CtnNum
} ) . ToListAsync ( ) ;
items = items . FindAll ( x = > x . Amount ! = 0 ) ;
foreach ( var item in items )
{
if ( item . Quantity = = 0 )
{
//逐个判定处理标准
switch ( item . Unit )
{
case "HOUR" : //小时
goto case "P" ;
case "GE" : //个
goto case "P" ;
case "DAY" : //天
goto case "P" ;
//case "XX": //箱型
// goto default;
case "JJZL" : //计价重量
goto case "Z" ;
case "ZJ" : //总价
goto case "P" ;
case "JZ" : //净重
item . Quantity = 0 ;
break ;
case "TEU" : //TEU
item . Quantity = order . TEU ;
break ;
case "JF" : //计费吨
item . Quantity = order . KGS . GetValueOrDefault ( ) / 1000 > order . CBM . GetValueOrDefault ( ) ? order . KGS . GetValueOrDefault ( ) : order . CBM . GetValueOrDefault ( ) ;
break ;
case "J" : //件数
item . Quantity = order . PKGS . GetValueOrDefault ( ) ;
break ;
case "C" : //尺码
item . Quantity = order . CBM . GetValueOrDefault ( ) ;
break ;
case "Z" : //重量
item . Quantity = order . KGS . GetValueOrDefault ( ) ;
break ;
case "P" : //单票
item . Quantity = 1 ;
break ;
default : //查找箱型标准
var ctn = ctns . Find ( x = > x . CtnCode = = item . Unit ) ;
item . Quantity = ctn = = null ? 0 : ctn . CtnNum . GetValueOrDefault ( ) ;
break ;
}
}
//计算税费
item . SetTax ( ) ;
}
//若计价货币单位不等于本位币则尝试获取最新汇率
await FetchExchangeRateAsync ( tenantDb , items ) ;
//写入费用
await tenantDb . Insertable ( items ) . ExecuteCommandAsync ( ) ;
}
static async Task FetchExchangeRateAsync ( SqlSugarClient tenantDb , List < FeeRecord > items )
{
var exRecords = items . Where ( x = > x . Currency ! = x . LocalCurrency & & x . ExchangeRate = = null ) ;
if ( exRecords . Any ( ) )
{
var exchanges = exRecords . GroupBy ( x = > new
{
x . Currency ,
x . LocalCurrency ,
x . FeeType ,
} ) . Select ( x = > new ExchangeRate
{
CurrencyFrom = x . Key . Currency ,
CurrencyTo = x . Key . LocalCurrency ,
FeeType = x . Key . FeeType
} ) ;
List < ExchangeRate > exchangeRates = [ ] ;
foreach ( var item in exchanges )
{
var result = await GetExchangeRateAsync ( tenantDb , item ) ;
if ( result . Succeeded & & result . Data ! = null )
exchangeRates . Add ( result . Data ) ;
}
foreach ( var item in items )
{
item . ExchangeRate = exchangeRates . Find ( x = > x . CurrencyFrom = = item . Currency & &
x . CurrencyTo = = item . LocalCurrency & & x . FeeType = = item . FeeType ) ? . Rate ;
}
}
}
static async Task < DataResult < ExchangeRate > > GetExchangeRateAsync ( SqlSugarClient tenantDb , ExchangeRate exchange )
{
if ( exchange . CurrencyFrom = = exchange . CurrencyTo )
{
exchange . ReverseRate = exchange . Rate = 1 m ;
return DataResult < ExchangeRate > . Success ( exchange ) ;
}
//获取本位币,默认=人民币
string localCurrency = FeeCurrency . RMB_CODE ;
if ( string . IsNullOrWhiteSpace ( exchange . CurrencyTo ) )
{
exchange . CurrencyTo = localCurrency ;
}
//需要做二次转换
if ( exchange . CurrencyFrom ! = localCurrency & & exchange . CurrencyTo ! = localCurrency )
{
//获取中间汇率
var middleRate = await GetLocalRateAsync ( tenantDb , exchange . CurrencyFrom , localCurrency , exchange . FeeType ) ;
if ( middleRate = = null )
return DataResult < ExchangeRate > . FailedData ( exchange , message : $"{MultiLanguageConst.FeeCurrencyNotFound}: {exchange.CurrencyFrom}" ) ;
var rate = await GetLocalRateAsync ( tenantDb , exchange . CurrencyTo , localCurrency , exchange . FeeType ) ;
exchange . Rate = Math . Round ( 1 / ( rate ? ? 1 m ) * middleRate . GetValueOrDefault ( ) , 4 , MidpointRounding . AwayFromZero ) ;
exchange . ReverseRate = Math . Round ( 1 / exchange . Rate , 4 , MidpointRounding . AwayFromZero ) ;
}
else
{
string currency = exchange . CurrencyFrom = = FeeCurrency . RMB_CODE ? exchange . CurrencyTo : exchange . CurrencyFrom ;
var rate = await GetLocalRateAsync ( tenantDb , currency , localCurrency , exchange . FeeType ) ;
if ( currency = = exchange . CurrencyFrom )
{
exchange . Rate = rate ? ? 1 m ;
exchange . ReverseRate = Math . Round ( 1 / exchange . Rate , 4 , MidpointRounding . AwayFromZero ) ;
}
else
{
exchange . ReverseRate = rate ? ? 1 m ;
exchange . Rate = Math . Round ( 1 / exchange . ReverseRate , 4 , MidpointRounding . AwayFromZero ) ;
}
}
return DataResult < ExchangeRate > . Success ( exchange ) ;
}
static async Task < decimal? > GetLocalRateAsync ( SqlSugarClient tenantDb , string currency , string localCurrency , FeeType ? type )
{
var entity = await tenantDb . Queryable < FeeCurrency > ( ) . Where ( x = > x . CodeName = = currency ) . Includes ( x = > x . Exchanges ) . FirstAsync ( ) ;
if ( entity = = null )
return null ;
var rate = entity . DefaultRate ;
DateTime dtNow = DateTime . Now ;
if ( type . HasValue & & entity . Exchanges ! = null & & entity . Exchanges . Count > 0 )
{
//取当前时间范围内的最新一条,优先获取本位币
var item = entity . Exchanges . FindAll ( x = > x . Status = = StatusEnum . Enable & & x . LocalCurrency = = localCurrency & &
x . StartDate > = dtNow & & x . EndDate < = dtNow ) . OrderByDescending ( x = > x . CreateTime ) . FirstOrDefault ( ) ;
item ? ? = entity . Exchanges . FindAll ( x = > x . Status = = StatusEnum . Enable & &
x . StartDate > = dtNow & & x . EndDate < = dtNow ) . OrderByDescending ( x = > x . CreateTime ) . FirstOrDefault ( ) ;
if ( item ! = null )
rate = type . Value = = FeeType . Receivable ? item . DRValue : item . CRValue ;
}
return rate ;
}
static async Task < List < FeeRecord > ? > CreateFeesIfMatchAsync ( SqlSugarClient tenantDb , SeaExportRes order , FeeCustTemplate template )
@ -239,13 +435,14 @@ namespace DS.WMS.Core.HangfireJob.Method
UnitPrice = SqlFunc . IsNull ( x . UnitPrice . Value , 0 ) ,
//Quantity = x.IsCtn ? 1 : 0,
Currency = x . Currency ,
ExchangeRate = x . ExchangeRate ,
ExchangeRate = x . ExchangeRate = = null ? 1 : 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 ,
LocalCurrency = FeeCurrency . RMB_CODE ,
Remark = template . FeeCategoryName ,
TemplateId = x . TemplateId ,
InputMethod = InputMethod . Automatic
@ -323,12 +520,6 @@ namespace DS.WMS.Core.HangfireJob.Method
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 )