Commit f369f6d5 by huluobin

# stash 周转

parent a412d99b
...@@ -22,6 +22,8 @@ public class DateTurnover { ...@@ -22,6 +22,8 @@ public class DateTurnover {
private BigDecimal forecastSales; private BigDecimal forecastSales;
//预测销量公式 //预测销量公式
private String forecastSalesFormula; private String forecastSalesFormula;
//预测销量解释
private String forecastSalesExplain;
//日期 //日期
private LocalDate date; private LocalDate date;
//周系数 //周系数
...@@ -36,6 +38,22 @@ public class DateTurnover { ...@@ -36,6 +38,22 @@ public class DateTurnover {
private BigDecimal showSales; private BigDecimal showSales;
//入库释义 //入库释义
private String inboundRelation; 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() { public void calcShowSales() {
this.showSales = sales; this.showSales = sales;
......
...@@ -661,12 +661,8 @@ public class AutoTurnoverJob extends PointJob { ...@@ -661,12 +661,8 @@ public class AutoTurnoverJob extends PointJob {
dcAutoForecastFluctuationActual.setEndTime(recordTime); dcAutoForecastFluctuationActual.setEndTime(recordTime);
forecastFluctuationList.add(dcAutoForecastFluctuationActual); forecastFluctuationList.add(dcAutoForecastFluctuationActual);
} }
}
/* //自动下单管理的冗余-缺货等异常提醒
* 自动下单管理的冗余-缺货等异常提醒
*/
if (hasMonitorFluctuation) {
unusualFluctuation( unusualFluctuation(
turnoverDays, turnoverDays,
recordTime, recordTime,
...@@ -1655,7 +1651,12 @@ public class AutoTurnoverJob extends PointJob { ...@@ -1655,7 +1651,12 @@ public class AutoTurnoverJob extends PointJob {
} }
//按照规则递减或递增 j = 63 //按照规则递减或递增 j = 63
for (int i = 0; i <= shortSupplyDays; i++) { 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()) { if (j + i < forecastSalesList.size()) {
forecastSalesList.set(j + i - 1, result); forecastSalesList.set(j + i - 1, result);
......
...@@ -75,7 +75,7 @@ public class AutoTrunoverContext { ...@@ -75,7 +75,7 @@ public class AutoTrunoverContext {
DcBaseSkuMapper dcBaseSkuMapper, DcBaseSkuMapper dcBaseSkuMapper,
DcAveragePurchaseMapper dcAveragePurchaseMapper, DcAveragePurchaseMapper dcAveragePurchaseMapper,
DcAverageWarehouseMapper dcAverageWarehouseMapper, DcAverageWarehouseMapper dcAverageWarehouseMapper,
AutoTurnoverService autoTurnoverService, DcBaseWeekCoefficientMapper dcBaseWeekCoefficientMapper, SalesDayConfigMapper salesDayConfigMapper, DateSalesService dateSalesService, DcBasePurchaseMapper dcBasePurchaseMapper, DcAutoConfigDeliveryMapper dcAutoConfigDeliveryMapper, DcAutoInboundMapper autoInboundMapper) { AutoTurnoverService autoTurnoverService, DcBaseWeekCoefficientMapper dcBaseWeekCoefficientMapper, SalesDayConfigMapper salesDayConfigMapper, DateSalesService dateSalesService, DcAutoConfigSkuWarehouseMapper autoConfigSkuWarehouseMapper, List<DateTurnover> dateTurnoverList, DcBasePurchaseMapper dcBasePurchaseMapper, DcAutoConfigDeliveryMapper dcAutoConfigDeliveryMapper, DcAutoInboundMapper autoInboundMapper) {
//source //source
this.dcBaseStock = dcBaseStock; this.dcBaseStock = dcBaseStock;
...@@ -91,6 +91,8 @@ public class AutoTrunoverContext { ...@@ -91,6 +91,8 @@ public class AutoTrunoverContext {
this.dcBaseWeekCoefficientMapper = dcBaseWeekCoefficientMapper; this.dcBaseWeekCoefficientMapper = dcBaseWeekCoefficientMapper;
this.salesDayConfigMapper = salesDayConfigMapper; this.salesDayConfigMapper = salesDayConfigMapper;
this.dateSalesService = dateSalesService; this.dateSalesService = dateSalesService;
this.autoConfigSkuWarehouseMapper = autoConfigSkuWarehouseMapper;
this.dateTurnoverList = dateTurnoverList;
this.dcBasePurchaseMapper = dcBasePurchaseMapper; this.dcBasePurchaseMapper = dcBasePurchaseMapper;
this.dcAutoConfigDeliveryMapper = dcAutoConfigDeliveryMapper; this.dcAutoConfigDeliveryMapper = dcAutoConfigDeliveryMapper;
this.autoInboundMapper = autoInboundMapper; this.autoInboundMapper = autoInboundMapper;
...@@ -355,6 +357,7 @@ public class AutoTrunoverContext { ...@@ -355,6 +357,7 @@ public class AutoTrunoverContext {
private final DateSalesService dateSalesService; private final DateSalesService dateSalesService;
private void calculatePlatformAvgSales() { private void calculatePlatformAvgSales() {
DcAutoSalesMapper mapper = SessionUtil.getSession().getMapper(DcAutoSalesMapper.class); DcAutoSalesMapper mapper = SessionUtil.getSession().getMapper(DcAutoSalesMapper.class);
SalesVolumeAvgDTO ebayAvgSales = mapper.getPlatformHistorySales(dcAutoTurnover.getBailunSku(), dcAutoTurnover.getWarehouseCode(), PlatformType.Ebay.value()); SalesVolumeAvgDTO ebayAvgSales = mapper.getPlatformHistorySales(dcAutoTurnover.getBailunSku(), dcAutoTurnover.getWarehouseCode(), PlatformType.Ebay.value());
dcAutoTurnover.setHistorySevendaySalesEbay(BigDecimal.ZERO); dcAutoTurnover.setHistorySevendaySalesEbay(BigDecimal.ZERO);
...@@ -548,41 +551,44 @@ public class AutoTrunoverContext { ...@@ -548,41 +551,44 @@ public class AutoTrunoverContext {
private List<DateTurnover> dateTurnoverList; private List<DateTurnover> dateTurnoverList;
private final DcBasePurchaseMapper dcBasePurchaseMapper; private final DcBasePurchaseMapper dcBasePurchaseMapper;
private final DcBaseTransferVerifyMapper dcBaseTransferVerifyMapper;
private void ExpectedStorage() { private void expectedStorage() {
if (purchase > 0) { if (dcMidTransit.getQuantityPurchase() > 0) {
List<DcBasePurchase> dcBasePurchaseList;
// 找采购在途的采购单 // 找采购在途的采购单
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) { for (DcBasePurchase dcBasePurchase : dcBasePurchaseList) {
if (dcBasePurchase.getCount() > 0) { if (dcBasePurchase.getCount() > 0) {
LocalDateTime finalEstimatedArrivalTime; 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()); finalEstimatedArrivalTime = dcBasePurchase.getEstimatedArrivalTime().plusDays(dcAutoTurnover.getInspectionDelivery()).plusDays(dcAutoTurnover.getTransferBaleDelivery()).plusDays(dcAutoTurnover.getTransferDelivery()).plusDays(dcAutoTurnover.getAbroadInboundDelivery());
} else {//普通采购单 }
//普通采购单
else {
finalEstimatedArrivalTime = dcBasePurchase.getEstimatedArrivalTime().plusDays(dcAutoTurnover.getInspectionDelivery()); finalEstimatedArrivalTime = dcBasePurchase.getEstimatedArrivalTime().plusDays(dcAutoTurnover.getInspectionDelivery());
} }
int interval = Period.between(recordTime, finalEstimatedArrivalTime.toLocalDate()).getDays(); DateTurnover dateTurnover = this.getDateTurnoverByDate(finalEstimatedArrivalTime.toLocalDate());
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()); dateTurnover.setForecastInboundRelation(dateTurnover.getForecastInboundRelation() + "*" + 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.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) { for (DcBaseTransferVerify dcBaseTransferVerify : dcBaseTransferVerifyList) {
if (dcBaseTransferVerify.getCount() > 0) { if (dcBaseTransferVerify.getCount() > 0) {
LocalDateTime finalEstimatedArrivalTime; LocalDateTime finalEstimatedArrivalTime;
...@@ -591,30 +597,21 @@ public class AutoTrunoverContext { ...@@ -591,30 +597,21 @@ public class AutoTrunoverContext {
} else { } else {
finalEstimatedArrivalTime = dcBaseTransferVerify.getCreateTime().plusDays(dcAutoConfigDelivery.getAbroadInbound()).plusDays(dcAutoConfigDelivery.getTranferBale()).plusDays(dcAutoConfigDelivery.getTranferHead()); finalEstimatedArrivalTime = dcBaseTransferVerify.getCreateTime().plusDays(dcAutoConfigDelivery.getAbroadInbound()).plusDays(dcAutoConfigDelivery.getTranferBale()).plusDays(dcAutoConfigDelivery.getTranferHead());
} }
int interval = Period.between(recordTime, finalEstimatedArrivalTime.toLocalDate()).getDays(); DateTurnover dateTurnover = this.getDateTurnoverByDate(finalEstimatedArrivalTime.toLocalDate());
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.setForecastInboundRelation(dateTurnover.getForecastInboundRelation() + "*" + Constant.TRANSFER_SIGN + dcBaseTransferVerify.getTransferOrderId() + "_" + dcBaseTransferVerify.getCount());
//todo fba的调拨在途,切换读我做的一个新表(表结构构建中) //todo fba的调拨在途,切换读我做的一个新表(表结构构建中)
try { DcBaseWarehouse dcBaseWarehouse = dcBaseWarehouseMapper.selectByWarehouseCode(dcAutoTurnover.getWarehouseCode())
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));
}
} finally { if (!dcBaseWarehouse.getSystemFlag().toUpperCase().equals(PlatformType.FBA.value())) {
SessionUtil.closeSession(); //预测调拨入库
dateTurnover.setForecastTransferInbound(dateTurnover.getForecastTransferInbound().add(new BigDecimal(dcBaseTransferVerify.getCount())));
//预测入库
dateTurnover.setForecastInbound(dateTurnover.getForecastPurchaseInbound().add(dateTurnover.getForecastTransferInbound()));
} }
} }
} }
} }
} }
...@@ -727,174 +724,101 @@ public class AutoTrunoverContext { ...@@ -727,174 +724,101 @@ public class AutoTrunoverContext {
} }
} }
private Integer fbaAdvise() { //通过SKU和仓库拿到实际库存
private final Integer realInventory;
BigDecimal inboundDecimal;//入库数量 private DateTurnover getDateTurnoverByDate(LocalDate localDate) {
BigDecimal forecastInventory;//预测库存 return dateTurnoverList.stream()
BigDecimal shortSupply;//缺货数量 .filter(dateTurnover -> dateTurnover.getDate().equals(localDate))
BigDecimal addShortSupply;// 补断货的数量 .findAny()
int shortSupplyDays = 0;//断货天数 .orElse(null)
int shortSupplyIndex = -1;//断货天索引 }
int fbaTransferIndex = 1;
for (int j = 0; j < autoForecastDay; j++) { private void fxx() {
BigDecimal forecastSalesItem = forecastSalesList.get(j); dateTurnoverList.forEach(dateTurnover -> {
inboundDecimal = BigDecimal.valueOf(forecastInboundList.get(j)); //昨天的周转预测
totalInbound = totalInbound.add(inboundDecimal); DateTurnover lastDateTurnover = this.getDateTurnoverByDate(dateTurnover.getDate().minusDays(1));
if (j == turnoverDays) { //昨天预测缺货
dcAutoTurnover.setTurnoverInbound(totalInbound); if (lastDateTurnover.getForecastShortSupply().compareTo(BigDecimal.ZERO) > 0) {
dateTurnover.setForecastSales(BigDecimal.ZERO);
dateTurnover.setForecastSalesExplain("昨天预测缺货");
//处理自动周转预测断货和冗余波动
this.handleAutoFastestStorage(dateTurnover);
} }
});
}
if (j == 0) { //j == 0表示, 周转计算的当天 //return 库存可用天数
if (outStock > 0) { //在两倍周转期内, 如果预测销量 <= 库存, 那么又是可用的一天
forecastSalesList.set(j, BigDecimal.ZERO); private Integer fbaAdvise() {
forecastSalesExplainList.set(j, "0, 昨天真实缺货");
shortSupplyIndex = j; dateTurnoverList.forEach(dateTurnover -> {
//如果有缺货数, 第一天预计库存 = 预计入库 - 缺货数 //result
forecastInventory = BigDecimal.valueOf((forecastInboundList.get(j).doubleValue() - outStock.doubleValue())); //预计库存
shortSupply = forecastInventory.compareTo(BigDecimal.ZERO) < 0 ? forecastInventory.abs() : BigDecimal.ZERO;//库存补入后的 缺货数 BigDecimal forecastInventory;
BigDecimal subtract = forecastSalesList.get(j).subtract(forecastInventory.compareTo(BigDecimal.ZERO) > 0 ? forecastInventory : BigDecimal.ZERO);//今天的缺货数 //缺货数量
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; 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表示, 周转计算之后的天数 else {
if (forecastShortSupplyList.get(j - 1).compareTo(BigDecimal.ZERO) > 0) {//是断货 //第一天预计库存 = 真实库存 + 预计入库
forecastSalesList.set(j, BigDecimal.ZERO); forecastInventory = dateTurnover.getForecastInbound().add(new BigDecimal(realInventory));
forecastSalesExplainList.set(j, "昨天预测缺货"); BigDecimal subtract = dateTurnover.getForecastSales().subtract(forecastInventory);
if (shortSupplyIndex < 0) { shortSupply = subtract.compareTo(BigDecimal.ZERO) > 0 ? subtract : BigDecimal.ZERO;
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;
}
} }
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 //为负的情况下, 应该为0
if (forecastInventory.compareTo(BigDecimal.ZERO) < 0) { if (forecastInventory.compareTo(BigDecimal.ZERO) < 0) {
forecastInventory = BigDecimal.ZERO; forecastInventory = BigDecimal.ZERO;
} }
//库存先补断 //库存补断货数量 = 这天的预测库存 - 昨天预计缺
addShortSupply = forecastInventory.subtract(forecastShortSupplyList.get(j - 1)); addShortSupply = forecastInventory.subtract(lastDateTurnover.getForecastShortSupply());
if (addShortSupply.compareTo(BigDecimal.ZERO) < 0) { if (addShortSupply.compareTo(BigDecimal.ZERO) < 0) {
forecastInventory = BigDecimal.ZERO; forecastInventory = BigDecimal.ZERO;
forecastShortSupplyList.set(j, addShortSupply.abs()); dateTurnover.setForecastShortSupply(addShortSupply.abs());
} else { } else {
forecastShortSupplyList.set(j, BigDecimal.ZERO); dateTurnover.setForecastShortSupply(BigDecimal.ZERO);
forecastInventory = addShortSupply; forecastInventory = addShortSupply;
} }
BigDecimal subtract = forecastSalesList.get(j).subtract(forecastInventory);//今日断货 //今日断货
BigDecimal subtract = dateTurnover.getForecastSales().subtract(forecastInventory);
shortSupply = subtract.compareTo(BigDecimal.ZERO) > 0 ? subtract : BigDecimal.ZERO; 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)); private void handleAutoFastestStorage(DateTurnover dateTurnover) {
}
return inventoryAvailableDays;
} }
private void handleForecastFluctuation() { private void handleForecastFluctuation() {
...@@ -1065,12 +989,11 @@ public class AutoTrunoverContext { ...@@ -1065,12 +989,11 @@ public class AutoTrunoverContext {
//计算周转显示销量 //计算周转显示销量
dateTurnoverList.forEach(DateTurnover::calcShowSales); dateTurnoverList.forEach(DateTurnover::calcShowSales);
ExpectedStorage(forecastInboundRelationList, purchase, transfer, recordTime, dcAutoTurnover, forecastPurchaseInboundList, forecastTransferInboundList, forecastInboundList); this.expectedStorage();
//通过SKU和仓库拿到实际库存 //通过SKU和仓库拿到实际库存
Integer realInventory = (dcBaseStock != null && dcBaseStock.getUsableStock() != null) ? dcBaseStock.getUsableStock() : 0; Integer realInventory = (dcBaseStock != null && dcBaseStock.getUsableStock() != null) ? dcBaseStock.getUsableStock() : 0;
BigDecimal totalSafeInventory = calculateSafeInventory(); BigDecimal totalSafeInventory = calculateSafeInventory();
Integer moq = dcBaseSku.getMoq(); Integer moq = dcBaseSku.getMoq();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment