From 41b6982d0f54a666e14dc0cb745625b84a2bfdba Mon Sep 17 00:00:00 2001 From: Qiuyi LI Date: Wed, 21 May 2025 15:55:02 +0200 Subject: [PATCH] Create ShopifyPromoCodeJob to retrieve promo code used in orders and set orders as abnormal if present with a specific promo code --- .../domain/job/ShopifyPromoCodeJob.java | 148 ++++++++++++++++++ .../business/mapper/PlatformOrderMapper.java | 2 + .../mapper/xml/PlatformOrderMapper.xml | 9 +- .../service/IPlatformOrderService.java | 3 +- .../impl/PlatformOrderServiceImpl.java | 5 + 5 files changed, 165 insertions(+), 2 deletions(-) create mode 100644 jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/domain/job/ShopifyPromoCodeJob.java diff --git a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/domain/job/ShopifyPromoCodeJob.java b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/domain/job/ShopifyPromoCodeJob.java new file mode 100644 index 000000000..3d0e10949 --- /dev/null +++ b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/domain/job/ShopifyPromoCodeJob.java @@ -0,0 +1,148 @@ +package org.jeecg.modules.business.domain.job; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.slf4j.Slf4j; +import org.codehaus.jettison.json.JSONArray; +import org.codehaus.jettison.json.JSONException; +import org.codehaus.jettison.json.JSONObject; +import org.jeecg.modules.business.domain.api.mabang.orderDoOrderAbnormal.OrderSuspendRequest; +import org.jeecg.modules.business.domain.api.mabang.orderDoOrderAbnormal.OrderSuspendRequestBody; +import org.jeecg.modules.business.domain.api.mabang.orderDoOrderAbnormal.OrderSuspendResponse; +import org.jeecg.modules.business.domain.api.shopify.GetOrderListRequest; +import org.jeecg.modules.business.domain.api.shopify.GetOrderListRequestBody; +import org.jeecg.modules.business.domain.api.shopify.GetOrderListResponse; +import org.jeecg.modules.business.domain.api.shopify.Order; +import org.jeecg.modules.business.entity.PlatformOrder; +import org.jeecg.modules.business.entity.PlatformOrderShopSync; +import org.jeecg.modules.business.service.IPlatformOrderService; +import org.quartz.Job; +import org.quartz.JobDataMap; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.stream.Collectors; + +import static java.util.stream.Collectors.*; +import static java.util.stream.Collectors.toList; + +@Slf4j +public class ShopifyPromoCodeJob implements Job { + + private static final List DEFAULT_INCLUDED_SHOPS = Arrays.asList("AC"); + + private static final Integer DEFAULT_NUMBER_OF_THREADS = 10; + + private final String DEFAULT_ABNORMAL_LABEL_NAME = "AC自行处理"; + + private final String DEFAULT_PROMO_CODE = "BARBE20"; + + @Autowired + private IPlatformOrderService platformOrderService; + + @Override + public void execute(JobExecutionContext context) throws JobExecutionException { + List shops = DEFAULT_INCLUDED_SHOPS; + String promoCode = DEFAULT_PROMO_CODE; + JobDataMap jobDataMap = context.getMergedJobDataMap(); + String parameter = ((String) jobDataMap.get("parameter")); + if (parameter != null) { + try { + JSONObject jsonObject = new JSONObject(parameter); + if (!jsonObject.isNull("includedShops")) { + JSONArray shopsArray = jsonObject.getJSONArray("includedShops"); + List shopList = new ArrayList<>(); + for (int i = 0; i < shopsArray.length(); i++) { + shopList.add(shopsArray.getString(i)); + } + shops = shopList; + } + if (!jsonObject.isNull("promoCode")) { + promoCode = jsonObject.getString("promoCode"); + } + } catch (JSONException e) { + log.error("Error while parsing parameter as JSON, falling back to default parameters."); + } + } + + ObjectMapper mapper = new ObjectMapper(); + mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + + List ordersWithoutShopifyNote = platformOrderService.fetchOrderInShopsWithoutShopifyNote(shops); + log.info("Fetched {} orders without Shopify promo code", ordersWithoutShopifyNote.size()); + Map> ordersByShop = ordersWithoutShopifyNote.stream().collect( + groupingBy(PlatformOrderShopSync::getShopifyPrefix)); + + List orders = new ArrayList<>(); + + ExecutorService executor = Executors.newFixedThreadPool(DEFAULT_NUMBER_OF_THREADS); + log.info("Constructing order retrieval requests"); + List getOrderListRequestBodyList = new ArrayList<>(); + ordersByShop.values().forEach(platformOrderShopSyncs -> { + if (!platformOrderShopSyncs.isEmpty()) { + List orderIds = platformOrderShopSyncs.stream().map(PlatformOrderShopSync::getPlatformOrderId).collect(Collectors.toList()); + String shopifyPrefix = platformOrderShopSyncs.get(0).getShopifyPrefix(); + String shopifyToken = platformOrderShopSyncs.get(0).getShopifyToken(); + getOrderListRequestBodyList.add(new GetOrderListRequestBody(shopifyPrefix, shopifyToken, orderIds)); + } + }); + + List> futures = getOrderListRequestBodyList.stream() + .map(body -> CompletableFuture.supplyAsync(() -> { + boolean success = false; + try { + GetOrderListRequest getOrderListRequest = new GetOrderListRequest(body); + String responseStr = getOrderListRequest.rawSend().getBody(); + GetOrderListResponse response = mapper.readValue(responseStr, GetOrderListResponse.class); + orders.addAll(response.getOrders()); + success = true; + } catch (RuntimeException e) { + log.error("Error communicating with ShopifyAPI", e); + } catch (JsonProcessingException e) { + log.error("Error processing json", e); + } + return success; + }, executor)) + .collect(Collectors.toList()); + List results = futures.stream().map(CompletableFuture::join).collect(Collectors.toList()); + long nbSuccesses = results.stream().filter(b -> b).count(); + log.info("{}/{} order retrieval requests have succeeded.", nbSuccesses, getOrderListRequestBodyList.size()); + log.info("{} orders have been retrieved.", orders.size()); + + log.info("Started adding Shopify promo code to orders without one"); + Map orderNoteMap = orders.stream().filter(Order::hasDiscountCodes).collect(toMap(order -> order.getId().toString(), Order::getDiscountCode)); + if (orderNoteMap.isEmpty()) { + log.info("No promo code can be added to orders, quitting now"); + } else { + List ordersToAddPromoCode = new ArrayList<>(orderNoteMap.keySet()); + List platformOrders = platformOrderService.selectByPlatformOrderIds(ordersToAddPromoCode); + platformOrders.forEach(platformOrder -> platformOrder.setShopifyNote(orderNoteMap.get(platformOrder.getPlatformOrderId()).trim())); + platformOrderService.updateBatchById(platformOrders); + log.info("Finished adding Shopify promo code to {} orders without one into DB.", platformOrders.size()); + } + + log.info("Setting orders to abnormal..."); + List orderIdsByShopifyNote = platformOrderService.fetchPlatformOrderIdsByShopifyNote(promoCode); + String finalPromoCode = promoCode; + List> abnormalFutures = orderIdsByShopifyNote.stream() + .map(id -> CompletableFuture.supplyAsync(() -> { + OrderSuspendRequestBody body = new OrderSuspendRequestBody(id, DEFAULT_ABNORMAL_LABEL_NAME, finalPromoCode); + OrderSuspendRequest request = new OrderSuspendRequest(body); + OrderSuspendResponse response = request.send(); + return response.success(); + }, executor)) + .collect(toList()); + List abnormalResults = abnormalFutures.stream().map(CompletableFuture::join).collect(Collectors.toList()); + log.info("Successfully set {}/{} orders to abnormal.", abnormalResults.size(), orderIdsByShopifyNote.size()); + executor.shutdown(); + } +} diff --git a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/mapper/PlatformOrderMapper.java b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/mapper/PlatformOrderMapper.java index a55d785e7..8501e428c 100644 --- a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/mapper/PlatformOrderMapper.java +++ b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/mapper/PlatformOrderMapper.java @@ -260,4 +260,6 @@ public interface PlatformOrderMapper extends BaseMapper { Map selectBatchIdsForUpdate(@Param("ids") List orderIds); PlatformOrder selectForUpdateSkipLock(@Param("id") String orderId); + + List fetchPlatformOrderIdsByShopifyNote(String shopifyNote); } diff --git a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/mapper/xml/PlatformOrderMapper.xml b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/mapper/xml/PlatformOrderMapper.xml index 6c0b8b800..19bebcb35 100644 --- a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/mapper/xml/PlatformOrderMapper.xml +++ b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/mapper/xml/PlatformOrderMapper.xml @@ -485,7 +485,7 @@ > #{shop} - AND erp_status <> 5 + AND erp_status in (1,2) AND shopify_note IS NULL ORDER BY order_time; @@ -1396,4 +1396,11 @@ WHERE id = #{id} FOR UPDATE; + + diff --git a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/service/IPlatformOrderService.java b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/service/IPlatformOrderService.java index 49a80bc45..c4851fe64 100644 --- a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/service/IPlatformOrderService.java +++ b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/service/IPlatformOrderService.java @@ -267,7 +267,6 @@ public interface IPlatformOrderService extends IService { Map fetchShippingPeriodAndType(String invoiceNumber); - void anonymizePersonalData(int indirectClientAnonymizationPeriod); List ordersByShop(String shopID); @@ -295,4 +294,6 @@ public interface IPlatformOrderService extends IService { int countListByClientAndShops(String clientId, List shopIDs, String start, String end, String invoicingMethod, List warehouses); PlatformOrder selectForUpdateSkipLock(String orderId); + + List fetchPlatformOrderIdsByShopifyNote(String shopifyNote); } diff --git a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/service/impl/PlatformOrderServiceImpl.java b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/service/impl/PlatformOrderServiceImpl.java index dae656990..57c5714ef 100644 --- a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/service/impl/PlatformOrderServiceImpl.java +++ b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/service/impl/PlatformOrderServiceImpl.java @@ -605,4 +605,9 @@ public class PlatformOrderServiceImpl extends ServiceImpl fetchPlatformOrderIdsByShopifyNote(String shopifyNote) { + return platformOrderMap.fetchPlatformOrderIdsByShopifyNote(shopifyNote); + } }