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;//入库数量
BigDecimal forecastInventory;//预测库存 private DateTurnover getDateTurnoverByDate(LocalDate localDate) {
BigDecimal shortSupply;//缺货数量 return dateTurnoverList.stream()
BigDecimal addShortSupply;// 补断货的数量 .filter(dateTurnover -> dateTurnover.getDate().equals(localDate))
int shortSupplyDays = 0;//断货天数 .findAny()
int shortSupplyIndex = -1;//断货天索引 .orElse(null)
}
int fbaTransferIndex = 1;
private void fxx() {
for (int j = 0; j < autoForecastDay; j++) { dateTurnoverList.forEach(dateTurnover -> {
BigDecimal forecastSalesItem = forecastSalesList.get(j); //昨天的周转预测
inboundDecimal = BigDecimal.valueOf(forecastInboundList.get(j)); DateTurnover lastDateTurnover = this.getDateTurnoverByDate(dateTurnover.getDate().minusDays(1));
totalInbound = totalInbound.add(inboundDecimal); //昨天预测缺货
if (j == turnoverDays) { if (lastDateTurnover.getForecastShortSupply().compareTo(BigDecimal.ZERO) > 0) {
dcAutoTurnover.setTurnoverInbound(totalInbound); dateTurnover.setForecastSales(BigDecimal.ZERO);
} dateTurnover.setForecastSalesExplain("昨天预测缺货");
//处理自动周转预测断货和冗余波动
if (j == 0) { //j == 0表示, 周转计算的当天 this.handleAutoFastestStorage(dateTurnover);
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);//今天的缺货数
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++; //return 库存可用天数
fbaTransferIndex++; //在两倍周转期内, 如果预测销量 <= 库存, 那么又是可用的一天
} else { private Integer fbaAdvise() {
if (shortSupplyIndex == 0) {
//尽量降序找一个不为0的历史销量
for (int i = historySalesList.size() - 1; i >= 0; i--) {
if (historySalesList.get(i) > 0) {
break;
}
}
shortSupplyIndex = -1; dateTurnoverList.forEach(dateTurnover -> {
shortSupplyDays = 0; //result
} else if (shortSupplyIndex > 0) { //预计库存
//尽量降序找一个不为0的预测销量 BigDecimal forecastInventory;
BigDecimal forecastSaleGTZero = null; //缺货数量
for (int i = shortSupplyIndex; i >= 0; i--) { BigDecimal shortSupply;
forecastSaleGTZero = BigDecimal.ZERO; //// 补断货的数量
if (forecastSalesList.get(i).compareTo(BigDecimal.ZERO) > 0) { BigDecimal addShortSupply;
forecastSaleGTZero = forecastSalesList.get(i); //当天
break; if (dateTurnover.getDate().equals(LocalDate.now())) {
} //缺货>0
} if (dcMidTransit.getQuantityOutStock() > 0) {
//按照规则递减或递增 j = 63
for (int i = 0; i <= shortSupplyDays; i++) { //预测销量0
BigDecimal result = forecastSaleGTZero.multiply(Constant.FBA_OUT_STOCK_DECREASE.pow(shortSupplyDays)).multiply(Constant.FBA_OUT_STOCK_INCREMENT.pow(i)).setScale(3, RoundingMode.HALF_EVEN); dateTurnover.setForecastSales(BigDecimal.ZERO);
//索引越界 dateTurnover.setForecastSalesExplain("0, 昨天真实缺货");
if (j + i < forecastSalesList.size()) {
forecastSalesList.set(j + i - 1, result); //预计库存: 第一天预计库存 = 预计入库 - 缺货数
if (i == 0) { forecastInventory = dateTurnover.getForecastInbound().subtract(new BigDecimal(dcMidTransit.getQuantityOutStock()));
forecastSalesExplainList.set(j + i, "基于" + shortSupplyDays + "天断货累积递减"); ////库存补入后的 缺货数
} else { shortSupply = forecastInventory.compareTo(BigDecimal.ZERO) < 0 ? forecastInventory.abs() : BigDecimal.ZERO;
forecastSalesExplainList.set(j + i, "基于预测销量递增第" + i + "天"); //今天的缺货数
} 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;
} }
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;
} }
//预测缺货数量
dateTurnover.setForecastShortSupply(shortSupply);
} }
forecastInventory = inboundDecimal.add(forecastInventoryList.get(j - 1)).subtract(forecastSalesList.get(j - 1)); //计算当天之后的天数
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