Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
D
dc-java
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
huluobin
dc-java
Commits
f369f6d5
Commit
f369f6d5
authored
Jan 15, 2021
by
huluobin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
# stash 周转
parent
a412d99b
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
131 additions
and
189 deletions
+131
-189
DateTurnover.java
.../src/main/java/com/bailuntec/domain/dto/DateTurnover.java
+18
-0
AutoTurnoverJob.java
...over/src/main/java/com/bailuntec/job/AutoTurnoverJob.java
+7
-6
AutoTrunoverContext.java
.../main/java/com/bailuntec/service/AutoTrunoverContext.java
+106
-183
No files found.
data-common/src/main/java/com/bailuntec/domain/dto/DateTurnover.java
View file @
f369f6d5
...
...
@@ -22,6 +22,8 @@ public class DateTurnover {
private
BigDecimal
forecastSales
;
//预测销量公式
private
String
forecastSalesFormula
;
//预测销量解释
private
String
forecastSalesExplain
;
//日期
private
LocalDate
date
;
//周系数
...
...
@@ -36,6 +38,22 @@ public class DateTurnover {
private
BigDecimal
showSales
;
//入库释义
private
String
inboundRelation
;
//预计入库数量
private
BigDecimal
forecastInbound
;
//预测缺货数量
private
BigDecimal
forecastShortSupply
;
//mop 采购建议
private
BigDecimal
moqPurchaseAdvised
;
//预测采购建议
private
BigDecimal
forecastPurchaseAdvised
;
//预计库存
private
BigDecimal
forecastInventory
;
//p_表示采购单Id, t_表示调拨单Id, 用_连接调拨在途数量
private
String
forecastInboundRelation
;
//预测采购入库
private
BigDecimal
forecastPurchaseInbound
;
//预测调拨入库
private
BigDecimal
forecastTransferInbound
;
public
void
calcShowSales
()
{
this
.
showSales
=
sales
;
...
...
data-show/show-auto-turnover/src/main/java/com/bailuntec/job/AutoTurnoverJob.java
View file @
f369f6d5
...
...
@@ -661,12 +661,8 @@ public class AutoTurnoverJob extends PointJob {
dcAutoForecastFluctuationActual
.
setEndTime
(
recordTime
);
forecastFluctuationList
.
add
(
dcAutoForecastFluctuationActual
);
}
}
/*
* 自动下单管理的冗余-缺货等异常提醒
*/
if
(
hasMonitorFluctuation
)
{
//自动下单管理的冗余-缺货等异常提醒
unusualFluctuation
(
turnoverDays
,
recordTime
,
...
...
@@ -1655,7 +1651,12 @@ public class AutoTurnoverJob extends PointJob {
}
//按照规则递减或递增 j = 63
for
(
int
i
=
0
;
i
<=
shortSupplyDays
;
i
++)
{
BigDecimal
result
=
forecastSaleGTZero
.
multiply
(
Constant
.
FBA_OUT_STOCK_DECREASE
.
pow
(
shortSupplyDays
)).
multiply
(
Constant
.
FBA_OUT_STOCK_INCREMENT
.
pow
(
i
)).
setScale
(
3
,
RoundingMode
.
HALF_EVEN
);
BigDecimal
result
=
forecastSaleGTZero
.
multiply
(
Constant
.
FBA_OUT_STOCK_DECREASE
.
pow
(
shortSupplyDays
))
.
multiply
(
Constant
.
FBA_OUT_STOCK_INCREMENT
.
pow
(
i
))
.
setScale
(
3
,
RoundingMode
.
HALF_EVEN
);
//索引越界
if
(
j
+
i
<
forecastSalesList
.
size
())
{
forecastSalesList
.
set
(
j
+
i
-
1
,
result
);
...
...
data-show/show-auto-turnover/src/main/java/com/bailuntec/service/AutoTrunoverContext.java
View file @
f369f6d5
...
...
@@ -75,7 +75,7 @@ public class AutoTrunoverContext {
DcBaseSkuMapper
dcBaseSkuMapper
,
DcAveragePurchaseMapper
dcAveragePurchaseMapper
,
DcAverageWarehouseMapper
dcAverageWarehouseMapper
,
AutoTurnoverService
autoTurnoverService
,
DcBaseWeekCoefficientMapper
dcBaseWeekCoefficientMapper
,
SalesDayConfigMapper
salesDayConfigMapper
,
DateSalesService
dateSalesService
,
DcBasePurchaseMapper
dcBasePurchaseMapper
,
DcAutoConfigDeliveryMapper
dcAutoConfigDeliveryMapper
,
DcAutoInboundMapper
autoInboundMapper
)
{
AutoTurnoverService
autoTurnoverService
,
DcBaseWeekCoefficientMapper
dcBaseWeekCoefficientMapper
,
SalesDayConfigMapper
salesDayConfigMapper
,
DateSalesService
dateSalesService
,
Dc
AutoConfigSkuWarehouseMapper
autoConfigSkuWarehouseMapper
,
List
<
DateTurnover
>
dateTurnoverList
,
Dc
BasePurchaseMapper
dcBasePurchaseMapper
,
DcAutoConfigDeliveryMapper
dcAutoConfigDeliveryMapper
,
DcAutoInboundMapper
autoInboundMapper
)
{
//source
this
.
dcBaseStock
=
dcBaseStock
;
...
...
@@ -91,6 +91,8 @@ public class AutoTrunoverContext {
this
.
dcBaseWeekCoefficientMapper
=
dcBaseWeekCoefficientMapper
;
this
.
salesDayConfigMapper
=
salesDayConfigMapper
;
this
.
dateSalesService
=
dateSalesService
;
this
.
autoConfigSkuWarehouseMapper
=
autoConfigSkuWarehouseMapper
;
this
.
dateTurnoverList
=
dateTurnoverList
;
this
.
dcBasePurchaseMapper
=
dcBasePurchaseMapper
;
this
.
dcAutoConfigDeliveryMapper
=
dcAutoConfigDeliveryMapper
;
this
.
autoInboundMapper
=
autoInboundMapper
;
...
...
@@ -355,6 +357,7 @@ public class AutoTrunoverContext {
private
final
DateSalesService
dateSalesService
;
private
void
calculatePlatformAvgSales
()
{
DcAutoSalesMapper
mapper
=
SessionUtil
.
getSession
().
getMapper
(
DcAutoSalesMapper
.
class
);
SalesVolumeAvgDTO
ebayAvgSales
=
mapper
.
getPlatformHistorySales
(
dcAutoTurnover
.
getBailunSku
(),
dcAutoTurnover
.
getWarehouseCode
(),
PlatformType
.
Ebay
.
value
());
dcAutoTurnover
.
setHistorySevendaySalesEbay
(
BigDecimal
.
ZERO
);
...
...
@@ -548,41 +551,44 @@ public class AutoTrunoverContext {
private
List
<
DateTurnover
>
dateTurnoverList
;
private
final
DcBasePurchaseMapper
dcBasePurchaseMapper
;
private
final
DcBaseTransferVerifyMapper
dcBaseTransferVerifyMapper
;
private
void
E
xpectedStorage
()
{
private
void
e
xpectedStorage
()
{
if
(
purchase
>
0
)
{
List
<
DcBasePurchase
>
dcBasePurchaseList
;
if
(
dcMidTransit
.
getQuantityPurchase
()
>
0
)
{
// 找采购在途的采购单
dcBasePurchaseList
=
dcBasePurchaseMapper
.
listPurchaseTransitOrder
(
dcAutoTurnover
.
getBailunSku
(),
dcAutoTurnover
.
getWarehouseCode
());
List
<
DcBasePurchase
>
dcBasePurchaseList
=
dcBasePurchaseMapper
.
listPurchaseTransitOrder
(
dcAutoTurnover
.
getBailunSku
(),
dcAutoTurnover
.
getWarehouseCode
());
if
(
dcBasePurchaseList
!=
null
&&
dcBasePurchaseList
.
size
()
>
0
)
{
if
(
ListUtil
.
isNotEmpty
(
dcBasePurchaseList
)
)
{
for
(
DcBasePurchase
dcBasePurchase
:
dcBasePurchaseList
)
{
if
(
dcBasePurchase
.
getCount
()
>
0
)
{
LocalDateTime
finalEstimatedArrivalTime
;
if
(
dcBasePurchase
.
getHasTransfer
()
==
1
)
{
//调拨采购单
//调拨采购单
if
(
dcBasePurchase
.
getHasTransfer
()
==
1
)
{
finalEstimatedArrivalTime
=
dcBasePurchase
.
getEstimatedArrivalTime
().
plusDays
(
dcAutoTurnover
.
getInspectionDelivery
()).
plusDays
(
dcAutoTurnover
.
getTransferBaleDelivery
()).
plusDays
(
dcAutoTurnover
.
getTransferDelivery
()).
plusDays
(
dcAutoTurnover
.
getAbroadInboundDelivery
());
}
else
{
//普通采购单
}
//普通采购单
else
{
finalEstimatedArrivalTime
=
dcBasePurchase
.
getEstimatedArrivalTime
().
plusDays
(
dcAutoTurnover
.
getInspectionDelivery
());
}
int
interval
=
Period
.
between
(
recordTime
,
finalEstimatedArrivalTime
.
toLocalDate
()).
getDays
();
int
index
=
Math
.
max
(
interval
,
0
);
forecastInboundRelationList
.
set
(
index
,
forecastInboundRelationList
.
get
(
index
).
equals
(
Constant
.
NAN_STRING
)
?
Constant
.
PURCHASE_SIGN
+
dcBasePurchase
.
getPurchaseId
()
+
"_"
+
dcBasePurchase
.
getCount
()
:
forecastInboundRelationList
.
get
(
index
)
+
"*"
+
Constant
.
PURCHASE_SIGN
+
dcBasePurchase
.
getPurchaseId
()
+
"_"
+
dcBasePurchase
.
getCount
());
forecastPurchaseInboundList
.
set
(
index
,
forecastPurchaseInboundList
.
get
(
index
)
+
dcBasePurchase
.
getCount
());
forecastInboundList
.
set
(
index
,
forecastPurchaseInboundList
.
get
(
index
)
+
forecastTransferInboundList
.
get
(
index
));
DateTurnover
dateTurnover
=
this
.
getDateTurnoverByDate
(
finalEstimatedArrivalTime
.
toLocalDate
());
//预测入库解释
dateTurnover
.
setForecastInboundRelation
(
dateTurnover
.
getForecastInboundRelation
()
+
"*"
+
Constant
.
PURCHASE_SIGN
+
dcBasePurchase
.
getPurchaseId
()
+
"_"
+
dcBasePurchase
.
getCount
());
//预测采购入库
dateTurnover
.
setForecastPurchaseInbound
(
dateTurnover
.
getForecastPurchaseAdvised
().
add
(
new
BigDecimal
(
dcBasePurchase
.
getCount
())));
//预测入库
dateTurnover
.
setForecastInbound
(
dateTurnover
.
getForecastPurchaseInbound
().
add
(
dateTurnover
.
getForecastTransferInbound
()));
}
}
}
}
//拿调拨单流水
if
(
transfer
>
0
)
{
if
(
dcMidTransit
.
getQuantityTransfer
()
>
0
)
{
List
<
DcBaseTransferVerify
>
dcBaseTransferVerifyList
;
DcBaseTransferVerifyMapper
dcBaseTransferVerifyMapper
=
SessionUtil
.
getSession
().
getMapper
(
DcBaseTransferVerifyMapper
.
class
);
// 找调拨在途的采购单
dcBaseTransferVerifyList
=
dcBaseTransferVerifyMapper
.
listTransferTransitOrder
(
dcAutoTurnover
.
getBailunSku
(),
dcAutoTurnover
.
getWarehouseCode
());
List
<
DcBaseTransferVerify
>
dcBaseTransferVerifyList
=
dcBaseTransferVerifyMapper
.
listTransferTransitOrder
(
dcAutoTurnover
.
getBailunSku
(),
dcAutoTurnover
.
getWarehouseCode
());
if
(
ListUtil
.
isNotEmpty
(
dcBaseTransferVerifyList
))
{
if
(
dcBaseTransferVerifyList
!=
null
&&
dcBaseTransferVerifyList
.
size
()
>
0
)
{
for
(
DcBaseTransferVerify
dcBaseTransferVerify
:
dcBaseTransferVerifyList
)
{
if
(
dcBaseTransferVerify
.
getCount
()
>
0
)
{
LocalDateTime
finalEstimatedArrivalTime
;
...
...
@@ -591,30 +597,21 @@ public class AutoTrunoverContext {
}
else
{
finalEstimatedArrivalTime
=
dcBaseTransferVerify
.
getCreateTime
().
plusDays
(
dcAutoConfigDelivery
.
getAbroadInbound
()).
plusDays
(
dcAutoConfigDelivery
.
getTranferBale
()).
plusDays
(
dcAutoConfigDelivery
.
getTranferHead
());
}
int
interval
=
Period
.
between
(
recordTime
,
finalEstimatedArrivalTime
.
toLocalDate
()).
getDays
();
int
index
=
Math
.
max
(
interval
,
0
);
forecastInboundRelationList
.
set
(
index
,
forecastInboundRelationList
.
get
(
index
).
equals
(
Constant
.
NAN_STRING
)
?
Constant
.
TRANSFER_SIGN
+
dcBaseTransferVerify
.
getTransferOrderId
()
+
"_"
+
dcBaseTransferVerify
.
getCount
()
:
forecastInboundRelationList
.
get
(
index
)
+
"*"
+
Constant
.
TRANSFER_SIGN
+
dcBaseTransferVerify
.
getTransferOrderId
()
+
"_"
+
dcBaseTransferVerify
.
getCount
());
DateTurnover
dateTurnover
=
this
.
getDateTurnoverByDate
(
finalEstimatedArrivalTime
.
toLocalDate
());
dateTurnover
.
setForecastInboundRelation
(
dateTurnover
.
getForecastInboundRelation
()
+
"*"
+
Constant
.
TRANSFER_SIGN
+
dcBaseTransferVerify
.
getTransferOrderId
()
+
"_"
+
dcBaseTransferVerify
.
getCount
());
//todo fba的调拨在途,切换读我做的一个新表(表结构构建中)
try
{
DcBaseWarehouseMapper
dcBaseWarehouseMapper
=
SessionUtil
.
getSession
().
getMapper
(
DcBaseWarehouseMapper
.
class
);
DcBaseWarehouse
dcBaseWarehouse
=
dcBaseWarehouseMapper
.
selectOneByExample
(
DcBaseWarehouseExample
.
newAndCreateCriteria
()
.
andWarehouseCodeEqualTo
(
dcAutoTurnover
.
getWarehouseCode
())
.
example
());
if
(!
dcBaseWarehouse
.
getSystemFlag
().
toUpperCase
().
equals
(
PlatformType
.
FBA
.
value
()))
{
forecastTransferInboundList
.
set
(
index
,
forecastTransferInboundList
.
get
(
index
)
+
dcBaseTransferVerify
.
getCount
());
forecastInboundList
.
set
(
index
,
forecastPurchaseInboundList
.
get
(
index
)
+
forecastTransferInboundList
.
get
(
index
));
}
DcBaseWarehouse
dcBaseWarehouse
=
dcBaseWarehouseMapper
.
selectByWarehouseCode
(
dcAutoTurnover
.
getWarehouseCode
())
}
finally
{
SessionUtil
.
closeSession
();
if
(!
dcBaseWarehouse
.
getSystemFlag
().
toUpperCase
().
equals
(
PlatformType
.
FBA
.
value
()))
{
//预测调拨入库
dateTurnover
.
setForecastTransferInbound
(
dateTurnover
.
getForecastTransferInbound
().
add
(
new
BigDecimal
(
dcBaseTransferVerify
.
getCount
())));
//预测入库
dateTurnover
.
setForecastInbound
(
dateTurnover
.
getForecastPurchaseInbound
().
add
(
dateTurnover
.
getForecastTransferInbound
()));
}
}
}
}
}
...
...
@@ -727,174 +724,101 @@ public class AutoTrunoverContext {
}
}
private
Integer
fbaAdvise
()
{
//通过SKU和仓库拿到实际库存
private
final
Integer
realInventory
;
BigDecimal
inboundDecimal
;
//入库数量
BigDecimal
forecastInventory
;
//预测库存
BigDecimal
shortSupply
;
//缺货数量
BigDecimal
addShortSupply
;
// 补断货的数量
int
shortSupplyDays
=
0
;
//断货天数
int
shortSupplyIndex
=
-
1
;
//断货天索引
int
fbaTransferIndex
=
1
;
private
DateTurnover
getDateTurnoverByDate
(
LocalDate
localDate
)
{
return
dateTurnoverList
.
stream
()
.
filter
(
dateTurnover
->
dateTurnover
.
getDate
().
equals
(
localDate
))
.
findAny
()
.
orElse
(
null
)
}
for
(
int
j
=
0
;
j
<
autoForecastDay
;
j
++)
{
BigDecimal
forecastSalesItem
=
forecastSalesList
.
get
(
j
);
inboundDecimal
=
BigDecimal
.
valueOf
(
forecastInboundList
.
get
(
j
));
totalInbound
=
totalInbound
.
add
(
inboundDecimal
);
if
(
j
==
turnoverDays
)
{
dcAutoTurnover
.
setTurnoverInbound
(
totalInbound
);
private
void
fxx
()
{
dateTurnoverList
.
forEach
(
dateTurnover
->
{
//昨天的周转预测
DateTurnover
lastDateTurnover
=
this
.
getDateTurnoverByDate
(
dateTurnover
.
getDate
().
minusDays
(
1
));
//昨天预测缺货
if
(
lastDateTurnover
.
getForecastShortSupply
().
compareTo
(
BigDecimal
.
ZERO
)
>
0
)
{
dateTurnover
.
setForecastSales
(
BigDecimal
.
ZERO
);
dateTurnover
.
setForecastSalesExplain
(
"昨天预测缺货"
);
//处理自动周转预测断货和冗余波动
this
.
handleAutoFastestStorage
(
dateTurnover
);
}
});
}
if
(
j
==
0
)
{
//j == 0表示, 周转计算的当天
if
(
outStock
>
0
)
{
forecastSalesList
.
set
(
j
,
BigDecimal
.
ZERO
);
forecastSalesExplainList
.
set
(
j
,
"0, 昨天真实缺货"
);
shortSupplyIndex
=
j
;
//如果有缺货数, 第一天预计库存 = 预计入库 - 缺货数
forecastInventory
=
BigDecimal
.
valueOf
((
forecastInboundList
.
get
(
j
).
doubleValue
()
-
outStock
.
doubleValue
()));
shortSupply
=
forecastInventory
.
compareTo
(
BigDecimal
.
ZERO
)
<
0
?
forecastInventory
.
abs
()
:
BigDecimal
.
ZERO
;
//库存补入后的 缺货数
BigDecimal
subtract
=
forecastSalesList
.
get
(
j
).
subtract
(
forecastInventory
.
compareTo
(
BigDecimal
.
ZERO
)
>
0
?
forecastInventory
:
BigDecimal
.
ZERO
);
//今天的缺货数
//return 库存可用天数
//在两倍周转期内, 如果预测销量 <= 库存, 那么又是可用的一天
private
Integer
fbaAdvise
()
{
dateTurnoverList
.
forEach
(
dateTurnover
->
{
//result
//预计库存
BigDecimal
forecastInventory
;
//缺货数量
BigDecimal
shortSupply
;
//// 补断货的数量
BigDecimal
addShortSupply
;
//当天
if
(
dateTurnover
.
getDate
().
equals
(
LocalDate
.
now
()))
{
//缺货>0
if
(
dcMidTransit
.
getQuantityOutStock
()
>
0
)
{
//预测销量0
dateTurnover
.
setForecastSales
(
BigDecimal
.
ZERO
);
dateTurnover
.
setForecastSalesExplain
(
"0, 昨天真实缺货"
);
//预计库存: 第一天预计库存 = 预计入库 - 缺货数
forecastInventory
=
dateTurnover
.
getForecastInbound
().
subtract
(
new
BigDecimal
(
dcMidTransit
.
getQuantityOutStock
()));
////库存补入后的 缺货数
shortSupply
=
forecastInventory
.
compareTo
(
BigDecimal
.
ZERO
)
<
0
?
forecastInventory
.
abs
()
:
BigDecimal
.
ZERO
;
//今天的缺货数
BigDecimal
subtract
=
dateTurnover
.
getForecastSales
().
subtract
(
forecastInventory
.
compareTo
(
BigDecimal
.
ZERO
)
>
0
?
forecastInventory
:
BigDecimal
.
ZERO
);
shortSupply
=
subtract
.
add
(
shortSupply
).
compareTo
(
BigDecimal
.
ZERO
)
>
0
?
subtract
.
add
(
shortSupply
)
:
BigDecimal
.
ZERO
;
}
else
{
//否则, 第一天预计库存 = 真实库存 + 预计入库
forecastInventory
=
BigDecimal
.
valueOf
((
forecastInboundList
.
get
(
j
).
doubleValue
()
+
realInventory
.
doubleValue
()));
BigDecimal
subtract
=
forecastSalesList
.
get
(
j
).
subtract
(
forecastInventory
);
shortSupply
=
subtract
.
compareTo
(
BigDecimal
.
ZERO
)
>
0
?
subtract
:
BigDecimal
.
ZERO
;
}
forecastShortSupplyList
.
set
(
j
,
forecastShortSupplyList
.
get
(
j
).
add
(
shortSupply
));
}
else
{
//j != 0表示, 周转计算之后的天数
if
(
forecastShortSupplyList
.
get
(
j
-
1
).
compareTo
(
BigDecimal
.
ZERO
)
>
0
)
{
//是断货
forecastSalesList
.
set
(
j
,
BigDecimal
.
ZERO
);
forecastSalesExplainList
.
set
(
j
,
"昨天预测缺货"
);
if
(
shortSupplyIndex
<
0
)
{
shortSupplyIndex
=
j
;
}
DcAutoFastestStorageMapper
dcAutoFastestStorageMapper
=
SessionUtil
.
getSession
().
getMapper
(
DcAutoFastestStorageMapper
.
class
);
DcAutoFastestStorage
dcAutoFastestStorage
=
dcAutoFastestStorageMapper
.
selectOneByExample
(
DcAutoFastestStorageExample
.
newAndCreateCriteria
()
.
andBailunSkuEqualTo
(
dcAutoTurnover
.
getBailunSku
())
.
andWarehouseCodeEqualTo
(
dcAutoTurnover
.
getWarehouseCode
())
.
example
());
if
(
dcAutoFastestStorage
!=
null
)
{
int
n
=
dcAutoFastestStorage
.
getPurchaseDays
()
+
dcAutoFastestStorage
.
getTransDays
();
int
x
=
Math
.
max
(
fbaTransferIndex
-
n
,
0
);
BigDecimal
multiSales
=
BigDecimal
.
valueOf
(
Math
.
min
(
1
,
Math
.
max
(
1
-
n
*
0.3
,
0
)
+
x
*
0.1
));
if
(
x
>=
1
)
{
forecastSalesList
.
set
(
j
,
forecastSalesItem
.
multiply
(
multiSales
));
}
if
(
salesDetailItemList
.
get
(
j
)
!=
null
&&
salesDetailItemList
.
get
(
j
).
getSalesDayConfig
()
!=
null
)
{
forecastSalesList
.
set
(
j
,
salesDetailItemList
.
get
(
j
).
getSalesDayConfig
());
}
}
shortSupplyDays
++;
fbaTransferIndex
++;
}
else
{
if
(
shortSupplyIndex
==
0
)
{
//尽量降序找一个不为0的历史销量
for
(
int
i
=
historySalesList
.
size
()
-
1
;
i
>=
0
;
i
--)
{
if
(
historySalesList
.
get
(
i
)
>
0
)
{
break
;
}
}
shortSupplyIndex
=
-
1
;
shortSupplyDays
=
0
;
}
else
if
(
shortSupplyIndex
>
0
)
{
//尽量降序找一个不为0的预测销量
BigDecimal
forecastSaleGTZero
=
null
;
for
(
int
i
=
shortSupplyIndex
;
i
>=
0
;
i
--)
{
forecastSaleGTZero
=
BigDecimal
.
ZERO
;
if
(
forecastSalesList
.
get
(
i
).
compareTo
(
BigDecimal
.
ZERO
)
>
0
)
{
forecastSaleGTZero
=
forecastSalesList
.
get
(
i
);
break
;
}
}
//按照规则递减或递增 j = 63
for
(
int
i
=
0
;
i
<=
shortSupplyDays
;
i
++)
{
BigDecimal
result
=
forecastSaleGTZero
.
multiply
(
Constant
.
FBA_OUT_STOCK_DECREASE
.
pow
(
shortSupplyDays
)).
multiply
(
Constant
.
FBA_OUT_STOCK_INCREMENT
.
pow
(
i
)).
setScale
(
3
,
RoundingMode
.
HALF_EVEN
);
//索引越界
if
(
j
+
i
<
forecastSalesList
.
size
())
{
forecastSalesList
.
set
(
j
+
i
-
1
,
result
);
if
(
i
==
0
)
{
forecastSalesExplainList
.
set
(
j
+
i
,
"基于"
+
shortSupplyDays
+
"天断货累积递减"
);
}
else
{
forecastSalesExplainList
.
set
(
j
+
i
,
"基于预测销量递增第"
+
i
+
"天"
);
}
}
}
shortSupplyIndex
=
-
1
;
shortSupplyDays
=
0
;
}
//没有缺货
else
{
//第一天预计库存 = 真实库存 + 预计入库
forecastInventory
=
dateTurnover
.
getForecastInbound
().
add
(
new
BigDecimal
(
realInventory
));
BigDecimal
subtract
=
dateTurnover
.
getForecastSales
().
subtract
(
forecastInventory
);
shortSupply
=
subtract
.
compareTo
(
BigDecimal
.
ZERO
)
>
0
?
subtract
:
BigDecimal
.
ZERO
;
}
forecastInventory
=
inboundDecimal
.
add
(
forecastInventoryList
.
get
(
j
-
1
)).
subtract
(
forecastSalesList
.
get
(
j
-
1
));
//预测缺货数量
dateTurnover
.
setForecastShortSupply
(
shortSupply
);
}
//计算当天之后的天数
else
{
DateTurnover
lastDateTurnover
=
this
.
getDateTurnoverByDate
(
dateTurnover
.
getDate
().
minusDays
(
1
));
//预测库存 = 昨天预计入库 + 这天预计入库 - 昨天预计销量
forecastInventory
=
dateTurnover
.
getForecastInbound
().
add
(
lastDateTurnover
.
getForecastInbound
()).
subtract
(
lastDateTurnover
.
getForecastSales
());
//为负的情况下, 应该为0
if
(
forecastInventory
.
compareTo
(
BigDecimal
.
ZERO
)
<
0
)
{
forecastInventory
=
BigDecimal
.
ZERO
;
}
//库存
先补断
货
addShortSupply
=
forecastInventory
.
subtract
(
forecastShortSupplyList
.
get
(
j
-
1
));
//库存
补断货数量 = 这天的预测库存 - 昨天预计缺
货
addShortSupply
=
forecastInventory
.
subtract
(
lastDateTurnover
.
getForecastShortSupply
(
));
if
(
addShortSupply
.
compareTo
(
BigDecimal
.
ZERO
)
<
0
)
{
forecastInventory
=
BigDecimal
.
ZERO
;
forecastShortSupplyList
.
set
(
j
,
addShortSupply
.
abs
());
dateTurnover
.
setForecastShortSupply
(
addShortSupply
.
abs
());
}
else
{
forecastShortSupplyList
.
set
(
j
,
BigDecimal
.
ZERO
);
dateTurnover
.
setForecastShortSupply
(
BigDecimal
.
ZERO
);
forecastInventory
=
addShortSupply
;
}
BigDecimal
subtract
=
forecastSalesList
.
get
(
j
).
subtract
(
forecastInventory
);
//今日断货
//今日断货
BigDecimal
subtract
=
dateTurnover
.
getForecastSales
().
subtract
(
forecastInventory
);
shortSupply
=
subtract
.
compareTo
(
BigDecimal
.
ZERO
)
>
0
?
subtract
:
BigDecimal
.
ZERO
;
forecastShortSupplyList
.
set
(
j
,
forecastShortSupplyList
.
get
(
j
).
add
(
shortSupply
));
dateTurnover
.
setForecastShortSupply
(
dateTurnover
.
getForecastShortSupply
(
).
add
(
shortSupply
));
}
// set 预计库存
dateTurnover
.
setForecastInventory
(
forecastInventory
);
//--------- 预测冗余, 预测断货 ---end
forecastInventoryList
.
set
(
j
,
forecastInventory
.
compareTo
(
BigDecimal
.
ZERO
)
<
0
?
BigDecimal
.
ZERO
:
forecastInventory
.
setScale
(
3
,
RoundingMode
.
HALF_EVEN
));
//在两倍周转期内, 如果预测销量 <= 库存, 那么又是可用的一天
if
(
j
<
Constant
.
TURNOVER_MULTIPLE
*
turnoverDays
&&
forecastSalesList
.
get
(
j
).
compareTo
(
forecastInventory
)
<=
0
)
{
inventoryAvailableDays
++;
}
//库存 - 销量, 继续跑, 这是周转期最后一天和周转期外的
if
(
j
>=
turnoverDays
)
{
if
(
j
==
turnoverDays
)
{
//周转期内总销量
if
((
warehouseCode
.
equals
(
WAREHOUSE_JIT
)
&&
(
turnoverSku
.
getBuyerName
().
equals
(
Constant
.
BUYER_JIT_1
)
||
turnoverSku
.
getBuyerName
().
equals
(
Constant
.
BUYER_JIT_2
)))
||
(
warehouseCode
.
equals
(
Constant
.
WAREHOUSE_JIT1
)
&&
(
turnoverSku
.
getBuyerName
().
equals
(
Constant
.
BUTER_JIT_5
))))
{
// totalSales = dcAutoTurnover.getDailyWeightedSales().multiply(BigDecimal.valueOf(turnoverDays));
totalSales
=
dcAutoTurnover
.
getDailyWeightedSales
().
multiply
(
BigDecimal
.
valueOf
(
turnoverDays
));
dcAutoTurnover
.
setTurnoverSales
(
totalSales
);
}
else
{
dcAutoTurnover
.
setTurnoverSales
(
totalSales
);
}
}
});
BigDecimal
totalAdvised
=
totalSafeInventory
//20200818
.
add
(
BigDecimal
.
valueOf
(
outStock
.
longValue
()))
//今天的实际缺货
.
add
(
totalSales
)
//累计销量
.
subtract
(
BigDecimal
.
valueOf
(
totalInbound
.
doubleValue
()))
//累计到货
.
subtract
(
outStock
>
0
?
BigDecimal
.
ZERO
:
BigDecimal
.
valueOf
(
realInventory
.
longValue
()))
//真实库存, 如果缺货就不减,不缺就减去
.
add
(
forecastSalesList
.
get
(
j
));
//预计销量
//采购建议数如果大于1的时候就向上取整。如果小于1就四舍五入
if
(
totalAdvised
.
compareTo
(
BigDecimal
.
ONE
)
>
0
)
{
totalAdvised
=
totalAdvised
.
setScale
(
0
,
RoundingMode
.
CEILING
);
}
else
{
totalAdvised
=
totalAdvised
.
setScale
(
0
,
RoundingMode
.
HALF_EVEN
);
}
forecastPurchaseAdvisedList
.
add
(
totalAdvised
);
if
(
totalAdvised
.
compareTo
(
moqDecimal
)
>
0
)
{
moqPurchaseAdvisedList
.
add
(
totalAdvised
);
}
else
if
(
totalAdvised
.
compareTo
(
BigDecimal
.
ZERO
)
<=
0
)
{
moqPurchaseAdvisedList
.
add
(
BigDecimal
.
ZERO
);
}
else
{
moqPurchaseAdvisedList
.
add
(
moqDecimal
);
}
}
}
totalSales
=
totalSales
.
add
(
forecastSalesList
.
get
(
j
));
}
return
inventoryAvailableDays
;
private
void
handleAutoFastestStorage
(
DateTurnover
dateTurnover
)
{
}
private
void
handleForecastFluctuation
()
{
...
...
@@ -1065,12 +989,11 @@ public class AutoTrunoverContext {
//计算周转显示销量
dateTurnoverList
.
forEach
(
DateTurnover:
:
calcShowSales
);
ExpectedStorage
(
forecastInboundRelationList
,
purchase
,
transfer
,
recordTime
,
dcAutoTurnover
,
forecastPurchaseInboundList
,
forecastTransferInboundList
,
forecastInboundList
);
this
.
expectedStorage
(
);
//通过SKU和仓库拿到实际库存
Integer
realInventory
=
(
dcBaseStock
!=
null
&&
dcBaseStock
.
getUsableStock
()
!=
null
)
?
dcBaseStock
.
getUsableStock
()
:
0
;
BigDecimal
totalSafeInventory
=
calculateSafeInventory
();
Integer
moq
=
dcBaseSku
.
getMoq
();
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment