From 19f1095a7cd56e99b6131538777a870f732aad7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E6=AC=A7=EF=BC=88=E6=9E=97=E5=B9=B3=E5=87=A1?= =?UTF-8?q?=EF=BC=89?= Date: Fri, 8 Nov 2024 09:18:27 +0800 Subject: [PATCH] 1 --- .idea/dataSources.xml | 1 + .idea/diff-generator.xml | 8 + .idea/jpb-settings.xml | 4 + .idea/sqldialects.xml | 7 + .../business/controller/OrderController.java | 39 ++++ .../cn/van/business/model/GoodsInfoVO.java | 93 ++++++++ .../java/cn/van/business/model/OrderRow.java | 32 ++- .../cn/van/business/model/update-schema.sql | 74 +++++++ .../java/cn/van/business/util/JDUtils.java | 207 +++++++++++++++--- 9 files changed, 414 insertions(+), 51 deletions(-) create mode 100644 .idea/diff-generator.xml create mode 100644 .idea/jpb-settings.xml create mode 100644 .idea/sqldialects.xml create mode 100644 src/main/java/cn/van/business/controller/OrderController.java create mode 100644 src/main/java/cn/van/business/model/GoodsInfoVO.java create mode 100644 src/main/java/cn/van/business/model/update-schema.sql diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml index 74dd33a..b63249d 100644 --- a/.idea/dataSources.xml +++ b/.idea/dataSources.xml @@ -11,6 +11,7 @@ + $ProjectFileDir$ diff --git a/.idea/diff-generator.xml b/.idea/diff-generator.xml new file mode 100644 index 0000000..7c8608f --- /dev/null +++ b/.idea/diff-generator.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/.idea/jpb-settings.xml b/.idea/jpb-settings.xml new file mode 100644 index 0000000..a6e603a --- /dev/null +++ b/.idea/jpb-settings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/sqldialects.xml b/.idea/sqldialects.xml new file mode 100644 index 0000000..38b1805 --- /dev/null +++ b/.idea/sqldialects.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/main/java/cn/van/business/controller/OrderController.java b/src/main/java/cn/van/business/controller/OrderController.java new file mode 100644 index 0000000..3c3d69c --- /dev/null +++ b/src/main/java/cn/van/business/controller/OrderController.java @@ -0,0 +1,39 @@ +package cn.van.business.controller; + +import cn.van.business.util.JDUtils; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; + +/** + * @author Leo + * @version 1.0 + * @create 2024/11/7 13:39 + * @description: + */ +@RestController +@RequestMapping("order") +public class OrderController { + + public static String TOKEN = "cc0313"; + @Resource + private JDUtils jdUtils; + + public boolean checkToken (String token){ + return TOKEN.equals(token); + } + + @RequestMapping("/refreshHistory") + @ResponseBody + public String refreshHistory(String token) throws Exception { + if (checkToken(token)) { + + jdUtils.fetchHistoricalOrders(); + + } + return "OK"; + } + +} diff --git a/src/main/java/cn/van/business/model/GoodsInfoVO.java b/src/main/java/cn/van/business/model/GoodsInfoVO.java new file mode 100644 index 0000000..9e983a6 --- /dev/null +++ b/src/main/java/cn/van/business/model/GoodsInfoVO.java @@ -0,0 +1,93 @@ +package cn.van.business.model; + +import javax.persistence.*; + +/** + * @author Leo + * @version 1.0 + * @create 2024/11/7 10:58 + * @description: + */ +@Entity +@Table(name = "goods_info") +public class GoodsInfoVO { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "owner") + private String owner; + + @Column(name = "main_sku_id") + private String mainSkuId; + + @Column(name = "product_id") + private String productId; + + @Column(name = "image_url") + private String imageUrl; + + @Column(name = "shop_name") + private String shopName; + + @Column(name = "shop_id") + private String shopId; + + // Getters and Setters + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getOwner() { + return owner; + } + + public void setOwner(String owner) { + this.owner = owner; + } + + public String getMainSkuId() { + return mainSkuId; + } + + public void setMainSkuId(String mainSkuId) { + this.mainSkuId = mainSkuId; + } + + public String getProductId() { + return productId; + } + + public void setProductId(String productId) { + this.productId = productId; + } + + public String getImageUrl() { + return imageUrl; + } + + public void setImageUrl(String imageUrl) { + this.imageUrl = imageUrl; + } + + public String getShopName() { + return shopName; + } + + public void setShopName(String shopName) { + this.shopName = shopName; + } + + public String getShopId() { + return shopId; + } + + public void setShopId(String shopId) { + this.shopId = shopId; + } +} diff --git a/src/main/java/cn/van/business/model/OrderRow.java b/src/main/java/cn/van/business/model/OrderRow.java index 1a8e94f..efd6fce 100644 --- a/src/main/java/cn/van/business/model/OrderRow.java +++ b/src/main/java/cn/van/business/model/OrderRow.java @@ -13,7 +13,7 @@ import java.util.Date; @Entity @Table(name = "order_rows") -public class OrderRowVO { +public class OrderRow { @Id @Column(name = "id") private String id; @@ -30,6 +30,7 @@ public class OrderRowVO { @Temporal(TemporalType.TIMESTAMP) @Column(name = "finish_time") + /**完成时间(购买用户确认收货时间),格式yyyy-MM-dd HH:mm:ss*/ private Date finishTime; @Temporal(TemporalType.TIMESTAMP) @@ -49,12 +50,21 @@ public class OrderRowVO { private Long skuId; @Column(name = "sku_name") + /** + * 商品名称 + * */ private String skuName; @Column(name = "sku_num") + /** + * + * 商品数量*/ private Integer skuNum; @Column(name = "sku_return_num") + /** + * + * 商品已退货数量*/ private Integer skuReturnNum; @Column(name = "sku_frozen_num") @@ -64,6 +74,7 @@ public class OrderRowVO { private Double price; @Column(name = "commission_rate") + /**佣金比例(投放的广告主计划比例)*/ private Double commissionRate; @Column(name = "sub_side_rate") @@ -155,11 +166,8 @@ public class OrderRowVO { @OneToOne(cascade = CascadeType.ALL) @JoinColumn(name = "goods_info_id", referencedColumnName = "id") - private GoodsInfo goodsInfo; + private GoodsInfoVO goodsInfo; - @OneToOne(cascade = CascadeType.ALL) - @JoinColumn(name = "category_info_id", referencedColumnName = "id") - private CategoryInfoVO categoryInfoVO; @Column(name = "express_status") private Integer expressStatus; @@ -179,8 +187,6 @@ public class OrderRowVO { @Column(name = "order_tag") private String orderTag; - public OrderRowVO() { - } public String getId() { return id; @@ -542,22 +548,14 @@ public class OrderRowVO { this.rid = rid; } - public GoodsInfo getGoodsInfo() { + public GoodsInfoVO getGoodsInfo() { return goodsInfo; } - public void setGoodsInfo(GoodsInfo goodsInfo) { + public void setGoodsInfo(GoodsInfoVO goodsInfo) { this.goodsInfo = goodsInfo; } - public CategoryInfo getCategoryInfo() { - return categoryInfo; - } - - public void setCategoryInfo(CategoryInfo categoryInfo) { - this.categoryInfo = categoryInfo; - } - public Integer getExpressStatus() { return expressStatus; } diff --git a/src/main/java/cn/van/business/model/update-schema.sql b/src/main/java/cn/van/business/model/update-schema.sql new file mode 100644 index 0000000..9fcdedc --- /dev/null +++ b/src/main/java/cn/van/business/model/update-schema.sql @@ -0,0 +1,74 @@ +CREATE TABLE goods_info +( + id BIGINT AUTO_INCREMENT NOT NULL, + owner VARCHAR(255) NULL, + main_sku_id VARCHAR(255) NULL, + product_id VARCHAR(255) NULL, + image_url VARCHAR(255) NULL, + shop_name VARCHAR(255) NULL, + shop_id VARCHAR(255) NULL, + CONSTRAINT pk_goods_info PRIMARY KEY (id) +); + +CREATE TABLE order_rows +( + id VARCHAR(255) NOT NULL, + order_id BIGINT NULL, + parent_id BIGINT NULL, + order_time datetime NULL, + finish_time datetime NULL, + modify_time datetime NULL, + order_emt INT NULL, + plus INT NULL, + union_id BIGINT NULL, + sku_id BIGINT NULL, + sku_name VARCHAR(255) NULL, + sku_num INT NULL, + sku_return_num INT NULL, + sku_frozen_num INT NULL, + price DOUBLE NULL, + commission_rate DOUBLE NULL, + sub_side_rate DOUBLE NULL, + subsidy_rate DOUBLE NULL, + final_rate DOUBLE NULL, + estimate_cos_price DOUBLE NULL, + estimate_fee DOUBLE NULL, + actual_cos_price DOUBLE NULL, + actual_fee DOUBLE NULL, + valid_code INT NULL, + trace_type INT NULL, + position_id BIGINT NULL, + site_id BIGINT NULL, + union_alias VARCHAR(255) NULL, + pid VARCHAR(255) NULL, + cid1 BIGINT NULL, + cid2 BIGINT NULL, + cid3 BIGINT NULL, + sub_union_id VARCHAR(255) NULL, + union_tag VARCHAR(255) NULL, + pop_id BIGINT NULL, + ext1 VARCHAR(255) NULL, + pay_month VARCHAR(255) NULL, + cp_act_id BIGINT NULL, + union_role INT NULL, + gift_coupon_ocs_amount DOUBLE NULL, + gift_coupon_key VARCHAR(255) NULL, + balance_ext VARCHAR(255) NULL, + sign VARCHAR(255) NULL, + pro_price_amount DOUBLE NULL, + rid BIGINT NULL, + goods_info_id BIGINT NULL, + express_status INT NULL, + channel_id BIGINT NULL, + sku_tag VARCHAR(255) NULL, + item_id VARCHAR(255) NULL, + caller_item_id VARCHAR(255) NULL, + order_tag VARCHAR(255) NULL, + CONSTRAINT pk_order_rows PRIMARY KEY (id) +); + +ALTER TABLE order_rows + ADD CONSTRAINT uc_order_rows_goods_info UNIQUE (goods_info_id); + +ALTER TABLE order_rows + ADD CONSTRAINT FK_ORDER_ROWS_ON_GOODS_INFO FOREIGN KEY (goods_info_id) REFERENCES goods_info (id); \ No newline at end of file diff --git a/src/main/java/cn/van/business/util/JDUtils.java b/src/main/java/cn/van/business/util/JDUtils.java index 29a6ade..6d7b29f 100644 --- a/src/main/java/cn/van/business/util/JDUtils.java +++ b/src/main/java/cn/van/business/util/JDUtils.java @@ -1,22 +1,32 @@ package cn.van.business.util; +import cn.van.business.model.GoodsInfoVO; import cn.van.business.model.OrderRow; import cn.van.business.repository.OrderRowRepository; +import com.alibaba.fastjson2.util.DateUtils; import com.jd.open.api.sdk.DefaultJdClient; import com.jd.open.api.sdk.JdClient; import com.jd.open.api.sdk.domain.kplunion.OrderService.request.query.OrderRowReq; +import com.jd.open.api.sdk.domain.kplunion.OrderService.response.query.GoodsInfo; import com.jd.open.api.sdk.domain.kplunion.OrderService.response.query.OrderRowResp; import com.jd.open.api.sdk.request.kplunion.UnionOpenOrderRowQueryRequest; import com.jd.open.api.sdk.response.kplunion.UnionOpenOrderRowQueryResponse; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.SetOperations; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import java.text.SimpleDateFormat; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; import java.util.Date; +import static java.lang.Thread.sleep; + /** * @author Leo * @version 1.0 @@ -36,49 +46,172 @@ public class JDUtils { @Autowired private OrderRowRepository orderRowRepository; - private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); /** - * 写两个方法,一个拉最新的订单。一个拉历史订单 + * 拉取最新的订单 */ - @Scheduled(cron = "0 0 * * * ?") - public void getHistoryOrder() { - // 因为只能一小时一小时的拉取订单,所以要循环的倒推去拉取历史订单,存到数据库 - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - // 当前是2024-10-10 11:46:00 , 则生成一个 2024-10-10 11:00:00 + @Scheduled(cron = "0 * * * * ?") // 每分钟执行一次 + public void fetchLatestOrder() throws Exception { + LocalDateTime now = LocalDateTime.now(); + LocalDateTime lastMinute = now.minusMinutes(1).withSecond(0).withNano(0); - - } - - @Scheduled(cron = "0 * * * * ?") - public void getNewOrder() throws Exception { - //一分钟一分钟拉取 2020-01-02 21:23:00 - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - String startTime = sdf.format(new Date(System.currentTimeMillis() - 1000 * 60)); - String endTime = sdf.format(new Date()); - UnionOpenOrderRowQueryResponse response = getUnionOpenOrderRowQueryResponse(startTime, endTime); - int code = response.getQueryResult().getCode(); - System.out.println("响应码:" + code); - if (code == 200) { - if (response.getQueryResult().getCode() == 200) { - OrderRowResp[] orderRowResps = response.getQueryResult().getData(); - if (orderRowResps == null) { - return; - } - for (OrderRowResp orderRowResp : orderRowResps) { - // 固化到数据库 - OrderRow orderRow = new OrderRow(); - orderRow.setOrderId(orderRowResp.getOrderId()); - orderRow.setSkuId(orderRowResp.getSkuId()); - orderRow.setSkuName(orderRowResp.getSkuName()); - - orderRowRepository.save(orderRowResp); + UnionOpenOrderRowQueryResponse response = fetchOrdersForDateTime(lastMinute, true); // 真实代表实时订单 + if (response != null){ + int code = response.getQueryResult().getCode(); + if (code == 200) { + if (response.getQueryResult().getCode() == 200) { + OrderRowResp[] orderRowResps = response.getQueryResult().getData(); + if (orderRowResps == null) { + return; + } + for (OrderRowResp orderRowResp : orderRowResps) { + // 固化到数据库 + OrderRow orderRow = createOrderRow(orderRowResp); + // 订单号不存在就保存,存在就更新订单状态 + orderRowRepository.save(orderRow); + } } } } } + /** + * 拉取历史订单 + */ + public void fetchHistoricalOrders() throws Exception { + // 从设定的开始日期到昨天的同一时间 + LocalDateTime startDate = LocalDateTime.of(2024, 7, 1, 0, 0); + LocalDateTime now = LocalDateTime.now(); + LocalDateTime lastHour = now.minusHours(1).withMinute(0).withSecond(0).withNano(0); + + + while (!startDate.isEqual(lastHour)) { + UnionOpenOrderRowQueryResponse response = fetchOrdersForDateTime(startDate, false); // 假的代表历史订单 + + if (response != null){ + int code = response.getQueryResult().getCode(); + if (code == 200) { + if (response.getQueryResult().getCode() == 200) { + OrderRowResp[] orderRowResps = response.getQueryResult().getData(); + if (orderRowResps == null) { + continue; + } + for (OrderRowResp orderRowResp : orderRowResps) { + // 固化到数据库 + OrderRow orderRow = createOrderRow(orderRowResp); + // 订单号不存在就保存,存在就更新订单状态 + orderRowRepository.save(orderRow); + } + } + } + sleep(1000); + } + startDate = startDate.plusHours(1); + + } + } + + /** + * 根据指定的日期时间拉取订单 + */ + public UnionOpenOrderRowQueryResponse fetchOrdersForDateTime(LocalDateTime dateTime, boolean isRealTime) throws Exception { + LocalDateTime endTime = isRealTime ? dateTime.plusMinutes(1) : dateTime.plusHours(1); + String key = dateTime.format(DATE_TIME_FORMATTER); + String hourRange = isRealTime ? "minute" : "hour"; + + SetOperations setOps = redisTemplate.opsForSet(); + + // 检查是否标记为已拉取 + if (Boolean.TRUE.equals(setOps.isMember(key, hourRange))) { + System.out.println(dateTime.format(DATE_TIME_FORMATTER) + " 已经拉取,跳过"); + return null; + } + + // 调用 API 以拉取订单 + UnionOpenOrderRowQueryResponse unionOpenOrderRowQueryResponse = getUnionOpenOrderRowQueryResponse(dateTime, endTime); + + // 标记已拉取 + setOps.add(key, hourRange); + return unionOpenOrderRowQueryResponse; + } + + /** + * 将 响应参数转化为 OrderRow,并返回 + * */ + private static OrderRow createOrderRow(OrderRowResp orderRowResp) { + OrderRow orderRow = new OrderRow(); + orderRow.setOrderId(orderRowResp.getOrderId()); + orderRow.setSkuId(orderRowResp.getSkuId()); + orderRow.setSkuName(orderRowResp.getSkuName()); + orderRow.setItemId(orderRowResp.getItemId()); + orderRow.setSkuNum(orderRowResp.getSkuNum()); + orderRow.setPrice(orderRowResp.getPrice()); + orderRow.setActualCosPrice(orderRowResp.getActualCosPrice()); + orderRow.setActualFee(orderRowResp.getActualFee()); + orderRow.setEstimateCosPrice(orderRowResp.getEstimateCosPrice()); + orderRow.setEstimateFee(orderRowResp.getEstimateFee()); + orderRow.setSubSideRate(orderRowResp.getSubSideRate()); + orderRow.setSubsidyRate(orderRowResp.getSubsidyRate()); + orderRow.setCommissionRate(orderRowResp.getCommissionRate()); + orderRow.setFinalRate(orderRowResp.getFinalRate()); + + orderRow.setOrderTime(DateUtils.parseDate(orderRowResp.getOrderTime())); + orderRow.setFinishTime(DateUtils.parseDate(orderRowResp.getFinishTime())); + orderRow.setOrderTag(orderRowResp.getOrderTag()); + orderRow.setOrderEmt(orderRowResp.getOrderEmt()); + orderRow.setUnionId(orderRowResp.getUnionId()); + orderRow.setUnionRole(orderRowResp.getUnionRole()); + orderRow.setUnionAlias(orderRowResp.getUnionAlias()); + orderRow.setUnionTag(orderRowResp.getUnionTag()); + orderRow.setTraceType(orderRowResp.getTraceType()); + orderRow.setValidCode(orderRowResp.getValidCode()); + orderRow.setPayMonth(orderRowResp.getPayMonth()); + orderRow.setSiteId(orderRowResp.getSiteId()); + orderRow.setParentId(orderRowResp.getParentId()); + GoodsInfo goodsInfo = orderRowResp.getGoodsInfo(); + GoodsInfoVO goodsInfoVO = new GoodsInfoVO(); + goodsInfoVO.setShopId(String.valueOf(goodsInfo.getShopId())); + goodsInfoVO.setShopName(goodsInfo.getShopName()); + goodsInfoVO.setOwner(goodsInfo.getOwner()); + goodsInfoVO.setProductId(String.valueOf(goodsInfo.getProductId())); + goodsInfoVO.setImageUrl(goodsInfo.getImageUrl()); + orderRow.setGoodsInfo(goodsInfoVO); + orderRow.setCallerItemId(orderRowResp.getCallerItemId()); + orderRow.setPid(orderRowResp.getPid()); + orderRow.setCid1(orderRowResp.getCid1()); + orderRow.setCid2(orderRowResp.getCid2()); + orderRow.setCid3(orderRowResp.getCid3()); + orderRow.setChannelId(orderRowResp.getChannelId()); + orderRow.setProPriceAmount(orderRowResp.getProPriceAmount()); + orderRow.setSkuFrozenNum(orderRowResp.getSkuFrozenNum()); + orderRow.setSkuReturnNum(orderRowResp.getSkuReturnNum()); + orderRow.setSkuTag(orderRowResp.getSkuTag()); + orderRow.setPositionId(orderRowResp.getPositionId()); + orderRow.setPopId(orderRowResp.getPopId()); + orderRow.setRid(orderRowResp.getRid()); + orderRow.setPlus(orderRowResp.getPlus()); + orderRow.setCpActId(orderRowResp.getCpActId()); + orderRow.setGiftCouponKey(orderRowResp.getGiftCouponKey()); + + orderRow.setModifyTime(new Date()); + orderRow.setSign(orderRowResp.getSign()); + orderRow.setBalanceExt(orderRowResp.getBalanceExt()); + orderRow.setExpressStatus(orderRowResp.getExpressStatus()); + orderRow.setExt1(orderRowResp.getExt1()); + orderRow.setSubUnionId(orderRowResp.getSubUnionId()); + orderRow.setGiftCouponOcsAmount(orderRowResp.getGiftCouponOcsAmount()); + orderRow.setTraceType(orderRowResp.getTraceType()); + orderRow.setExpressStatus(orderRowResp.getExpressStatus()); + orderRow.setTraceType(orderRowResp.getTraceType()); + orderRow.setId(orderRowResp.getId()); + orderRow.setValidCode(orderRowResp.getValidCode()); + orderRow.setExpressStatus(orderRowResp.getExpressStatus()); + orderRow.setTraceType(orderRowResp.getTraceType()); + return orderRow; + } + /** * 获取订单列表 * @@ -87,7 +220,13 @@ public class JDUtils { * @return * @throws Exception */ - public UnionOpenOrderRowQueryResponse getUnionOpenOrderRowQueryResponse(String startTime, String endTime) throws Exception { + public UnionOpenOrderRowQueryResponse getUnionOpenOrderRowQueryResponse(LocalDateTime start, LocalDateTime end) throws Exception { + String startTime = start.format(DATE_TIME_FORMATTER); + String endTime = end.format(DATE_TIME_FORMATTER); + // 模拟 API 调用 + System.out.println("调用API - 从 " + startTime + + " 到 " + endTime); + // 实际的 API 调用逻辑应在这里进行 String accessToken = ""; JdClient client = new DefaultJdClient(SERVER_URL, accessToken, APP_KEY, SECRET_KEY); UnionOpenOrderRowQueryRequest request = new UnionOpenOrderRowQueryRequest();