Commit 18e212c5 by huluobin

销量预测算法修改

parent 93984b04
......@@ -31,6 +31,20 @@
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-client</artifactId>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
......@@ -59,29 +73,55 @@
<artifactId>commons-beanutils</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<!-- &lt;!&ndash; https://mvnrepository.com/artifact/org.slf4j/slf4j-api &ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>org.slf4j</groupId>-->
<!-- <artifactId>slf4j-api</artifactId>-->
<!-- </dependency>-->
<!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
<!-- &lt;!&ndash; https://mvnrepository.com/artifact/ch.qos.logback/logback-classic &ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>ch.qos.logback</groupId>-->
<!-- <artifactId>logback-classic</artifactId>-->
<!-- </dependency>-->
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>RELEASE</version>
<scope>test</scope>
</dependency>
<!-- 自动生成接口文档 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
</dependency>
<!--mp 增加Mybatis-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<!--mp 代码生成工具-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
</dependency>
<!--freemarker作为模板-->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</dependency>
</dependencies>
<build>
......@@ -110,4 +150,4 @@
</resource>
</resources>
</build>
</project>
\ No newline at end of file
</project>
package com.bailuntec.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.time.LocalDateTime;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* <p>
* 销量预测配置表
* </p>
*
* @author robbendev
* @since 2020-08-13
*/
@Data
@EqualsAndHashCode(callSuper = false)
@ApiModel(value="DcAutoSalesForecastConfig对象", description="销量预测配置表")
public class DcAutoSalesForecastConfig implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
@ApiModelProperty(value = "规则描述")
private String title;
@ApiModelProperty(value = "仓库类型,可以留空 例:中国仓, dc_base_warehouse.hq_type")
private String warehouseType;
@ApiModelProperty(value = "国家,可以留空 例:美国,dc_base_warehouse.area_id")
private String warehouseAreaId;
@ApiModelProperty(value = "仓库编码,可以留空 dc_base_warehouse.warehouse_code ")
private String warehouseCode;
@ApiModelProperty(value = "类目,例:推荐普货 dc_base_sku.product_type")
private String category;
@ApiModelProperty(value = "一个sku 同时命中多条规则时,数字越大优先")
private Integer level;
@ApiModelProperty(value = "是否作废 1-作废 0-正常")
private Integer isDelete;
@ApiModelProperty(value = "创建时间")
private LocalDateTime createDate;
@ApiModelProperty(value = "筛选类型 1 =根据入库时间筛选 2 = 根据销量筛选")
private Integer screenType;
@ApiModelProperty(value = "作废时间")
private LocalDateTime deleteTime;
}
package com.bailuntec.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* <p>
* 销量预测 商品编码 配置
* </p>
*
* @author robbendev
* @since 2020-08-13
*/
@Data
@EqualsAndHashCode(callSuper = false)
@ApiModel(value="DcAutoSalesForecastProductCodeConfig对象", description="销量预测 商品编码 配置")
public class DcAutoSalesForecastProductCodeConfig implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
private Integer configId;
@ApiModelProperty(value = "dc_base_sku.product_code")
private String productCode;
}
package com.bailuntec.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* <p>
* 销量预测sku配置
* </p>
*
* @author robbendev
* @since 2020-08-13
*/
@Data
@EqualsAndHashCode(callSuper = false)
@ApiModel(value="DcAutoSalesForecastSkuConfig对象", description="销量预测sku配置")
public class DcAutoSalesForecastSkuConfig implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
private Integer configId;
private String bailunSku;
}
package com.bailuntec.domain.entity;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* <p>
* 销量预测阶段
* </p>
*
* @author robbendev
* @since 2020-08-13
*/
@Data
@EqualsAndHashCode(callSuper = false)
@ApiModel(value="DcAutoSalesForecastStageConfig对象", description="销量预测阶段")
public class DcAutoSalesForecastStageConfig implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
@ApiModelProperty(value = "配置主表id")
private Integer configId;
@ApiModelProperty(value = "首次入库距今多少时长(dc_auto_sales_forecast_config.screen_type==1 时生效),0 代表未配置。首次入库取值:dc_base_stock.first_inbound_date")
private Integer durationUpperLimit;
@ApiModelProperty(value = "首次入库距今多少时长(dc_auto_sales_forecast_config.screen_type==1 时生效),0 代表未配置。首次入库取值:dc_base_stock.first_inbound_date")
private Integer durationLowerLimit;
@ApiModelProperty(value = "销量上限(dc_auto_sales_forecast_config.screen_type==2 时生效),例:10.1,加权日均销量 <= 10.1; dc_auto_turnover.daily_weighted_sales (注意:这个字段正是周转算法要算的不能直接取)")
private BigDecimal salesUpperLimit;
@ApiModelProperty(value = "销量下限(dc_auto_sales_forecast_config.screen_type==2 时生效),例:0 加权日均销量 >= 0; dc_auto_turnover.daily_weighted_sales")
private BigDecimal salesLowerLimit;
@ApiModelProperty(value = "阶段顺序")
private Integer index;
@ApiModelProperty(value = "时间段一的比例,例:0.33 代表 从今天 ~ (供应链长度*0.33)天 的日期全部采用第一时间段的算法;")
private BigDecimal oneRatio;
@ApiModelProperty(value = "时间段二的比例")
private BigDecimal twoRatio;
@ApiModelProperty(value = "时间段三的比例")
private BigDecimal threeRatio;
@ApiModelProperty(value = "时间段一的第一个变量 (过去n1天销量)*(n2)+(过去n3天销量)*(n4)+(过去n5天销量)*(n6)")
private BigDecimal oneN1;
@ApiModelProperty(value = "时间段一的第二个变量")
private BigDecimal oneN2;
@ApiModelProperty(value = "时间段一的第三个变量 ")
private BigDecimal oneN3;
@ApiModelProperty(value = "时间段一的第四个变量 ")
private BigDecimal oneN4;
@ApiModelProperty(value = "时间段一的第五个变量 ")
private BigDecimal oneN5;
@ApiModelProperty(value = "时间段一的第六个变量 ")
private BigDecimal oneN6;
@ApiModelProperty(value = "时间段二的第一个变量 (过去n1天销量)*(n2)+(过去n3天销量)*(n4)+(过去n5天销量)*(n6)")
private BigDecimal twoN1;
@ApiModelProperty(value = "时间段二的第二个变量")
private BigDecimal twoN2;
@ApiModelProperty(value = "时间段二的第三个变量 ")
private BigDecimal twoN3;
@ApiModelProperty(value = "时间段二的第四个变量 ")
private BigDecimal twoN4;
@ApiModelProperty(value = "时间段二的第五个变量 ")
private BigDecimal twoN5;
@ApiModelProperty(value = "时间段二的第六个变量 ")
private BigDecimal twoN6;
@ApiModelProperty(value = "时间段三的第一个变量 (过去n1天销量)*(n2)+(过去n3天销量)*(n4)+(过去n5天销量)*(n6)")
private BigDecimal threeN1;
@ApiModelProperty(value = "时间段三的第二个变量")
private BigDecimal threeN2;
@ApiModelProperty(value = "时间段三的第三个变量 ")
private BigDecimal threeN3;
@ApiModelProperty(value = "时间段三的第四个变量 ")
private BigDecimal threeN4;
@ApiModelProperty(value = "时间段三的第五个变量 ")
private BigDecimal threeN5;
@ApiModelProperty(value = "时间段三的第六个变量 ")
private BigDecimal threeN6;
}
package com.bailuntec.mapper;
import com.bailuntec.domain.entity.DcAutoSalesForecastConfig;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* 销量预测配置表 Mapper 接口
* </p>
*
* @author robbendev
* @since 2020-08-13
*/
public interface DcAutoSalesForecastConfigMapper extends BaseMapper<DcAutoSalesForecastConfig> {
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.bailuntec.mapper.DcAutoSalesForecastConfigMapper">
</mapper>
package com.bailuntec.mapper;
import com.bailuntec.domain.entity.DcAutoSalesForecastProductCodeConfig;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* 销量预测 商品编码 配置 Mapper 接口
* </p>
*
* @author robbendev
* @since 2020-08-13
*/
public interface DcAutoSalesForecastProductCodeConfigMapper extends BaseMapper<DcAutoSalesForecastProductCodeConfig> {
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.bailuntec.mapper.DcAutoSalesForecastProductCodeConfigMapper">
</mapper>
package com.bailuntec.mapper;
import com.bailuntec.domain.entity.DcAutoSalesForecastSkuConfig;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* 销量预测sku配置 Mapper 接口
* </p>
*
* @author robbendev
* @since 2020-08-13
*/
public interface DcAutoSalesForecastSkuConfigMapper extends BaseMapper<DcAutoSalesForecastSkuConfig> {
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.bailuntec.mapper.DcAutoSalesForecastSkuConfigMapper">
</mapper>
package com.bailuntec.mapper;
import com.bailuntec.domain.entity.DcAutoSalesForecastStageConfig;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
/**
* <p>
* 销量预测阶段 Mapper 接口
* </p>
*
* @author robbendev
* @since 2020-08-13
*/
public interface DcAutoSalesForecastStageConfigMapper extends BaseMapper<DcAutoSalesForecastStageConfig> {
/**
* <p>
* 查询周转sku命中的规则
* </p>
*
* @param bailunSku bailunSku
* @param warehouseCode 仓库编码
* @return 命中的预测规则
*/
DcAutoSalesForecastStageConfig selectMatchStage(@Param("bailunSku") String bailunSku, @Param("warehouseCode") String warehouseCode);
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.bailuntec.mapper.DcAutoSalesForecastStageConfigMapper">
<select id="selectMatchStage" resultType="com.bailuntec.domain.entity.DcAutoSalesForecastStageConfig">
SELECT t7.* from dc_auto_turnover t1
LEFT JOIN dc_base_sku t2 on t1.bailun_sku =t2.bailun_sku
LEFT JOIN dc_base_stock t8 on t1.bailun_sku = t8.bailun_sku and t1.warehouse_code = t8.warehouse_code
LEFT JOIN dc_base_warehouse t6 on t1.warehouse_code = t6.warehouse_code
LEFT JOIN dc_auto_sales_forecast_sku_config t3 on t1.bailun_sku = t3.bailun_sku
LEFT JOIN dc_auto_sales_forecast_product_code_config t4 on t2.product_code = t4.product_code
LEFT JOIN dc_auto_sales_forecast_config t5 on (t3.config_id =t5.id or t5.id not in (select config_id from dc_auto_sales_forecast_sku_config))
and (t4.config_id = t5.id or t5.id not in (select config_id from dc_auto_sales_forecast_product_code_config))
and (t6.warehouse_code = t5.warehouse_code or length(trim(t5.warehouse_code)) = 0)
and (t6.hq_type = t5.warehouse_type or length(trim(t5.warehouse_type)) = 0)
and (t2.product_type = t5.category or length(trim(t5.category)) = 0)
and (t6.area_id = t5.warehouse_area_id or length(trim(t5.warehouse_area_id)) = 0)
LEFT JOIN dc_auto_sales_forecast_stage_config t7 on t7.config_id =t5.id
and (IF(t5.screen_type =1,
t8.first_inbound_date &lt;= t7.duration_upper_limit or t8.first_inbound_date &gt;= t7.duration_lower_limit or t8.first_inbound_date is null or length(trim(t8.first_inbound_date)) = 0,
t1.daily_weighted_sales &lt;= t7.sales_upper_limit or t1.daily_weighted_sales &gt;= t7.sales_lower_limit or t1.daily_weighted_sales is null or length(trim(t1.daily_weighted_sales)) = 0))
where t1.bailun_sku =#{bailunSku} and t1.warehouse_code = #{warehouseCode}
and t5.id is not null
ORDER BY t5.`level` desc
limit 1
</select>
</mapper>
......@@ -130,9 +130,23 @@ public interface DcBaseOmsSkuMapper {
List<Double> listFbaFee(@Param("bailunSku") String bailunSku, @Param("website") String website, @Param("timeInterval") int timeInterval);
BigDecimal selectFBAFee(@Param("bailunSku") String bailunSku, @Param("webSite") String webSite, @Param("paidTime")LocalDateTime paidTime);
BigDecimal selectFBAFee(@Param("bailunSku") String bailunSku, @Param("webSite") String webSite, @Param("paidTime") LocalDateTime paidTime);
BigDecimal selectCostPlatformFee(@Param("bailunSku") String bailunSku, @Param("platformType") String platformType, @Param("webSite") String webSite);
DcBaseOmsSku selectOneByCreateTime(@Param("bailunSku") String bailunSku);
}
\ No newline at end of file
/**
* <p>
* 过去过去的sku销量
* </p>
*
* @param lowerTime lowerTime
* @param upperTime upperTime
* @return sku销量
*/
Integer omsSkuSellerCount(@Param("lowerTime") LocalDateTime lowerTime,
@Param("upperTime") LocalDateTime upperTime,
@Param("bailunSku") String bailunSku,
@Param("warehouseCode") String warehouseCode);
}
This source diff could not be displayed because it is too large. You can view the blob instead.
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<configuration scan="true" scanPeriod="60 seconds" debug="true">
<!-- 彩色日志格式 -->
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
<conversionRule conversionWord="wex"
converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
<conversionRule conversionWord="wEx"
converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
<property name="log.context.name" value="data-base" />
<property name="log.charset" value="UTF-8" />
<property name="log.pattern" value="[%-5level] %date --%thread-- [%logger] %msg %n" />
<contextName>${log.context.name}</contextName>
<property name="CONSOLE_LOG_PATTERN"
value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<!--控制台日志输出-->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder charset="${log.charset}">
<pattern>${log.pattern}</pattern>
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset class="java.nio.charset.Charset">UTF-8</charset>
</encoder>
</appender>
<root>
<!--<level value="DEBUG" />-->
<level value="INFO" />
<appender-ref ref="STDOUT" />
<property name="contextName" value="data-center"/>
<contextName>${contextName}</contextName>
   
<logger name="com.bailuntec" level="DEBUG"/>
<logger name="org.apache.zookeeper" level="WARN"/>
<logger name="org.apache.curator" level="WARN"/>
<logger name="org.springframework" level="INFO"/>
<root level="INFO" additivity="false">
<appender-ref ref="STDOUT"/>
</root>
<logger name="org.apache.zookeeper" level="WARN" />
<logger name="org.apache.curator" level="WARN" />
</configuration>
\ No newline at end of file
</configuration>
......@@ -28,7 +28,7 @@
</environments>
<mappers>
<package name="com.bailuntec.mapper"></package>
<package name="com.bailuntec.mapper"/>
</mappers>
</configuration>
\ No newline at end of file
</configuration>
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class CodeGenerator {
/**
* <p>
* 读取控制台内容
* </p>
*/
public static String scanner(String tip) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入" + tip + ":");
if (scanner.hasNext()) {
String ipt = scanner.next();
if (StringUtils.isNotEmpty(ipt)) {
return ipt;
}
}
throw new MybatisPlusException("请输入正确的" + tip + "!");
}
public static void main(String[] args) {
// 代码生成器
AutoGenerator mpg = new AutoGenerator();
// 全局配置
GlobalConfig gc = new GlobalConfig();
String projectPath = System.getProperty("user.dir");
gc.setOutputDir(projectPath + "/data-common/src/main/java");
gc.setAuthor("robbendev");
gc.setOpen(false);
gc.setSwagger2(true);
gc.setIdType(IdType.AUTO);
// 实体属性 Swagger2 注解
mpg.setGlobalConfig(gc);
// 数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://gz-cdb-kp7s5i79.sql.tencentcdb.com:61691/bailun_datacenter?serverTimezone=GMT%2B8&characterEncoding=utf-8");
// dsc.setSchemaName("public");
dsc.setDriverName("com.mysql.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("#7kfnymAM$Y9-Ntf");
mpg.setDataSource(dsc);
// 包配置
PackageConfig pc = new PackageConfig();
pc.setParent("com.bailuntec");
pc.setEntity("domain.entity");
pc.setService("application");
pc.setServiceImpl(null);
pc.setService(null);
pc.setMapper("mapper");
pc.setController(null);
mpg.setPackageInfo(pc);
// 自定义配置
InjectionConfig cfg = new InjectionConfig() {
@Override
public void initMap() {
// to do nothing
}
};
// 如果模板引擎是 freemarker
String templatePath = "/templates/mapper.xml.ftl";
// 如果模板引擎是 velocity
// String templatePath = "/templates/mapper.xml.vm";
// 自定义输出配置
List<FileOutConfig> focList = new ArrayList<>();
// 自定义配置会被优先输出
focList.add(new FileOutConfig(templatePath) {
@Override
public String outputFile(TableInfo tableInfo) {
// 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
return projectPath + "/data-common/src/main/java/com/bailuntec/mapper/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
}
});
cfg.setFileOutConfigList(focList);
mpg.setCfg(cfg);
// 配置模板
TemplateConfig templateConfig = new TemplateConfig();
templateConfig.setXml(null);
mpg.setTemplate(templateConfig);
// 策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setNaming(NamingStrategy.underline_to_camel);
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
// strategy.setSuperEntityColumns("create_time", "last_update_time", "record_state", "source_from", "create_user_id", "create_user_name");
strategy.setEntityLombokModel(true);
strategy.setRestControllerStyle(false);
strategy.setControllerMappingHyphenStyle(false);
// strategy.setVersionFieldName("version");
strategy.setInclude(scanner("表名,多个英文逗号分割").split(","));
strategy.setControllerMappingHyphenStyle(true);
strategy.setTablePrefix(pc.getModuleName() + "_");
mpg.setStrategy(strategy);
mpg.setTemplateEngine(new FreemarkerTemplateEngine());
mpg.execute();
}
}
package com.bailuntec.mapper;
import com.bailuntec.domain.entity.DcAutoSalesForecastStageConfig;
import com.bailuntec.utils.SessionUtil;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
/**
* <p>
*
* </p>
*
* @author robbendev
* @since 2020/8/13 3:34 下午
*/
class DcAutoSalesForecastStageConfigMapperTest {
@Test
void selectMatchStage() {
DcAutoSalesForecastStageConfigMapper dcAutoSalesForecastStageConfigMapper = SessionUtil.getSession().getMapper(DcAutoSalesForecastStageConfigMapper.class);
DcAutoSalesForecastStageConfig dcAutoSalesForecastStageConfig = dcAutoSalesForecastStageConfigMapper.selectMatchStage("946776911", "GZBLWH");
}
}
......@@ -3,9 +3,9 @@ package com.bailuntec.serviceImpl;
import com.bailuntec.dao.DcAccountingEntryTaskDao;
import com.bailuntec.domain.entity.DcAccountingEntryTask;
import com.bailuntec.service.AccountingEntryService;
import com.qiniu.common.Region;
import com.qiniu.http.Response;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.Region;
import com.qiniu.storage.UploadManager;
import com.qiniu.util.Auth;
import lombok.extern.slf4j.Slf4j;
......
......@@ -47,6 +47,13 @@
<docker-maven-plugin.version>1.2.0</docker-maven-plugin.version>
<jedis.version>3.0.1</jedis.version>
<skipDockerBuild>true</skipDockerBuild>
<spring-boot.version>2.0.3.RELEASE</spring-boot.version>
<mybatis-plus-generator.version>3.3.2</mybatis-plus-generator.version>
<mybatis-plus-boot-starter.version>3.3.2</mybatis-plus-boot-starter.version>
<springfox-swagger2.version>2.9.2</springfox-swagger2.version>
<spring-cloud.version>Finchley.SR4</spring-cloud.version>
<freemarker.version>2.3.28</freemarker.version>
<curator.version>2.10.0</curator.version>
</properties>
......@@ -79,6 +86,37 @@
<groupId>com.dangdang</groupId>
<artifactId>elastic-job-lite-core</artifactId>
<version>${elastic-job-lite-core.version}</version>
<exclusions>
<exclusion>
<artifactId>curator-client</artifactId>
<groupId>org.apache.curator</groupId>
</exclusion>
<exclusion>
<artifactId>curator-framework</artifactId>
<groupId>org.apache.curator</groupId>
</exclusion>
<exclusion>
<artifactId>curator-recipes</artifactId>
<groupId>org.apache.curator</groupId>
</exclusion>
</exclusions>
</dependency>
<!--避免继承springcloud冲突-->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>${curator.version}</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-client</artifactId>
<version>${curator.version}</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>${curator.version}</version>
</dependency>
<!--pagehelper-->
......@@ -147,12 +185,6 @@
<version>${commons-beanutils.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
<dependency>
......@@ -161,12 +193,6 @@
<version>${log4j.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-slf4j-impl -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>${log4j.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
......@@ -175,13 +201,6 @@
<version>${slf4j.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-simple -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp -->
<dependency>
......@@ -217,13 +236,60 @@
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<!-- 自动生成接口文档 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${springfox-swagger2.version}</version>
</dependency>
<!--freemarker作为模板-->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>${freemarker.version}</version>
</dependency>
<!--mp 增加Mybatis-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus-generator.version}</version>
</dependency>
<!--mp 代码生成工具-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>${mybatis-plus-generator.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
......@@ -268,4 +334,4 @@
</resource>
</resources>
</build>
</project>
\ No newline at end of file
</project>
......@@ -15,18 +15,27 @@
<dependency>
<groupId>com.bailuntec</groupId>
<artifactId>data-common</artifactId>
<exclusions>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>RELEASE</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
......@@ -80,4 +89,4 @@
</resources>
</build>
</project>
\ No newline at end of file
</project>
......@@ -14,10 +14,15 @@ import com.dangdang.ddframe.job.reg.base.CoordinatorRegistryCenter;
import com.dangdang.ddframe.job.reg.zookeeper.ZookeeperConfiguration;
import com.dangdang.ddframe.job.reg.zookeeper.ZookeeperRegistryCenter;
import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import javax.sql.DataSource;
@Slf4j
@MapperScan("com.bailuntec.mapper")
public class Application {
private static PropertiesUtil propertiesUtil = PropertiesUtil.getInstance("job");
private static final String EVENT_RDB_STORAGE_DRIVER = propertiesUtil.getPropertyAsString("EVENT_RDB_STORAGE_DRIVER");
......@@ -33,19 +38,13 @@ public class Application {
createJobConfigurationNormal(),
createJobEventConfiguration(),
new AutoTurnoverJobListener()).init();
//
new JobScheduler(createRegistryCenter(),
createJobConfigurationIncrement(),
createJobEventConfiguration(),
new AutoTurnoverJobListener()).init();
new JobScheduler(createRegistryCenter(),
createJobConfigurationTest(),
createJobEventConfiguration(),
new AutoTurnoverJobListener()).init();
log.info("start success");
}
private static CoordinatorRegistryCenter createRegistryCenter() {
......@@ -77,17 +76,6 @@ public class Application {
return LiteJobConfiguration.newBuilder(simpleJobConfig).build();
}
private static LiteJobConfiguration createJobConfigurationTest() {
JobCoreConfiguration simpleCoreConfig = JobCoreConfiguration.newBuilder(
"XXXX",
"0 25 17 * * ?",
propertiesUtil.getPropertyAsInt("SHARDING_TOTAL_COUNT_INCREMENT"))
.jobParameter("INCREMENT")
.build();
SimpleJobConfiguration simpleJobConfig = new SimpleJobConfiguration(simpleCoreConfig, AutoTurnoverJob.class.getCanonicalName());
return LiteJobConfiguration.newBuilder(simpleJobConfig).build();
}
private static JobEventConfiguration createJobEventConfiguration() {
return new JobEventRdbConfiguration(setUpEventTraceDataSource());
......
......@@ -11,6 +11,10 @@ import com.bailuntec.domain.entity.*;
import com.bailuntec.domain.enumerate.PlatformType;
import com.bailuntec.domain.example.*;
import com.bailuntec.mapper.*;
import com.bailuntec.service.AutoSalesService;
import com.bailuntec.service.AutoTurnoverService;
import com.bailuntec.service.impl.AutoSalesServiceImpl;
import com.bailuntec.service.impl.AutoTurnoverServiceImpl;
import com.bailuntec.support.PointJob;
import com.bailuntec.utils.DigestUtils;
import com.bailuntec.utils.OkHttpUtil;
......@@ -38,9 +42,10 @@ import java.util.concurrent.atomic.AtomicInteger;
@Slf4j
public class AutoTurnoverJob extends PointJob {
private AutoSalesServiceImpl autoSalesServiceImpl = new AutoSalesServiceImpl();
private AutoSalesService autoSalesService = new AutoSalesServiceImpl();
private PropertiesUtil propertiesUtil = PropertiesUtil.getInstance("const");
private OkHttpClient client = OkHttpUtil.getInstance();
private AutoTurnoverService autoTurnoverService = new AutoTurnoverServiceImpl();
@Override
public void executeJob(ShardingContext shardingContext, JobPointLog jobPointLog) {
......@@ -231,7 +236,7 @@ public class AutoTurnoverJob extends PointJob {
dcAutoSalesMapper.insertSelective(dcAutoSales);
}
} else {
dcAutoSales = autoSalesServiceImpl.forecastSalesBySalesVolumeDTO(salesVolumeDTO);
dcAutoSales = autoSalesService.forecastSalesBySalesVolumeDTO(salesVolumeDTO);
}
DcAutoWarehouseweekSalesMapper dcAutoWarehouseweekSalesMapper = SessionUtil.getSession().getMapper(DcAutoWarehouseweekSalesMapper.class);
......@@ -652,6 +657,8 @@ public class AutoTurnoverJob extends PointJob {
dcAutoTurnover.setIs_out_stock(0);
dcAutoTurnover.setGmtModified(LocalDateTime.now());
autoTurnoverService.setAutoTurnoverSaleDetails(dcAutoTurnover);
int i = autoTurnoverMapper.updateByExampleSelective(dcAutoTurnover, DcAutoTurnoverExample.newAndCreateCriteria().andBailunSkuEqualTo(dcAutoTurnover.getBailunSku()).andWarehouseCodeEqualTo(dcAutoTurnover.getWarehouseCode()).example());
if (i == 0) {
autoTurnoverMapper.insertSelective(dcAutoTurnover);
......
package com.bailuntec.service;
public interface AutoSalesService {
import com.bailuntec.domain.dto.SalesVolumeDTO;
import com.bailuntec.domain.entity.DcAutoSales;
public interface AutoSalesService {
DcAutoSales forecastSalesBySalesVolumeDTO(SalesVolumeDTO salesVolumeDTO) throws Exception;
}
package com.bailuntec.service;
import com.bailuntec.domain.entity.DcAutoTurnover;
/**
* <p>
*
* </p>
*
* @author robbendev
* @since 2020/8/13 2:09 下午
*/
public interface AutoTurnoverService {
/**
* <p>
* 计算设置autoTurnover销售预测
* </p>
*
* @param dcAutoTurnover
*/
void setAutoTurnoverSaleDetails(DcAutoTurnover dcAutoTurnover);
}
package com.bailuntec.job;
package com.bailuntec.service.impl;
import com.bailuntec.domain.dto.SalesVolumeDTO;
import com.bailuntec.domain.entity.DcAutoSales;
......
package com.bailuntec.service.impl;
import com.bailuntec.domain.entity.DcAutoSalesForecastStageConfig;
import com.bailuntec.domain.entity.DcAutoTurnover;
import com.bailuntec.mapper.DcAutoSalesForecastStageConfigMapper;
import com.bailuntec.mapper.DcAutoTurnoverMapper;
import com.bailuntec.mapper.DcBaseOmsSkuMapper;
import com.bailuntec.service.AutoTurnoverService;
import com.bailuntec.utils.SessionUtil;
import com.google.gson.Gson;
import org.apache.ibatis.session.SqlSession;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.LinkedList;
import java.util.Optional;
import java.util.Queue;
/**
* <p>
*
* </p>
*
* @author robbendev
* @since 2020/8/13 2:09 下午
*/
public class AutoTurnoverServiceImpl implements AutoTurnoverService {
@Override
public void setAutoTurnoverSaleDetails(DcAutoTurnover dcAutoTurnover) {
SqlSession session = SessionUtil.getFactory().openSession(true);
try {
DcAutoSalesForecastStageConfigMapper dcAutoSalesForecastStageConfigMapper = session.getMapper(DcAutoSalesForecastStageConfigMapper.class);
DcAutoTurnoverMapper dcAutoTurnoverMapper = session.getMapper(DcAutoTurnoverMapper.class);
DcBaseOmsSkuMapper dcBaseOmsSkuMapper = session.getMapper(DcBaseOmsSkuMapper.class);
//命中的预测规则
DcAutoSalesForecastStageConfig dcAutoSalesForecastStageConfig = dcAutoSalesForecastStageConfigMapper.selectMatchStage(dcAutoTurnover.getBailunSku(), dcAutoTurnover.getWarehouseCode());
// if (dcAutoSalesForecastStageConfig == null) {
// return;
// }
//周转天数
int turnoverDays = Optional.ofNullable(dcAutoTurnover.getTurnoverDays()).orElse(0);
/*
* 每个时间段的销量预测是dcAutoSalesForecastStageConfig对应时间段的三个参数对应的过去时间段的销量的加权平均*/
//今天0点
LocalDateTime midNight = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
String bailunSku = dcAutoTurnover.getBailunSku();
String warehouseCode = dcAutoTurnover.getWarehouseCode();
Queue<BigDecimal> forecastSalesDetails = new LinkedList<>();
//获取过去7天的销量
BigDecimal last1DaySellerNum = BigDecimal.valueOf(Optional.ofNullable(dcBaseOmsSkuMapper.omsSkuSellerCount(midNight.minusDays(1), midNight, bailunSku, warehouseCode)).orElse(0));
BigDecimal last2DaySellerNum = BigDecimal.valueOf(Optional.ofNullable(dcBaseOmsSkuMapper.omsSkuSellerCount(midNight.minusDays(2), midNight.minusDays(1), bailunSku, warehouseCode)).orElse(0));
BigDecimal last3DaySellerNum = BigDecimal.valueOf(Optional.ofNullable(dcBaseOmsSkuMapper.omsSkuSellerCount(midNight.minusDays(3), midNight.minusDays(2), bailunSku, warehouseCode)).orElse(0));
BigDecimal last4DaySellerNum = BigDecimal.valueOf(Optional.ofNullable(dcBaseOmsSkuMapper.omsSkuSellerCount(midNight.minusDays(4), midNight.minusDays(3), bailunSku, warehouseCode)).orElse(0));
BigDecimal last5DaySellerNum = BigDecimal.valueOf(Optional.ofNullable(dcBaseOmsSkuMapper.omsSkuSellerCount(midNight.minusDays(5), midNight.minusDays(4), bailunSku, warehouseCode)).orElse(0));
BigDecimal last6DaySellerNum = BigDecimal.valueOf(Optional.ofNullable(dcBaseOmsSkuMapper.omsSkuSellerCount(midNight.minusDays(6), midNight.minusDays(5), bailunSku, warehouseCode)).orElse(0));
BigDecimal last7DaySellerNum = BigDecimal.valueOf(Optional.ofNullable(dcBaseOmsSkuMapper.omsSkuSellerCount(midNight.minusDays(7), midNight.minusDays(6), bailunSku, warehouseCode)).orElse(0));
forecastSalesDetails.offer(last1DaySellerNum);
forecastSalesDetails.offer(last2DaySellerNum);
forecastSalesDetails.offer(last3DaySellerNum);
forecastSalesDetails.offer(last4DaySellerNum);
forecastSalesDetails.offer(last5DaySellerNum);
forecastSalesDetails.offer(last6DaySellerNum);
forecastSalesDetails.offer(last7DaySellerNum);
if (dcAutoSalesForecastStageConfig != null) {
int duration1 = BigDecimal.valueOf(turnoverDays).multiply(dcAutoSalesForecastStageConfig.getOneRatio()).intValue();
int duration2 = BigDecimal.valueOf(turnoverDays).multiply(dcAutoSalesForecastStageConfig.getTwoRatio()).intValue();
int duration3 = turnoverDays - duration1 - duration2;
/*第一部分预测*/
BigDecimal duration1ForecastSellerNum = BigDecimal.valueOf(Optional.ofNullable(dcBaseOmsSkuMapper.omsSkuSellerCount(midNight.minusDays(dcAutoSalesForecastStageConfig.getOneN1().intValue()), midNight, bailunSku, warehouseCode)).orElse(0))
.multiply(dcAutoSalesForecastStageConfig.getOneN2())
.add(BigDecimal.valueOf(Optional.ofNullable(dcBaseOmsSkuMapper.omsSkuSellerCount(midNight.minusDays(dcAutoSalesForecastStageConfig.getOneN3().intValue()), midNight, bailunSku, warehouseCode)).orElse(0))
.multiply(dcAutoSalesForecastStageConfig.getOneN4()))
.add(BigDecimal.valueOf(dcBaseOmsSkuMapper.omsSkuSellerCount(midNight.minusDays(dcAutoSalesForecastStageConfig.getOneN5().intValue()), midNight, bailunSku, warehouseCode))
.multiply(dcAutoSalesForecastStageConfig.getOneN6()));
for (int i = 0; i < duration1; i++) {
forecastSalesDetails.offer(duration1ForecastSellerNum);
}
/*第二部分预测*/
BigDecimal duration2ForecastSellerNum = BigDecimal.valueOf(dcBaseOmsSkuMapper.omsSkuSellerCount(midNight.minusDays(dcAutoSalesForecastStageConfig.getTwoN1().intValue()), midNight, bailunSku, warehouseCode))
.multiply(dcAutoSalesForecastStageConfig.getTwoN2())
.add(BigDecimal.valueOf(dcBaseOmsSkuMapper.omsSkuSellerCount(midNight.minusDays(dcAutoSalesForecastStageConfig.getTwoN3().intValue()), midNight, bailunSku, warehouseCode))
.multiply(dcAutoSalesForecastStageConfig.getTwoN4()))
.add(BigDecimal.valueOf(dcBaseOmsSkuMapper.omsSkuSellerCount(midNight.minusDays(dcAutoSalesForecastStageConfig.getTwoN5().intValue()), midNight, bailunSku, warehouseCode))
.multiply(dcAutoSalesForecastStageConfig.getTwoN6()));
for (int i = 0; i < duration2; i++) {
forecastSalesDetails.offer(duration2ForecastSellerNum);
}
/*第三部分预测*/
BigDecimal duration3ForecastSellerNum = BigDecimal.valueOf(dcBaseOmsSkuMapper.omsSkuSellerCount(midNight.minusDays(dcAutoSalesForecastStageConfig.getThreeN1().intValue()), midNight, bailunSku, warehouseCode))
.multiply(dcAutoSalesForecastStageConfig.getThreeN2())
.add(BigDecimal.valueOf(dcBaseOmsSkuMapper.omsSkuSellerCount(midNight.minusDays(dcAutoSalesForecastStageConfig.getThreeN3().intValue()), midNight, bailunSku, warehouseCode))
.multiply(dcAutoSalesForecastStageConfig.getThreeN4()))
.add(BigDecimal.valueOf(dcBaseOmsSkuMapper.omsSkuSellerCount(midNight.minusDays(dcAutoSalesForecastStageConfig.getThreeN5().intValue()), midNight, bailunSku, warehouseCode))
.multiply(dcAutoSalesForecastStageConfig.getThreeN6()));
for (int i = 0; i < duration3; i++) {
forecastSalesDetails.offer(duration3ForecastSellerNum);
}
dcAutoTurnover.setSalesDetails(new Gson().toJson(forecastSalesDetails));
// dcAutoTurnoverMapper.updateByPrimaryKey(dcAutoTurnover);
} else {
for (int i = 0; i < turnoverDays; i++) {
forecastSalesDetails.offer(dcAutoTurnover.getDailyWeightedSales())
}
}
} finally {
session.close();
}
}
}
#EVENT_RDB_STORAGE_DRIVER=com.mysql.jdbc.Driver
#EVENT_RDB_STORAGE_URL=jdbc:mysql://gz-cdb-kp7s5i79.sql.tencentcdb.com:61691/bailun_datacenter?serverTimezone=GMT%2B8&characterEncoding=utf-8
EVENT_RDB_STORAGE_URL=jdbc:mysql://gz-cdb-kp7s5i79.sql.tencentcdb.com:61691/bailun_datacenter?serverTimezone=GMT%2B8&characterEncoding=utf-8
#EVENT_RDB_STORAGE_USERNAME=root
#EVENT_RDB_STORAGE_PASSWORD=123456
#ZOOKEEPER_SERVER=127.0.0.1:2181
ZOOKEEPER_SERVER=127.0.0.1:2181
EVENT_RDB_STORAGE_DRIVER=com.mysql.jdbc.Driver
EVENT_RDB_STORAGE_URL=jdbc:mysql://10.0.8.15:3306/bailun_datacenter?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
#EVENT_RDB_STORAGE_URL=jdbc:mysql://10.0.8.15:3306/bailun_datacenter?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
EVENT_RDB_STORAGE_USERNAME=root
EVENT_RDB_STORAGE_PASSWORD=#7kfnymAM$Y9-Ntf
ZOOKEEPER_SERVER=172.31.255.120:2181
#ZOOKEEPER_SERVER=172.31.255.120:2181
NAME_SPACE=data-center
JOB_NAME=show-auto-turnover
......
package com.bailuntec.service.impl;
import com.bailuntec.domain.entity.DcAutoTurnover;
import com.bailuntec.mapper.DcAutoTurnoverMapper;
import com.bailuntec.service.AutoTurnoverService;
import com.bailuntec.utils.SessionUtil;
import org.junit.jupiter.api.Test;
/**
* <p>
*
* </p>
*
* @author robbendev
* @since 2020/8/13 4:10 下午
*/
class AutoTurnoverServiceImplTest {
@Test
void setAutoTurnoverSaleDetails() {
try {
DcAutoTurnoverMapper dcAutoTurnoverMapper = SessionUtil.getSession().getMapper(DcAutoTurnoverMapper.class);
AutoTurnoverService autoTurnoverService = new AutoTurnoverServiceImpl();
DcAutoTurnover dcAutoTurnover = dcAutoTurnoverMapper.selectByPrimaryKey(58845);
autoTurnoverService.setAutoTurnoverSaleDetails(dcAutoTurnover);
System.out.println(dcAutoTurnover.getSalesDetails());
} finally {
SessionUtil.closeSession();
}
}
}
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