From 992f25a224657233bc301df53ac164955f8f9400 Mon Sep 17 00:00:00 2001 From: Jack <46790855@qq.com> Date: Fri, 5 Dec 2025 21:34:47 +0800 Subject: [PATCH 01/28] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E6=89=93=E5=8D=B0=EF=BC=8Ce=E7=AD=BE=E5=AE=9D=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../EsignContractFillingFileServiceImpl.java | 196 +++++++++--------- .../impl/EsignContractServiceImpl.java | 81 +++++--- .../impl/ShopNumberSeqServiceImpl.java | 52 +++-- .../impl/ShopOrderBaseServiceImpl.java | 2 +- 4 files changed, 181 insertions(+), 150 deletions(-) diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/esign/service/impl/EsignContractFillingFileServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/esign/service/impl/EsignContractFillingFileServiceImpl.java index f39b49d3..75350f7e 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/esign/service/impl/EsignContractFillingFileServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/esign/service/impl/EsignContractFillingFileServiceImpl.java @@ -91,7 +91,7 @@ public class EsignContractFillingFileServiceImpl extends BaseServiceImpl @@ -109,47 +109,47 @@ public class EsignContractFillingFileServiceImpl extends BaseServiceImpl() {{ + componentList.add(new HashMap() {{ put("componentKey", "plat_contracts"); put("componentValue", "《平台商户入驻服务框架协议》和《小发同城服务费结算》"); }}); @@ -207,7 +207,7 @@ public class EsignContractFillingFileServiceImpl extends BaseServiceImpl() {{ + componentList.add(new HashMap() {{ put("componentKey", "mch_sign_date" + finalI); put("componentValue", today); }}); @@ -216,34 +216,34 @@ public class EsignContractFillingFileServiceImpl extends BaseServiceImpl() {{ + componentList.add(new HashMap() {{ put("componentKey", "plat_sign_date" + finalI); put("componentValue", today); }}); } // 甲方公司名称 - int mchCompanyCount = CommonConstant.MCH_ENTITY_TYPE_QY.equals(shopMchEntry.getEntity_type()) ? 17 : 16; + int mchCompanyCount = CommonConstant.MCH_ENTITY_TYPE_QY.equals(mchEntry.getEntity_type()) ? 17 : 16; for (int i = 1; i <= mchCompanyCount; i++) { int finalI = i; - list.add(new HashMap() {{ + componentList.add(new HashMap() {{ put("componentKey", "mch_company" + finalI); put("componentValue", mchCompany); }}); } // 特殊处理:甲方收款账户方(企业是公司名,个人是个人实名) - if (!CommonConstant.MCH_ENTITY_TYPE_QY.equals(shopMchEntry.getEntity_type())) { - list.add(new HashMap() {{ + if (!CommonConstant.MCH_ENTITY_TYPE_QY.equals(mchEntry.getEntity_type())) { + componentList.add(new HashMap() {{ put("componentKey", "mch_company17"); - put("componentValue", shopMchEntry.getContact_name()); + put("componentValue", mchEntry.getContact_name()); }}); } // 甲方法人姓名 for (int i = 1; i <= 4; i++) { int finalI = i; - list.add(new HashMap() {{ + componentList.add(new HashMap() {{ put("componentKey", "mch_legal_person_name" + finalI); put("componentValue", legalPersonName); }}); @@ -252,63 +252,63 @@ public class EsignContractFillingFileServiceImpl extends BaseServiceImpl() {{ + componentList.add(new HashMap() {{ put("componentKey", "mch_legal_person_mobile" + finalI); put("componentValue", legalPersonMobile); }}); } // 甲方身份证号码 - list.add(new HashMap() {{ + componentList.add(new HashMap() {{ put("componentKey", "mch_legal_person_id_number1"); put("componentValue", legalPersonIdNumber); }}); // 甲方店铺名称 - list.add(new HashMap() {{ + componentList.add(new HashMap() {{ put("componentKey", "mch_store_name1"); - put("componentValue", shopMchEntry.getStore_name()); + put("componentValue", mchEntry.getStore_name()); }}); // 规则编号 - list.add(new HashMap() {{ + componentList.add(new HashMap() {{ put("componentKey", "rule_no"); put("componentValue", 3); }}); // 分账比例 BigDecimal finalSplitRatio = splitRatio; - list.add(new HashMap() {{ + componentList.add(new HashMap() {{ put("componentKey", "mch_ratio"); put("componentValue", finalSplitRatio); }}); // 结算方式 - list.add(new HashMap() {{ + componentList.add(new HashMap() {{ put("componentKey", "settlement_method"); - put("componentValue", shopMchEntry.getSettlement_method()); + put("componentValue", mchEntry.getSettlement_method()); }}); // 甲方地址 - list.add(new HashMap() {{ + componentList.add(new HashMap() {{ put("componentKey", "mch_address1"); - put("componentValue", shopMchEntry.getStore_address()); + put("componentValue", mchEntry.getStore_address()); }}); // 甲方银行 - list.add(new HashMap() {{ + componentList.add(new HashMap() {{ put("componentKey", "mch_bank1"); - put("componentValue", shopMchEntry.getBank_name()); + put("componentValue", mchEntry.getBank_name()); }}); // 甲方账户号 - list.add(new HashMap() {{ + componentList.add(new HashMap() {{ put("componentKey", "mch_account_number1"); - put("componentValue", shopMchEntry.getAccount_number()); + put("componentValue", mchEntry.getAccount_number()); }}); // 乙方公司名称 - list.add(new HashMap() {{ + componentList.add(new HashMap() {{ put("componentKey", "plat_company1"); put("componentValue", platCompany + "和代理商"); }}); @@ -316,7 +316,7 @@ public class EsignContractFillingFileServiceImpl extends BaseServiceImpl() {{ + componentList.add(new HashMap() {{ put("componentKey", "plat_company" + finalI); put("componentValue", platCompany); }}); @@ -325,58 +325,58 @@ public class EsignContractFillingFileServiceImpl extends BaseServiceImpl() {{ + componentList.add(new HashMap() {{ put("componentKey", "plat_mobile" + finalI); - put("componentValue", esignPlatformInfo.getLegal_person_mobile()); + put("componentValue", platformInfo.getLegal_person_mobile()); }}); } // 乙方邮箱(重复填充,但保持原逻辑) for (int i = 0; i < 6; i++) { - list.add(new HashMap() {{ + componentList.add(new HashMap() {{ put("componentKey", "plat_email1"); - put("componentValue", esignPlatformInfo.getEmail()); + put("componentValue", platformInfo.getEmail()); }}); } // 乙方银行 - list.add(new HashMap() {{ + componentList.add(new HashMap() {{ put("componentKey", "plat_bank1"); - put("componentValue", esignPlatformInfo.getRec_acc_bank_name()); + put("componentValue", platformInfo.getRec_acc_bank_name()); }}); // 乙方账户号 - list.add(new HashMap() {{ + componentList.add(new HashMap() {{ put("componentKey", "plat_account_number1"); - put("componentValue", esignPlatformInfo.getRec_acc_card_no()); + put("componentValue", platformInfo.getRec_acc_card_no()); }}); // 11. 处理代理商相关数据 if (distributor != null) { // 有代理商的时候,填充代理商的信息 - list.add(new HashMap() {{ + componentList.add(new HashMap() {{ put("componentKey", "distr_company1"); put("componentValue", distributor.getLicense_company()); }}); - list.add(new HashMap() {{ + componentList.add(new HashMap() {{ put("componentKey", "distr_mobile1"); put("componentValue", distributor.getLegal_person_mobile()); }}); - list.add(new HashMap() {{ + componentList.add(new HashMap() {{ put("componentKey", "distr_company2"); put("componentValue", distributor.getLicense_company()); }}); - list.add(new HashMap() {{ + componentList.add(new HashMap() {{ put("componentKey", "distr_bank1"); put("componentValue", distributor.getRec_acc_bank_name()); }}); - list.add(new HashMap() {{ + componentList.add(new HashMap() {{ put("componentKey", "distr_account_number1"); put("componentValue", distributor.getRec_acc_card_no()); }}); - list.add(new HashMap() {{ + componentList.add(new HashMap() {{ put("componentKey", "distr_sign_date1"); put("componentValue", today); }}); @@ -384,24 +384,24 @@ public class EsignContractFillingFileServiceImpl extends BaseServiceImpl() {{ + componentList.add(new HashMap() {{ put("componentKey", "distr_company1"); put("componentValue", "无"); }}); - list.add(new HashMap() {{ + componentList.add(new HashMap() {{ put("componentKey", "distr_mobile1"); put("componentValue", "无"); }}); - list.add(new HashMap() {{ + componentList.add(new HashMap() {{ put("componentKey", "distr_company2"); put("componentValue", "无"); }}); - list.add(new HashMap() {{ + componentList.add(new HashMap() {{ put("componentKey", "distr_bank1"); put("componentValue", "无"); }}); - list.add(new HashMap() {{ + componentList.add(new HashMap() {{ put("componentKey", "distr_account_number1"); put("componentValue", "无"); }}); @@ -409,7 +409,7 @@ public class EsignContractFillingFileServiceImpl extends BaseServiceImpl signPositionMap = getSignPosition(templateId, fileId); if (signPositionMap != null) { if (signPositionMap.get("mch") != null) { - esignContractFillingFile.setMch_sign_position(signPositionMap.get("mch").toString()); + contractFillingFile.setMch_sign_position(signPositionMap.get("mch").toString()); } if (signPositionMap.get("plat") != null) { - esignContractFillingFile.setPlat_sign_position(signPositionMap.get("plat").toString()); + contractFillingFile.setPlat_sign_position(signPositionMap.get("plat").toString()); } if (distributor != null && signPositionMap.get("distr") != null) { // 如果有代理商,则把代理商的印章位置信息写入数据库 - esignContractFillingFile.setDistri_sign_position(signPositionMap.get("distr").toString()); + contractFillingFile.setDistri_sign_position(signPositionMap.get("distr").toString()); } } // 17. 保存合同填充记录并预创建签署流程 - if (esignContractFillingFileService.trySaveRecord(esignContractFillingFile)) { + if (esignContractFillingFileService.trySaveRecord(contractFillingFile)) { successCnt += 1; log.debug("[合同生成] 合同记录保存成功, fileId: {}", fileId); // 预新增一个签署合同记录 boolean preCreateResult = esignContractService.preCreateSignFlow( - esignContractFillingFile.getMobile(), esignContractFillingFile.getDoc_template_id()); + contractFillingFile.getMobile(), contractFillingFile.getDoc_template_id()); log.debug("[合同生成] 预创建签署流程结果: {}, 商家手机号: {}, 模板ID: {}", - preCreateResult, esignContractFillingFile.getMobile(), esignContractFillingFile.getDoc_template_id()); + preCreateResult, contractFillingFile.getMobile(), contractFillingFile.getDoc_template_id()); } else { log.error("[合同生成] 保存合同记录失败, fileId: {}", fileId); } diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/esign/service/impl/EsignContractServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/esign/service/impl/EsignContractServiceImpl.java index e5147939..142dd5a7 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/esign/service/impl/EsignContractServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/esign/service/impl/EsignContractServiceImpl.java @@ -167,61 +167,77 @@ public class EsignContractServiceImpl extends BaseServiceImpl innerSignFlowCreateByFile(Integer storeId) { + // 1. 参数校验 if (CheckUtil.isEmpty(storeId)) { return Pair.of(false, "缺少必要参数!"); } - // 组织和填充商家店铺的模版数据 + // 2. 组织和填充商家店铺的模版数据 Boolean isFill = esignContractFillingFileService.fillDocTemplate(storeId); if (!isFill) { return Pair.of(false, "合同信息未准备好,请检查商家入驻手续是否已完成!"); } + // 3. 获取商家合同信息 EsignContract esignContract = getEsignContractByStoreId(storeId); if (esignContract == null) { return Pair.of(false, "未找到商家合同信息"); } - // 检查商户入驻信息是否被审核通过 - // 检查店铺是否已经申请过入驻 + // 4. 检查商户入驻信息是否被审核通过 Integer apprStatus = shopMchEntryService.getApprovalStatus(esignContract.getMch_mobile()); if (!CommonConstant.MCH_APPR_STA_PASS.equals(apprStatus)) { return Pair.of(false, "请先审核商家入驻信息"); } - //"{\"docs\":[{\"fileId\":\"ab30d2c5600441f4a7daf512e4d69157\",\"fileName\":\"小发同城平台商户合作协议.pdf\"}],\"signFlowConfig\":{\"signFlowTitle\":\"小发同城平台商户合作协议\",\"signFlowExpireTime\":1746844718000,\"autoFinish\":true,\"notifyUrl\":\"https://mall.gpxscs.cn/asyn/notify\",\"redirectConfig\":{\"redirectUrl\":\"https://mall.gpxscs.cn/\"}},\"signers\":[{\"signConfig\":{\"signOrder\":1},\"noticeConfig\":{\"noticeTypes\":\"1\"},\"signerType\":0,\"psnSignerInfo\":{\"psnAccount\":\"13128997057\",\"psnInfo\":{\"psnName\":\"潘军杰\"}},\"signFields\":[{\"fileId\":\"ab30d2c5600441f4a7daf512e4d69157\",\"normalSignFieldConfig\":{\"signFieldStyle\":1,\"signFieldPosition\":{\"positionPage\":40,\"positionX\":472.3607,\"positionY\":277.19104}}},{\"fileId\":\"ab30d2c5600441f4a7daf512e4d69157\",\"normalSignFieldConfig\":{\"signFieldStyle\":1,\"signFieldPosition\":{\"positionPage\":5,\"positionX\":470.58798,\"positionY\":589.14496}}}]},{\"signConfig\":{\"signOrder\":2},\"noticeConfig\":{\"noticeTypes\":\"1\"},\"signerType\":1,\"orgSignerInfo\":{\"orgName\":\"桂平发发网络有限公司\",\"orgInfo\":{\"orgIDCardNum\":\"91450881MADEQ92533\",\"orgIDCardType\":\"CRED_ORG_USCC\"},\"transactorInfo\":{\"psnAccount\":\"17777525395\",\"psnInfo\":{\"psnName\":\"谢能坤\"}}},\"signFields\":[{\"fileId\":\"ab30d2c5600441f4a7daf512e4d69157\",\"normalSignFieldConfig\":{\"signFieldStyle\":1,\"signFieldPosition\":{\"positionPage\":2,\"positionX\":479.04996,\"positionY\":357.2327}}},{\"fileId\":\"ab30d2c5600441f4a7daf512e4d69157\",\"normalSignFieldConfig\":{\"signFieldStyle\":1,\"signFieldPosition\":{\"positionPage\":5,\"positionX\":255.96832,\"positionY\":588.4553}}}]}]}"; -// esignContractService. + // 5. 获取签署请求参数 String jsonParams = esignContract.getReq_params(); + if (StrUtil.isBlank(jsonParams)) { + return Pair.of(false, "合同请求参数为空"); + } try { - //请求方法 + // 6. 调用E签宝API创建签署流程 EsignRequestType requestType = EsignRequestType.POST; - String apiAddr = "/v3/sign-flow/create-by-file"; - Map header = EsignHttpHelper.signAndBuildSignAndJsonHeader(appId, appSecret, jsonParams, requestType.name(), apiAddr, true); - //发起接口请求 - EsignHttpResponse createByDocTemplate = EsignHttpHelper.doCommHttp(serverUrl, apiAddr, requestType, jsonParams, header, debug); - log.info("发起合同签署流程返回消息:{},{}", createByDocTemplate.getStatus(), createByDocTemplate.getBody()); - if (createByDocTemplate.getStatus() != 200) { - if (createByDocTemplate.getBody() != null) { - JSONObject resBody = JSONUtil.parseObj(createByDocTemplate.getBody()); - log.error("e签宝请求失败,返回状态码:{}, {}", createByDocTemplate.getStatus(), resBody.getStr("message")); - return Pair.of(false, "e签宝请求失败,{}" + resBody.getStr("message")); + Map header = EsignHttpHelper.signAndBuildSignAndJsonHeader( + appId, appSecret, jsonParams, requestType.name(), apiAddr, true); + + EsignHttpResponse response = EsignHttpHelper.doCommHttp( + serverUrl, apiAddr, requestType, jsonParams, header, debug); + + log.info("发起合同签署流程返回消息:status={}, body={}", response.getStatus(), response.getBody()); + + // 7. 处理API响应结果 + if (response.getStatus() != HttpStatus.OK.value()) { + String errorMsg = "E签宝请求失败"; + if (response.getBody() != null) { + try { + JSONObject resBody = JSONUtil.parseObj(response.getBody()); + errorMsg += "," + resBody.getStr("message", "未知错误"); + } catch (Exception parseException) { + log.warn("解析E签宝错误响应失败:{}", response.getBody()); + } } - return Pair.of(false, "e签宝请求失败!"); + log.error("E签宝请求失败,返回状态码:{}", response.getStatus()); + return Pair.of(false, errorMsg); } - JSONObject jsonObject = JSONUtil.parseObj(createByDocTemplate.getBody()); + // 8. 解析成功响应数据 + JSONObject jsonObject = JSONUtil.parseObj(response.getBody()); Integer code = jsonObject.getInt("code"); - String signFlowId = (String) jsonObject.getByPath("data.signFlowId"); + String signFlowId = jsonObject.getByPath("data.signFlowId", String.class); + if (code == null || code != 0 || StrUtil.isBlank(signFlowId)) { - log.error("e签宝请求失败,返回status码:{}", code); - return Pair.of(false, "e签宝请求失败!"); + log.error("E签宝请求失败,返回 code 码:{}", code); + return Pair.of(false, "E签宝请求失败!"); } - //合同签署状态:-1:预备数据阶段;0-等待签署;1-已部分签署;2-已完成(所有签署方完成签署)3-已撤销(发起方撤销签署任务)5-已过期(签署截止日到期后触发)7-已拒签(签署方拒绝签署) - Boolean success = updateContractFlowIdAndFileUrl(esignContract.getId(), signFlowId, CommonConstant.CONTRACT_SIGN_STA_ING, null); + // 9. 更新合同流程状态 + Boolean success = updateContractFlowIdAndFileUrl( + esignContract.getId(), signFlowId, CommonConstant.CONTRACT_SIGN_STA_ING, null); + if (!success) { log.error("更新合同流程状态失败"); return Pair.of(false, "更新合同流程状态失败"); @@ -229,12 +245,13 @@ public class EsignContractServiceImpl extends BaseServiceImpl>>>>> {}", signature); if (!mySignature.equals(signature)) { - log.warn("e签宝异步通知签名校验失败: 计算签名={}, 请求签名={}", mySignature, signature); + log.warn("E签宝异步通知签名校验失败: 计算签名={}, 请求签名={}", mySignature, signature); return ResponseEntity.status(HttpStatus.BAD_REQUEST) .body(new JSONObject().put("code", 400).put("msg", "签名校验失败").toString()); } @@ -288,7 +305,7 @@ public class EsignContractServiceImpl extends BaseServiceImpl * 收到异步通知,签署完成之后,获取合同文件地址,保存并上传到 oss * @@ -837,7 +854,7 @@ public class EsignContractServiceImpl extends BaseServiceImpl createNextSeqPair(String prefix) { - String ymd = DateUtil.format(new Date(), "yyyyMMdd"); - String id = String.format("%s_%s_", prefix, ymd); - ShopNumberSeq shopNumberSeq = this.baseMapper.selectById(id); - if (shopNumberSeq == null) { - shopNumberSeq = new ShopNumberSeq(); - shopNumberSeq.setPrefix(id); - shopNumberSeq.setNumber(1L); - if (!save(shopNumberSeq)) { - return null; + // 参数校验 + if (prefix == null || prefix.trim().isEmpty()) { + return null; + } + + try { + String ymd = DateUtil.format(new Date(), "yyyyMMdd"); + String seqId = String.format("%s_%s_", prefix, ymd); + + // 查询或创建序列记录 + ShopNumberSeq shopNumberSeq = this.baseMapper.selectById(seqId); + if (shopNumberSeq == null) { + shopNumberSeq = new ShopNumberSeq(); + shopNumberSeq.setPrefix(seqId); + shopNumberSeq.setNumber(1L); + if (!save(shopNumberSeq)) { + return null; + } } - } - String order_id = String.format("%s_%s_%s", prefix, ymd, shopNumberSeq.getNumber()); - shopNumberSeq.setPrefix(id); - boolean flag = edit(shopNumberSeq); - if (flag) { - return Pair.of(shopNumberSeq.getNumber(), order_id); - } + // 获取当前序列号 + Long number = shopNumberSeq.getNumber(); + String orderId = String.format("%s_%s_%s", prefix, ymd, number); - return null; + // 增加序列号并更新 + // shopNumberSeq.setNumber(number + 1); + shopNumberSeq.setPrefix(seqId); + return edit(shopNumberSeq) ? Pair.of(number, orderId) : null; + + } catch (Exception e) { + log.error("生成序列号失败,prefix: {}", prefix, e); + return null; + } } + /** * 得到下一个Id * diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/order/service/impl/ShopOrderBaseServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/order/service/impl/ShopOrderBaseServiceImpl.java index aece29b9..13a0e99d 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/order/service/impl/ShopOrderBaseServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/order/service/impl/ShopOrderBaseServiceImpl.java @@ -6421,7 +6421,7 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl seqPair = shopNumberSeqService.createNextSeqPair(type_code);// 位数的序号: DD_20251205_1 2025-12-05 1 + Pair seqPair = shopNumberSeqService.createNextSeqPair(type_code);// 位数的序号: DD_20251205_12-> pair 12, 2025-12-05 String order_id = seqPair.getSecond(); Long seqNo = seqPair.getFirst(); // 序号: DD_20251205_1 得出 1 RootContext.bind(xid); From eb8fb4a4e9c5c265215b5b26a7be06f54fc746a3 Mon Sep 17 00:00:00 2001 From: Jack <46790855@qq.com> Date: Mon, 8 Dec 2025 17:08:08 +0800 Subject: [PATCH 02/28] =?UTF-8?q?=E7=94=A8=E6=88=B7=E6=8F=90=E4=BA=A4?= =?UTF-8?q?=E5=8F=96=E6=B6=88=E8=AE=A2=E5=8D=95=E6=B5=81=E7=A8=8B=E4=BF=AE?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../order/service/ShopOrderBaseService.java | 8 +- .../impl/ShopOrderBaseServiceImpl.java | 210 ++++++++++-------- 2 files changed, 126 insertions(+), 92 deletions(-) diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/order/service/ShopOrderBaseService.java b/mall-shop/src/main/java/com/suisung/mall/shop/order/service/ShopOrderBaseService.java index 41a68fe5..0db71718 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/order/service/ShopOrderBaseService.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/order/service/ShopOrderBaseService.java @@ -459,20 +459,20 @@ public interface ShopOrderBaseService extends IBaseService { * * @param order_id * @param shopOrderInfo - * @param check_paid_flag + * @param checkPaidState 订单是否未支付,默认值 true * @return */ - boolean cancel(String order_id, ShopOrderInfo shopOrderInfo, boolean check_paid_flag); + boolean cancel(String order_id, ShopOrderInfo shopOrderInfo, boolean checkPaidState); /** * 取消订单 * * @param order_ids * @param order_rows - * @param check_paid_flag + * @param isNotPaid 订单是否未支付,默认值 true * @return */ - boolean cancel(List order_ids, List order_rows, boolean check_paid_flag); + boolean cancel(List order_ids, List order_rows, boolean isNotPaid); void exportFile(HttpServletResponse response, ShopOrderBase shopOrderBase, List order_ids); diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/order/service/impl/ShopOrderBaseServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/order/service/impl/ShopOrderBaseServiceImpl.java index 13a0e99d..f6fbb494 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/order/service/impl/ShopOrderBaseServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/order/service/impl/ShopOrderBaseServiceImpl.java @@ -1087,7 +1087,7 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl order_ids, List order_rows, boolean check_paid_flag) { - List cancel_id_row = new ArrayList<>(order_ids.size()); + public boolean cancel(List orderIds, List orderRows, boolean checkPaidState) { + List cancelIdRow = new ArrayList<>(orderIds.size()); // 检测数据是否合法,过滤允许修改的数据 - if (CollUtil.isEmpty(order_ids)) { + if (CollUtil.isEmpty(orderIds)) { throw new ApiException(I18nUtil._("请选择需要取消的订单")); } - if (CollUtil.isEmpty(order_rows)) { - order_rows = Convert.toList(Map.class, shopOrderInfoService.gets(order_ids)); + if (CollUtil.isEmpty(orderRows)) { + orderRows = Convert.toList(Map.class, shopOrderInfoService.gets(orderIds)); } - for (String order_id : order_ids) { - Optional orderOpl = order_rows.stream().filter(s -> ObjectUtil.equal(order_id, Convert.toStr(s.get("order_id")))).findFirst(); - Map order = orderOpl.orElseGet(HashMap::new); + // 筛选可取消的订单 + for (String orderId : orderIds) { + Optional orderOpt = orderRows.stream() + .filter(s -> ObjectUtil.equal(orderId, Convert.toStr(s.get("order_id")))) + .findFirst(); + Map order = orderOpt.orElseGet(HashMap::new); + // 订单状态(LIST):2011-待订单审核;2013-待财务审核;2020-待配货/待出库审核;2030-待发货;2040-已发货/待收货确认;2060-已完成/已签收;2070-已取消/已作废; - Integer order_state_id = (Integer) order.get("order_state_id"); + Integer orderStateId = (Integer) order.get("order_state_id"); // 付款状态(ENUM):3010-未付款;3011-付款待审核;3012-部分付款;3013-已付款 - Integer order_is_paid = (Integer) order.get("order_is_paid"); - // 要检查订单付款状态 - if (check_paid_flag) { - if (ifCancel(order_state_id, order_is_paid)) { - // 未付款,未配送的订单才能取消订单 - cancel_id_row.add(order_id); + Integer orderIsPaid = (Integer) order.get("order_is_paid"); + + // 根据是否检查支付状态来判断订单是否可取消 + if (checkPaidState) { + // 检查订单是否可以取消(未付款且处于特定状态) + if (isOrderCancelable(orderStateId, orderIsPaid)) { + cancelIdRow.add(orderId); + } else { + // 订单已支付,检查是否允许退款 + boolean isOrderDenyReturn = shopOrderReturnService.isOrderDenyReturn(orderId); + if (!isOrderDenyReturn) { + // 支付的订单允许退款,立即发起退款流程,再由商家审核 + CommonResult refundResult = shopOrderReturnService.addRemainingItems(orderId, false, "用户取消订单"); + if (refundResult == null || refundResult.getStatus() != 200) { + logger.error("提交订单审核失败!"); + return false; + } + + return true; + } } } else { - // 不检查订单付款状态 - cancel_id_row.add(order_id); + // 不检查订单付款状态,直接加入可取消列表 + cancelIdRow.add(orderId); } } - if (CollUtil.isEmpty(cancel_id_row)) { + if (CollUtil.isEmpty(cancelIdRow)) { throw new ApiException(I18nUtil._("无符合取消条件的订单!")); } - order_ids = cancel_id_row; + orderIds = cancelIdRow; + // 更新订单主表状态为已取消 ShopOrderBase orderBase = new ShopOrderBase(); orderBase.setOrder_state_id(StateCode.ORDER_STATE_CANCEL); QueryWrapper baseQueryWrapper = new QueryWrapper<>(); - baseQueryWrapper.in("order_id", order_ids); + baseQueryWrapper.in("order_id", orderIds); baseQueryWrapper.ne("order_state_id", StateCode.ORDER_STATE_CANCEL); // 2070-已取消 - if (!edit(orderBase, baseQueryWrapper)) {// 批量更改状态 + if (!edit(orderBase, baseQueryWrapper)) { // 批量更改状态 throw new ApiException(ResultCode.FAILED); } + // 更新订单信息表状态为已取消 ShopOrderInfo shopOrderInfo = new ShopOrderInfo(); shopOrderInfo.setOrder_state_id(StateCode.ORDER_STATE_CANCEL); QueryWrapper infoQueryWrapper = new QueryWrapper<>(); - infoQueryWrapper.in("order_id", cancel_id_row); + infoQueryWrapper.in("order_id", cancelIdRow); infoQueryWrapper.ne("order_state_id", StateCode.ORDER_STATE_CANCEL); if (!shopOrderInfoService.edit(shopOrderInfo, infoQueryWrapper)) { - throw new ApiException(String.format("订单:%s 取消状态有误!", CollUtil.join(cancel_id_row, ","))); + throw new ApiException(String.format("订单:%s 取消状态有误!", CollUtil.join(cancelIdRow, ","))); } // 积分退还 order_resource_ext1 默认为积分。 - List order_data_rows = shopOrderDataService.gets(order_ids); - for (ShopOrderData order_data_row : order_data_rows) { - String orderId = order_data_row.getOrder_id(); + List orderDataRows = shopOrderDataService.gets(orderIds); + for (ShopOrderData orderDataRow : orderDataRows) { + String orderId = orderDataRow.getOrder_id(); - Optional orderOpl = order_rows.stream().filter(s -> ObjectUtil.equal(orderId, Convert.toStr(s.get("order_id")))).findFirst(); - Map order = orderOpl.orElseGet(HashMap::new); + Optional orderOpt = orderRows.stream() + .filter(s -> ObjectUtil.equal(orderId, Convert.toStr(s.get("order_id")))) + .findFirst(); + Map order = orderOpt.orElseGet(HashMap::new); - Integer buyer_user_id = (Integer) order.get("buyer_user_id"); - BigDecimal order_resource_ext1 = order_data_row.getOrder_resource_ext1();// 积分 - BigDecimal order_resource_ext2 = order_data_row.getOrder_resource_ext2();// 众宝 + Integer buyerUserId = (Integer) order.get("buyer_user_id"); + BigDecimal orderResourceExt1 = orderDataRow.getOrder_resource_ext1(); // 积分 + BigDecimal orderResourceExt2 = orderDataRow.getOrder_resource_ext2(); // 众宝 - if (ObjectUtil.compare(order_resource_ext1, BigDecimal.ZERO) > 0 && CheckUtil.isNotEmpty(buyer_user_id)) { - Integer store_id = (Integer) order.get("store_id"); + // 退还积分 + if (ObjectUtil.compare(orderResourceExt1, BigDecimal.ZERO) > 0 && CheckUtil.isNotEmpty(buyerUserId)) { + Integer storeId = (Integer) order.get("store_id"); // 扣除积分 - String desc = String.format("%s 积分退还,订单号 %s", order_resource_ext1, order_data_row.getOrder_id()); - if (!payService.points(buyer_user_id, order_resource_ext1, PointsType.POINTS_TYPE_CONSUME_RETRUN, desc, store_id, null, order_data_row.getOrder_id())) { + String desc = String.format("%s 积分退还,订单号 %s", orderResourceExt1, orderDataRow.getOrder_id()); + if (!payService.points(buyerUserId, orderResourceExt1, PointsType.POINTS_TYPE_CONSUME_RETRUN, desc, storeId, null, orderDataRow.getOrder_id())) { throw new ApiException(I18nUtil._("积分操作失败!")); } } // 程序没有编写完成,缺失众宝积分退回功能 - //if (ObjectUtil.compare(order_resource_ext2, BigDecimal.ZERO) > 0 && CheckUtil.isNotEmpty(buyer_user_id)) { - // String desc = String.format("%s 众宝退还", order_resource_ext2); - // todo shopUserPointsHistoryService.sp(buyer_user_id,order_resource_ext2,SpType.SP_TYPE_CONSUME_RETRUN, desc); - //} + // if (ObjectUtil.compare(orderResourceExt2, BigDecimal.ZERO) > 0 && CheckUtil.isNotEmpty(buyerUserId)) { + // String desc = String.format("%s 众宝退还", orderResourceExt2); + // todo shopUserPointsHistoryService.sp(buyerUserId, orderResourceExt2, SpType.SP_TYPE_CONSUME_RETRUN, desc); + // } } // 限购商品数量退还 QueryWrapper itemQueryWrapper = new QueryWrapper<>(); - itemQueryWrapper.in("order_id", order_ids); - List order_item_rows = shopOrderItemService.find(itemQueryWrapper); - - for (ShopOrderItem order_item_row : order_item_rows) { + itemQueryWrapper.in("order_id", orderIds); + List orderItemRows = shopOrderItemService.find(itemQueryWrapper); + for (ShopOrderItem orderItemRow : orderItemRows) { + // 退还用户购买数量限制 QueryWrapper buyQueryWrapper = new QueryWrapper<>(); - buyQueryWrapper.eq("product_id", order_item_row.getProduct_id()); - buyQueryWrapper.eq("item_id", order_item_row.getItem_id()); - buyQueryWrapper.eq("user_id", order_item_row.getBuyer_id()); + buyQueryWrapper.eq("product_id", orderItemRow.getProduct_id()); + buyQueryWrapper.eq("item_id", orderItemRow.getItem_id()); + buyQueryWrapper.eq("user_id", orderItemRow.getBuyer_id()); List productBuyList = shopUserProductBuyService.find(buyQueryWrapper); - Integer order_item_quantity = order_item_row.getOrder_item_quantity(); + Integer orderItemQuantity = orderItemRow.getOrder_item_quantity(); if (CollUtil.isNotEmpty(productBuyList)) { - + // 减少用户的已购买数量 for (ShopUserProductBuy productBuy : productBuyList) { - productBuy.setProduct_buy_num(productBuy.getProduct_buy_num() - order_item_quantity); + productBuy.setProduct_buy_num(productBuy.getProduct_buy_num() - orderItemQuantity); } if (!shopUserProductBuyService.saveOrUpdate(productBuyList)) { @@ -4242,29 +4265,29 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl stockDeltaMap = new HashMap<>(); -// stockDeltaMap.put(shopProductItem.getItem_src_id() + "-" + order_item_row.getOrder_id(), order_item_quantity); -// syncThirdDataService.incrProductStockToRedis(stockDeltaMap); + // Map stockDeltaMap = new HashMap<>(); + // stockDeltaMap.put(shopProductItem.getItem_src_id() + "-" + orderItemRow.getOrder_id(), orderItemQuantity); + // syncThirdDataService.incrProductStockToRedis(stockDeltaMap); } } // 退还礼包活动 - if (order_item_row.getActivity_type_id().equals(StateCode.ACTIVITY_TYPE_GIFTPACK)) { + if (orderItemRow.getActivity_type_id().equals(StateCode.ACTIVITY_TYPE_GIFTPACK)) { QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.eq("exchange_code", order_item_row.getActivity_code()); + queryWrapper.eq("exchange_code", orderItemRow.getActivity_code()); ShopStoreActivityCode shopStoreActivityCode = shopStoreActivityCodeService.findOne(queryWrapper); shopStoreActivityCode.setUser_id(0); shopStoreActivityCode.setOrder_id(""); @@ -4277,18 +4300,21 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl voucherQueryWrapper = new QueryWrapper<>(); - voucherQueryWrapper.in("order_id", order_ids); + voucherQueryWrapper.in("order_id", orderIds); List userVouchers = shopUserVoucherService.find(voucherQueryWrapper); if (CollUtil.isNotEmpty(userVouchers)) { - userVouchers = userVouchers.stream().map(userVoucher -> userVoucher.setVoucher_state_id(StateCode.VOUCHER_STATE_UNUSED)).collect(Collectors.toList()); + // 将已使用的优惠券状态重置为未使用 + userVouchers = userVouchers.stream() + .map(userVoucher -> userVoucher.setVoucher_state_id(StateCode.VOUCHER_STATE_UNUSED)) + .collect(Collectors.toList()); if (!shopUserVoucherService.edit(userVouchers)) { throw new ApiException(I18nUtil._("退还优惠券失败!")); } } - // 取消拼团 - for (String order_id : order_ids) { - cancelActivity(order_id); + // 取消拼团活动 + for (String orderId : orderIds) { + cancelActivity(orderId); } return true; @@ -5227,7 +5253,7 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl shopOrderInfos = shopOrderInfoService.gets(order_ids); List rows = Convert.toList(Map.class, shopOrderInfos); // 检查登录用户和订单店铺是否有权限操作取消动作 - if (CheckUtil.checkDataRights(user_id, rows, "buyer_user_id") || CheckUtil.checkDataRights(Convert.toInt(user.getStore_id()), rows, "store_id")) { + if (CheckUtil.checkDataRights(user_id, rows, "buyer_user_id") + || CheckUtil.checkDataRights(Convert.toInt(user.getStore_id()), rows, "store_id")) { cancel(order_ids, rows, true); } else { throw new ApiException(ResultCode.FORBIDDEN); @@ -5267,12 +5294,12 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl order_states = Arrays.asList(StateCode.ORDER_STATE_WAIT_PAY, StateCode.ORDER_STATE_WAIT_REVIEW, StateCode.ORDER_STATE_WAIT_FINANCE_REVIEW, StateCode.ORDER_STATE_PICKING, StateCode.ORDER_STATE_WAIT_SHIPPING); - // 3010-未付款,未付款的订单才能取消 - return order_states.contains(order_state_id) && ObjectUtil.equal(order_is_paid, StateCode.ORDER_PAID_STATE_NO); + private boolean isOrderCancelable(Integer orderStateId, Integer orderIsPaid) { + // 可以取消订单的状态列表:待付款、待审核、待财务审核、待配货、待发货 + List cancelableStates = Arrays.asList( + StateCode.ORDER_STATE_WAIT_PAY, + StateCode.ORDER_STATE_WAIT_REVIEW, + StateCode.ORDER_STATE_WAIT_FINANCE_REVIEW, + StateCode.ORDER_STATE_PICKING, + StateCode.ORDER_STATE_WAIT_SHIPPING + ); + + // 订单必须处于可取消状态且未付款才能取消 + return cancelableStates.contains(orderStateId) && + ObjectUtil.equal(orderIsPaid, StateCode.ORDER_PAID_STATE_NO); } // QueryWrapper queryWrapper, From 8bd8c49f3838c0cb5e4bddfb2244de463af24ed4 Mon Sep 17 00:00:00 2001 From: Jack <46790855@qq.com> Date: Tue, 9 Dec 2025 00:25:31 +0800 Subject: [PATCH 03/28] =?UTF-8?q?=E7=94=A8=E6=88=B7=E5=8B=BE=E9=80=89?= =?UTF-8?q?=E5=A4=9A=E4=B8=AA=E5=95=86=E5=93=81=E9=80=80=E6=AC=BE=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E5=BC=80=E5=8F=91=EF=BC=8C=E6=95=B4=E5=8D=95=E5=8F=96?= =?UTF-8?q?=E6=B6=88=E9=80=BB=E8=BE=91=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mobile/UserReturnController.java | 29 +- .../order/service/ShopOrderReturnService.java | 8 + .../impl/ShopOrderBaseServiceImpl.java | 7 +- .../impl/ShopOrderReturnServiceImpl.java | 325 +++++++++++++++++- 4 files changed, 355 insertions(+), 14 deletions(-) diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/order/controller/mobile/UserReturnController.java b/mall-shop/src/main/java/com/suisung/mall/shop/order/controller/mobile/UserReturnController.java index 5fa657ae..17048bbb 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/order/controller/mobile/UserReturnController.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/order/controller/mobile/UserReturnController.java @@ -1,6 +1,8 @@ package com.suisung.mall.shop.order.controller.mobile; import cn.hutool.core.bean.BeanUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.suisung.mall.common.api.CommonResult; import com.suisung.mall.common.api.ResultCode; @@ -15,10 +17,7 @@ import com.suisung.mall.shop.order.vo.OrderReturnVo; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; /** *

@@ -57,7 +56,7 @@ public class UserReturnController extends BaseControllerImpl { return shopOrderReturnService.returnItem(); } - @ApiOperation(value = "添加退款退货-部分退货,卖家也可以决定不退货退款,买家申请退款不支持。卖家可以主动退款。", notes = "添加退款退货-发货退货,卖家也可以决定不退货退款,买家申请退款不支持。卖家可以主动退款。") + @ApiOperation(value = "添加退款退货-部分退货", notes = "添加退款退货-发货退货,卖家也可以决定不退货退款,买家申请退款不支持。卖家可以主动退款。") @RequestMapping(value = "/addItem", method = RequestMethod.GET) public CommonResult addItem(OrderReturnVo orderReturnVo) { UserDto user = getCurrentUser(); @@ -77,6 +76,26 @@ public class UserReturnController extends BaseControllerImpl { return shopOrderReturnService.addItem(orderReturnInputVo, true); } + @ApiOperation(value = "批量添加退款退货(支持多个商品)", notes = "添加退款退货-发货退货,卖家也可以决定不退货退款,买家申请退款不支持。卖家可以主动退款。") + @RequestMapping(value = "/addItemBatch", method = RequestMethod.POST) + public CommonResult addItemBatch(@RequestBody JSONObject orderReturnVoJSON) { + if (orderReturnVoJSON == null) { + return CommonResult.failed("请求参数不能为空"); + } + + OrderReturnInputVo orderReturnInputVo = JSONUtil.toBean(orderReturnVoJSON, OrderReturnInputVo.class); + if (orderReturnInputVo == null) { + return CommonResult.failed("请求参数格式不正确"); + } + + UserDto user = getCurrentUser(); + if (user == null) { + return CommonResult.failed(ResultCode.NEED_LOGIN); + } + + return shopOrderReturnService.tryAddItemBatch(orderReturnInputVo); + } + @ApiOperation(value = "添加退款退货-整单退货", notes = "添加退款退货-整单退货") @RequestMapping(value = "/addWholeItems", method = RequestMethod.POST) public CommonResult addWholeItems(@RequestParam(name = "order_id") String order_id) { diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/order/service/ShopOrderReturnService.java b/mall-shop/src/main/java/com/suisung/mall/shop/order/service/ShopOrderReturnService.java index e00dcb59..e6a428c3 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/order/service/ShopOrderReturnService.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/order/service/ShopOrderReturnService.java @@ -50,6 +50,14 @@ public interface ShopOrderReturnService extends IBaseService { */ CommonResult addItem(OrderReturnInputVo orderReturnInputVo, Boolean needSendMsg); + /** + * 尝试批量添加退款退货申请(自动使用最大可退数量和金额),等待商家审核处理(同意或不同意) + * + * @param orderReturnInputVo 退款申请输入参数,支持订单多个商品退款 + * @return CommonResult 退款申请结果 + */ + CommonResult tryAddItemBatch(OrderReturnInputVo orderReturnInputVo); + Map getReturnDetail(String return_id); boolean processReviewList(ShopOrderReturn shopOrderReturn, Integer receiving_address); diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/order/service/impl/ShopOrderBaseServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/order/service/impl/ShopOrderBaseServiceImpl.java index f6fbb494..87046f57 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/order/service/impl/ShopOrderBaseServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/order/service/impl/ShopOrderBaseServiceImpl.java @@ -4167,11 +4167,12 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl order_return_items = orderReturnItemService.find(returnItemQueryWrapper); - if (CollUtil.isNotEmpty(order_return_items)) { throw new ApiException(I18nUtil._("此订单商品正在退款审核!")); } @@ -568,17 +568,16 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl available_return_num) { throw new ApiException(String.format("商品 %s 的退款数量超过可退数量,最多可退 %d 件", shopOrderItem.getItem_name(), available_return_num)); @@ -650,6 +649,208 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl data = new HashMap<>(); + + // 获取用户ID + Integer user_id = orderReturnInputVo.getUser_id(); + if (CheckUtil.isEmpty(user_id)) { + UserDto user = getCurrentUser(); + if (user == null) { + throw new ApiUserException(I18nUtil._("用户信息异常!")); + } + user_id = user.getId(); + } + + // 获取买家店铺ID(如果有) + Integer buyer_store_id = shopStoreBaseService.getStoreId(user_id); + + // 获取订单信息 + String order_id = orderReturnInputVo.getOrder_id(); + List order_item_ids = orderReturnInputVo.getReturn_items().stream() + .map(OrderReturnItemInputVo::getOrder_item_id) + .distinct() + .collect(Collectors.toList()); + + ShopOrderInfo shopOrderInfo = shopOrderInfoService.get(order_id); + if (shopOrderInfo == null) { + throw new ApiException(I18nUtil._("此订单信息数据有误!")); + } + + ShopOrderBase orderBase = shopOrderBaseService.get(order_id); + if (orderBase == null) { + throw new ApiException(I18nUtil._("此订单详细信息数据有误!")); + } + + // 判断此订单商品是否有正在审核的退款单 + QueryWrapper returnQueryWrapper = new QueryWrapper<>(); + returnQueryWrapper.eq("order_id", order_id) + .eq("return_state_id", StateCode.RETURN_PROCESS_CHECK); + List order_return_rows = find(returnQueryWrapper); + + if (CollUtil.isNotEmpty(order_return_rows)) { + List return_ids = order_return_rows.stream() + .map(ShopOrderReturn::getReturn_id) + .collect(Collectors.toList()); + + QueryWrapper returnItemQueryWrapper = new QueryWrapper<>(); + returnItemQueryWrapper.in("order_item_id", order_item_ids) + .in("return_id", return_ids); + List order_return_items = orderReturnItemService.find(returnItemQueryWrapper); + if (CollUtil.isNotEmpty(order_return_items)) { + throw new ApiException(I18nUtil._("此订单商品正在退款审核!")); + } + } + + // 检查数据权限 + if (!CheckUtil.checkDataRights(user_id, orderBase, ShopOrderBase::getBuyer_user_id)) { + throw new ApiException(ResultCode.FORBIDDEN); + } + + // 获取退款申请参数 + String return_id = orderReturnInputVo.getReturn_id(); + Integer return_reason_id = orderReturnInputVo.getReturn_reason_id() == null ? 0 : orderReturnInputVo.getReturn_reason_id(); + String return_buyer_message = orderReturnInputVo.getReturn_buyer_message(); + Integer store_id = Convert.toInt(orderBase.getStore_id()); + String return_tel = orderReturnInputVo.getReturn_tel(); + + // 手机号验证 + if (StrUtil.isNotBlank(return_tel) && !PhoneUtil.isMobile(return_tel)) { + throw new ApiException(I18nUtil._("手机号输入有误!")); + } + + Date curTime = new Date(); + + // 构建退款单主表信息 + ShopOrderReturn orderReturn = new ShopOrderReturn(); + orderReturn.setReturn_id(return_id); + orderReturn.setOrder_id(order_id); + orderReturn.setBuyer_user_id(user_id); + orderReturn.setBuyer_store_id(buyer_store_id); + orderReturn.setReturn_reason_id(return_reason_id); + orderReturn.setReturn_buyer_message(return_buyer_message); + orderReturn.setStore_id(store_id); + orderReturn.setReturn_refund_amount(BigDecimal.ZERO); + orderReturn.setReturn_commision_fee(BigDecimal.ZERO); + orderReturn.setReturn_state_id(StateCode.RETURN_PROCESS_CHECK); + orderReturn.setReturn_tel(return_tel); + orderReturn.setReturn_year(DateUtil.year(curTime)); // 退单年份-索引查询 + orderReturn.setReturn_month(DateUtil.month(curTime) + 1); // 退单月份-索引查询 + orderReturn.setReturn_day(DateUtil.dayOfMonth(curTime)); // 退单日-索引查询 + orderReturn.setReturn_reason_id(0); // 注意:这里覆盖了前面设置的return_reason_id + orderReturn.setReturn_store_user_id(0); + orderReturn.setReturn_mobile(0L); + orderReturn.setReturn_telephone(""); + orderReturn.setSubsite_id(shopOrderInfo.getSubsite_id()); + + // 构建退款单明细信息 + List shopOrderReturnItems = new ArrayList<>(); + for (OrderReturnItemInputVo returnItemInputVo : orderReturnInputVo.getReturn_items()) { + // 获取订单商品信息 + ShopOrderItem shopOrderItem = shopOrderItemService.get(returnItemInputVo.getOrder_item_id()); + if (shopOrderItem == null) { + throw new ApiException("订单商品不存在,请检查商品ID是否正确: " + returnItemInputVo.getOrder_item_id()); + } + + // 验证是否为当前订单的商品 + if (!order_id.equals(shopOrderItem.getOrder_id())) { + throw new ApiException("商品ID " + returnItemInputVo.getOrder_item_id() + " 不属于订单 " + order_id); + } + + // 获取商品索引信息 + ShopProductIndex shopProductIndex = shopProductIndexService.get(shopOrderItem.getProduct_id()); + if (shopProductIndex == null) { + throw new ApiException("商品信息不存在,请检查商品ID是否正确: " + shopOrderItem.getProduct_id()); + } + + // 检查是否允许退货 + boolean is_denyreturn = ifDenyReturn(shopOrderInfo, shopOrderItem, shopProductIndex); + if (is_denyreturn) { + // 获取更详细的拒绝退货原因 + String denyReason = getDenyReturnReason(shopOrderInfo, shopOrderItem, shopProductIndex); + if (StrUtil.isBlank(denyReason)) { + denyReason = "此商品不允许退货!"; + } + throw new ApiException(denyReason); + } + + // 构建退款单明细 + ShopOrderReturnItem orderReturnItem = new ShopOrderReturnItem(); + + // 检查退款数量是否超过可退数量 + Integer order_item_quantity = shopOrderItem.getOrder_item_quantity(); // 订单中该商品的原始购买数量 + Integer order_item_return_agree_num = ObjectUtil.defaultIfNull(shopOrderItem.getOrder_item_return_agree_num(), 0); // 订单中该商品已经同意退货的数量 + Integer available_return_num = order_item_quantity - order_item_return_agree_num; // 当前还可以申请退款的商品数量 + if (available_return_num <= 0) { + throw new ApiException(String.format("商品 %s 已无可退数量", shopOrderItem.getItem_name())); + } + + // 检查退款金额是否合理 + BigDecimal order_item_payment_amount = shopOrderItem.getOrder_item_payment_amount(); + BigDecimal order_item_return_agree_amount = ObjectUtil.defaultIfNull(shopOrderItem.getOrder_item_return_agree_amount(), BigDecimal.ZERO); + BigDecimal available_return_amount = order_item_payment_amount.subtract(order_item_return_agree_amount); + if (available_return_amount.compareTo(BigDecimal.ZERO) <= 0) { + throw new ApiException(String.format("商品 %s 已无可退金额", shopOrderItem.getItem_name())); + } + + String return_item_image = ObjectUtil.defaultIfBlank( + orderReturnInputVo.getRefund_pic(), + orderReturnInputVo.getUpload_img()); + + orderReturnItem.setOrder_item_id(returnItemInputVo.getOrder_item_id()); + orderReturnItem.setOrder_id(order_id); + orderReturnItem.setReturn_item_num(available_return_num); + orderReturnItem.setReturn_item_subtotal(available_return_amount); + orderReturnItem.setReturn_reason_id(return_reason_id); + orderReturnItem.setReturn_item_note(return_buyer_message); + orderReturnItem.setReturn_item_image(return_item_image); + orderReturnItem.setReturn_state_id(StateCode.RETURN_PROCESS_CHECK); + + shopOrderReturnItems.add(orderReturnItem); + } + + // 保存退款单 + if (!addReturnByItem(orderReturn, shopOrderReturnItems)) { + throw new ApiException(ResultCode.FAILED); + } + + data.put("return", orderReturn); + data.put("items", shopOrderReturnItems); + + // 打票机打印退款订单到店(异步执行) + shopStorePrinterService.printShopStoreReturnOrder(return_id); + + // 发送消息通知, 退款提醒商家 + String message_id = "refund-reminder"; + Map args = new HashMap<>(); + args.put("order_id", orderReturn.getReturn_id()); + messageService.sendNoticeMsg(0, store_id, message_id, args); + + // 发送unipush消息 + String title = "您有一个退款的订单,请及时前往后台审核!"; + String content = String.format("订单号:%s 退单号:[%s],时间:%s,请及时前往后台审核!", + order_id, orderReturn.getReturn_id(), + DateTimeUtils.formatDateTime(LocalDateTime.now(), "yyyy-MM-dd HH:mm:ss")); + JSONObject payload = JSONUtil.createObj(); + payload.set("category", CommonConstant.PUSH_MSG_CATE_MCH_RETURN_ORDER_LIST); + payload.set("orderId", order_id); + payload.set("returnId", orderReturn.getReturn_id()); + pushMessageService.noticeMerchantEmployeeOrderAction(store_id, order_id, title, content, payload); + + data.put("order_item_ids", order_item_ids); + return CommonResult.success(data); + } + /** * 取消退货 @@ -3099,4 +3300,116 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl availableReturnNum) { + if (!autoCorrect) { + throw new ApiException(String.format("商品 %s 的退款数量超过可退数量,最多可退 %d 件", + shopOrderItem.getItem_name(), availableReturnNum)); + } + + // 按比例调整退款金额 + BigDecimal ratio = BigDecimal.valueOf(availableReturnNum) + .divide(BigDecimal.valueOf(requestReturnNum), 6, RoundingMode.HALF_UP); + BigDecimal correctedAmount = requestRefundAmount.multiply(ratio); + return new BigDecimal[]{BigDecimal.valueOf(availableReturnNum), correctedAmount}; + } + + // 校验并处理请求退款金额是否超过可退金额 + if (requestRefundAmount.compareTo(availableReturnAmount) > 0) { + if (!autoCorrect) { + throw new ApiException(String.format("商品 %s 的退款金额超过可退金额,最多可退 %.2f 元", + shopOrderItem.getItem_name(), availableReturnAmount)); + } + return new BigDecimal[]{BigDecimal.valueOf(requestReturnNum), availableReturnAmount}; + } + + return new BigDecimal[]{BigDecimal.valueOf(requestReturnNum), requestRefundAmount}; + } + + /** + * 校验退款商品数量是否有效(专用于仅校验数量的场景) + * + * @param shopOrderItem 订单商品项 + * @param requestReturnNum 请求退款数量 + * @param autoCorrect 是否自动纠正数量(false:超出时抛出异常, true:超出时自动调整为最大可退数量) + * @return 校验后的有效退款数量 + * @throws ApiException 当autoCorrect为false且请求数量超出可退数量时抛出异常 + */ + private Integer validateReturnQuantity(ShopOrderItem shopOrderItem, Integer requestReturnNum, boolean autoCorrect) { + // 校验请求参数有效性 + if (requestReturnNum <= 0) { + throw new ApiException("退款数量必须大于0,请检查商品 " + shopOrderItem.getItem_name() + " 的退款数量"); + } + + // 计算可退数量 + Integer orderItemQuantity = shopOrderItem.getOrder_item_quantity(); + Integer orderItemReturnAgreeNum = ObjectUtil.defaultIfNull(shopOrderItem.getOrder_item_return_agree_num(), 0); + Integer availableReturnNum = orderItemQuantity - orderItemReturnAgreeNum; + + // 检查是否还有可退数量 + if (availableReturnNum <= 0) { + if (autoCorrect) { + return 0; + } + throw new ApiException(String.format("商品 %s 已无可退数量,无法申请退款", shopOrderItem.getItem_name())); + } + + // 校验并处理请求退款数量是否超过可退数量 + if (requestReturnNum > availableReturnNum) { + if (!autoCorrect) { + throw new ApiException(String.format("商品 %s 的退款数量超过可退数量,最多可退 %d 件", + shopOrderItem.getItem_name(), availableReturnNum)); + } + return availableReturnNum; + } + + return requestReturnNum; + } + + } \ No newline at end of file From fe5c88442731687d2f7142664ff7e548f77ba5fd Mon Sep 17 00:00:00 2001 From: Jack <46790855@qq.com> Date: Tue, 9 Dec 2025 00:26:05 +0800 Subject: [PATCH 04/28] =?UTF-8?q?=E7=94=A8=E6=88=B7=E5=8B=BE=E9=80=89?= =?UTF-8?q?=E5=A4=9A=E4=B8=AA=E5=95=86=E5=93=81=E9=80=80=E6=AC=BE=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E5=BC=80=E5=8F=91=EF=BC=8C=E6=95=B4=E5=8D=95=E5=8F=96?= =?UTF-8?q?=E6=B6=88=E9=80=BB=E8=BE=91=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../impl/ShopOrderReturnServiceImpl.java | 112 ------------------ 1 file changed, 112 deletions(-) diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/order/service/impl/ShopOrderReturnServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/order/service/impl/ShopOrderReturnServiceImpl.java index 333973a4..d356b0fe 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/order/service/impl/ShopOrderReturnServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/order/service/impl/ShopOrderReturnServiceImpl.java @@ -74,7 +74,6 @@ import org.springframework.transaction.annotation.Transactional; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.math.BigDecimal; -import java.math.RoundingMode; import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; @@ -3300,116 +3299,5 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl availableReturnNum) { - if (!autoCorrect) { - throw new ApiException(String.format("商品 %s 的退款数量超过可退数量,最多可退 %d 件", - shopOrderItem.getItem_name(), availableReturnNum)); - } - - // 按比例调整退款金额 - BigDecimal ratio = BigDecimal.valueOf(availableReturnNum) - .divide(BigDecimal.valueOf(requestReturnNum), 6, RoundingMode.HALF_UP); - BigDecimal correctedAmount = requestRefundAmount.multiply(ratio); - return new BigDecimal[]{BigDecimal.valueOf(availableReturnNum), correctedAmount}; - } - - // 校验并处理请求退款金额是否超过可退金额 - if (requestRefundAmount.compareTo(availableReturnAmount) > 0) { - if (!autoCorrect) { - throw new ApiException(String.format("商品 %s 的退款金额超过可退金额,最多可退 %.2f 元", - shopOrderItem.getItem_name(), availableReturnAmount)); - } - return new BigDecimal[]{BigDecimal.valueOf(requestReturnNum), availableReturnAmount}; - } - - return new BigDecimal[]{BigDecimal.valueOf(requestReturnNum), requestRefundAmount}; - } - - /** - * 校验退款商品数量是否有效(专用于仅校验数量的场景) - * - * @param shopOrderItem 订单商品项 - * @param requestReturnNum 请求退款数量 - * @param autoCorrect 是否自动纠正数量(false:超出时抛出异常, true:超出时自动调整为最大可退数量) - * @return 校验后的有效退款数量 - * @throws ApiException 当autoCorrect为false且请求数量超出可退数量时抛出异常 - */ - private Integer validateReturnQuantity(ShopOrderItem shopOrderItem, Integer requestReturnNum, boolean autoCorrect) { - // 校验请求参数有效性 - if (requestReturnNum <= 0) { - throw new ApiException("退款数量必须大于0,请检查商品 " + shopOrderItem.getItem_name() + " 的退款数量"); - } - - // 计算可退数量 - Integer orderItemQuantity = shopOrderItem.getOrder_item_quantity(); - Integer orderItemReturnAgreeNum = ObjectUtil.defaultIfNull(shopOrderItem.getOrder_item_return_agree_num(), 0); - Integer availableReturnNum = orderItemQuantity - orderItemReturnAgreeNum; - - // 检查是否还有可退数量 - if (availableReturnNum <= 0) { - if (autoCorrect) { - return 0; - } - throw new ApiException(String.format("商品 %s 已无可退数量,无法申请退款", shopOrderItem.getItem_name())); - } - - // 校验并处理请求退款数量是否超过可退数量 - if (requestReturnNum > availableReturnNum) { - if (!autoCorrect) { - throw new ApiException(String.format("商品 %s 的退款数量超过可退数量,最多可退 %d 件", - shopOrderItem.getItem_name(), availableReturnNum)); - } - return availableReturnNum; - } - - return requestReturnNum; - } - } \ No newline at end of file From 6185956410f6a8bdad3a5e3c9f878bf3be0b3729 Mon Sep 17 00:00:00 2001 From: liyj <1617420630@qq.com> Date: Tue, 9 Dec 2025 17:32:15 +0800 Subject: [PATCH 05/28] =?UTF-8?q?=E6=A8=A1=E6=9D=BF=E5=B8=82=E5=9C=BA?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E8=A1=8C=E4=B8=9A=E6=9F=A5=E8=AF=A2=EF=BC=8C?= =?UTF-8?q?=E5=A4=8D=E5=88=B6=E6=A8=A1=E6=9D=BF=E9=BB=98=E8=AE=A4=E4=B8=8D?= =?UTF-8?q?=E5=8F=91=E5=B8=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../shop/page/controller/admin/ShopPageAppController.java | 5 +++++ .../mall/shop/page/service/impl/ShopPageAppServiceImpl.java | 1 + 2 files changed, 6 insertions(+) diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/page/controller/admin/ShopPageAppController.java b/mall-shop/src/main/java/com/suisung/mall/shop/page/controller/admin/ShopPageAppController.java index 1abdd980..54ff588e 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/page/controller/admin/ShopPageAppController.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/page/controller/admin/ShopPageAppController.java @@ -492,10 +492,15 @@ public class ShopPageAppController extends BaseControllerImpl { } QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("is_pulish", "1"); + queryWrapper.eq("app_industry", "1"); String appName= getParameter("appName"); if(StringUtils.isNotEmpty(appName)){ queryWrapper.like("app_name", appName); } + String app_industry= getParameter("appIndustry"); + if(StringUtils.isNotEmpty(app_industry)){ + queryWrapper.eq("app_industry", app_industry); + } Page shopPageAppPage= shopPageAppService.lists(queryWrapper,pageNum,pageSize); List shopPageAppPageList = shopPageAppPage.getRecords(); for (ShopPageApp shopPageApp : shopPageAppPageList) { diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/page/service/impl/ShopPageAppServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/page/service/impl/ShopPageAppServiceImpl.java index 5f6a56d6..791f40ac 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/page/service/impl/ShopPageAppServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/page/service/impl/ShopPageAppServiceImpl.java @@ -1024,6 +1024,7 @@ public class ShopPageAppServiceImpl extends BaseServiceImpl sourceShopPageBaseQueryWrapper = new QueryWrapper<>(); From c1dc9994ebdbad0a6a984647a5fa74cf2ce9cb38 Mon Sep 17 00:00:00 2001 From: liyj <1617420630@qq.com> Date: Tue, 9 Dec 2025 17:34:43 +0800 Subject: [PATCH 06/28] =?UTF-8?q?=E5=8E=BB=E9=99=A4=E5=A4=9A=E4=BD=99?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mall/shop/page/controller/admin/ShopPageAppController.java | 1 - 1 file changed, 1 deletion(-) diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/page/controller/admin/ShopPageAppController.java b/mall-shop/src/main/java/com/suisung/mall/shop/page/controller/admin/ShopPageAppController.java index 54ff588e..c787c91a 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/page/controller/admin/ShopPageAppController.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/page/controller/admin/ShopPageAppController.java @@ -492,7 +492,6 @@ public class ShopPageAppController extends BaseControllerImpl { } QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("is_pulish", "1"); - queryWrapper.eq("app_industry", "1"); String appName= getParameter("appName"); if(StringUtils.isNotEmpty(appName)){ queryWrapper.like("app_name", appName); From 78dce9f77be961562fc8b67d0fbd822d0e5e2818 Mon Sep 17 00:00:00 2001 From: Jack <46790855@qq.com> Date: Thu, 11 Dec 2025 12:06:35 +0800 Subject: [PATCH 07/28] =?UTF-8?q?=E5=B9=B3=E5=8F=B0=E5=86=85=E9=83=A8?= =?UTF-8?q?=E9=85=8D=E9=80=81=E8=B4=B9=E7=9A=84=E9=80=BB=E8=BE=91=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mall/common/feignService/ShopService.java | 4 +- .../pojo/dto/OrderCacDeliveryFeeDTO.java | 47 +++ .../pay/service/AccountBaseConfigService.java | 4 +- .../impl/AccountBaseConfigServiceImpl.java | 31 +- .../service/impl/LakalaPayServiceImpl.java | 6 +- .../service/impl/PayUserPayServiceImpl.java | 2 +- .../service/AccountBaseConfigService.java | 20 +- .../impl/AccountBaseConfigServiceImpl.java | 154 +++++++++- .../order/mapper/ShopOrderInfoMapper.java | 26 ++ .../order/service/ShopOrderInfoService.java | 25 +- .../impl/ShopOrderBaseServiceImpl.java | 43 ++- .../impl/ShopOrderInfoServiceImpl.java | 48 +++ .../impl/ShopOrderReturnServiceImpl.java | 50 ++++ .../service/impl/SFExpressApiServiceImpl.java | 6 +- .../admin/ShopStoreInfoController.java | 14 +- ...pStoreSameCityTransportBaseController.java | 6 +- ...SameCityTransportBaseMobileController.java | 6 +- ...ShopStoreSameCityTransportBaseService.java | 29 +- .../impl/ShopStoreInfoServiceImpl.java | 3 +- ...StoreSameCityTransportBaseServiceImpl.java | 279 +++++++++++++++++- .../service/impl/ShopUserCartServiceImpl.java | 6 +- 21 files changed, 728 insertions(+), 81 deletions(-) create mode 100644 mall-common/src/main/java/com/suisung/mall/common/pojo/dto/OrderCacDeliveryFeeDTO.java diff --git a/mall-common/src/main/java/com/suisung/mall/common/feignService/ShopService.java b/mall-common/src/main/java/com/suisung/mall/common/feignService/ShopService.java index 73af2839..cabe8b6c 100644 --- a/mall-common/src/main/java/com/suisung/mall/common/feignService/ShopService.java +++ b/mall-common/src/main/java/com/suisung/mall/common/feignService/ShopService.java @@ -326,12 +326,12 @@ public interface ShopService { /** * 获取店铺的内部运费 shopping_fee_inner (远程调用用途) * - * @param store_id + * @param order_id * @return */ @ApiOperation(value = "获取店铺的内部运费 shopping_fee_inner", notes = "获取店铺的内部运费 shopping_fee_inner (远程调用用途)") @RequestMapping(value = "/admin/shop/shop-store-info/shopping-fee-inner", method = RequestMethod.POST) - Integer storeShoppingFeeInner(@RequestParam(name = "store_id") Integer store_id); + Integer storeShoppingFeeInner(@RequestParam(name = "order_id") String order_id); @GetMapping(value = "/admin/shop/shop-store-employee-rights-base/queryByRightsIds") diff --git a/mall-common/src/main/java/com/suisung/mall/common/pojo/dto/OrderCacDeliveryFeeDTO.java b/mall-common/src/main/java/com/suisung/mall/common/pojo/dto/OrderCacDeliveryFeeDTO.java new file mode 100644 index 00000000..146be51f --- /dev/null +++ b/mall-common/src/main/java/com/suisung/mall/common/pojo/dto/OrderCacDeliveryFeeDTO.java @@ -0,0 +1,47 @@ +package com.suisung.mall.common.pojo.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.math.BigDecimal; + + +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@ApiModel(value = "OrderDeliveryInfoDTO", description = "计算订单内部配送费参数实体类") +public class OrderCacDeliveryFeeDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "订单ID") + private String order_id; + + @ApiModelProperty(value = "店铺ID") + private Integer store_id; + + @ApiModelProperty(value = "配送方式Id") + private Integer delivery_type_id; + + @ApiModelProperty(value = "订单商品金额") + private BigDecimal order_product_amount; + + @ApiModelProperty(value = "订单支付金额") + private BigDecimal order_payment_amount; + + @ApiModelProperty(value = "订单折扣金额") + private BigDecimal order_discount_amount; + + @ApiModelProperty(value = "订单重量(克)") + private Integer order_weight_gram; + + @ApiModelProperty(value = "配送地址经度") + private String da_longitude; + + @ApiModelProperty(value = "配送地址纬度") + private String da_latitude; +} \ No newline at end of file diff --git a/mall-pay/src/main/java/com/suisung/mall/pay/service/AccountBaseConfigService.java b/mall-pay/src/main/java/com/suisung/mall/pay/service/AccountBaseConfigService.java index 2521325a..25e5d117 100644 --- a/mall-pay/src/main/java/com/suisung/mall/pay/service/AccountBaseConfigService.java +++ b/mall-pay/src/main/java/com/suisung/mall/pay/service/AccountBaseConfigService.java @@ -50,9 +50,9 @@ public interface AccountBaseConfigService extends IBaseService { */ Long getOrderCountByStoreId(Integer storeId, List orderStatusIdList, List orderRefundStatusIdList, List deliveryTypeList, Long expireSeconds); + + /** + * 根据订单ID获取计算配送费所需的订单信息 + *

+ * 查询逻辑说明: + * 1. 从订单基础信息表获取订单ID、店铺ID和商品总额 + * 2. 从订单数据表计算实际支付金额(订单支付金额 - 运费金额) + * 3. 从订单数据表计算折扣金额(商品零售总额 - 折扣金额 - 优惠券金额 - 调整金额 - 积分抵扣金额) + * 4. 从订单配送地址表获取配送地址的经纬度 + * + * @param orderId 订单ID + * @return OrderCacDeliveryFeeDTO 订单配送费计算参数实体 + */ + @Select("SELECT sob.order_id,sob.store_id,sob.order_product_amount,sob.order_payment_amount," + + "(sob.order_product_amount-sod.order_discount_amount-sod.voucher_price-sod.order_adjust_fee-sod.order_points_fee) as order_discount_amount," + + "0 as order_weight_gram," + + "aoda.da_longitude,aoda.da_latitude, soi.delivery_type_id " + + "FROM shop_order_base sob " + + "JOIN shop_order_data sod ON sob.order_id=sod.order_id " + + "JOIN shop_order_info soi ON sob.order_id=soi.order_id " + + "JOIN shop_order_delivery_address aoda ON sob.order_id=aoda.order_id " + + "WHERE sob.order_id=#{orderId}") + OrderCacDeliveryFeeDTO getOrderCacDeliveryFeeArgs(String orderId); + } diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/order/service/ShopOrderInfoService.java b/mall-shop/src/main/java/com/suisung/mall/shop/order/service/ShopOrderInfoService.java index 968209fd..47a00897 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/order/service/ShopOrderInfoService.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/order/service/ShopOrderInfoService.java @@ -3,6 +3,7 @@ package com.suisung.mall.shop.order.service; import com.suisung.mall.common.api.CommonResult; import com.suisung.mall.common.modules.order.ShopOrderInfo; import com.suisung.mall.common.pojo.dto.BookingArgDTO; +import com.suisung.mall.common.pojo.dto.OrderCacDeliveryFeeDTO; import com.suisung.mall.core.web.service.IBaseService; import org.springframework.data.util.Pair; @@ -145,11 +146,33 @@ public interface ShopOrderInfoService extends IBaseService { List genBookingOrderArgList(String storeId); /** - * 获取某个活动订单成功数量 + * 获取某个活动订单成功数量(目前砍价用途) * * @param activityId 活动ID * @param activityTypeId 活动类型ID, 可选参数 * @return */ long fetchActivityOrderSuccessCount(String activityId, String activityTypeId); + + /** + * 获取某个订单是否存在(满足)内部配送费 + * + * @param deliveryTypeId 店铺ID + * @return Pair,第一个元素表示是否满足内部配送费条件,第二个元素为内部配送费金额 + */ + Boolean hasInnerMinDeliveryFee(Integer deliveryTypeId); + + /** + * 根据订单ID获取计算配送费所需的订单信息 + *

+ * 查询逻辑说明: + * 1. 从订单基础信息表获取订单ID、店铺ID和商品总额 + * 2. 从订单数据表计算实际支付金额(订单支付金额 - 运费金额) + * 3. 从订单数据表计算折扣金额(商品总额 - 折扣金额 - 调整金额 - 积分抵扣金额) + * 4. 从订单配送地址表获取配送地址的经纬度 + * + * @param orderId 订单ID + * @return OrderCacDeliveryFeeDTO 订单配送费计算参数实体 + */ + OrderCacDeliveryFeeDTO getOrderCacDeliveryFeeArgs(String orderId); } diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/order/service/impl/ShopOrderBaseServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/order/service/impl/ShopOrderBaseServiceImpl.java index 87046f57..9e1cca1a 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/order/service/impl/ShopOrderBaseServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/order/service/impl/ShopOrderBaseServiceImpl.java @@ -917,6 +917,8 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl productBaseOpl = product_rows.stream().filter(s -> ObjectUtil.equal(product_id, Convert.toInt(s.get("product_id")))).findFirst(); @@ -962,8 +964,7 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl + * 内部配送费仅适用于同城配送方式,该方法通过检查配送方式是否为同城配送来判断是否满足条件 + * + * @param deliveryTypeId 配送方式ID + * @return Boolean 是否满足内部配送费条件 + */ + @Override + public Boolean hasInnerMinDeliveryFee(Integer deliveryTypeId) { + // 参数校验 + if (CheckUtil.isEmpty(deliveryTypeId)) { + logger.warn("[获取内部配送费] 配送方式ID为空,deliveryTypeId: {}", deliveryTypeId); + return false; + } + + // 检查配送方式是否为同城配送(只有同城配送才有内部配送费) + boolean isSameCityDelivery = StateCode.DELIVERY_TYPE_MAP.containsKey(deliveryTypeId) + && ObjectUtil.equal(StateCode.DELIVERY_TYPE_SAME_CITY, deliveryTypeId); + + logger.debug("[获取内部配送费] 配送方式检查结果, deliveryTypeId: {}, isSameCityDelivery: {}", + deliveryTypeId, isSameCityDelivery); + + return isSameCityDelivery; + } + + + /** + * 根据订单ID获取计算配送费所需的订单信息 + *

+ * 查询逻辑说明: + * 1. 从订单基础信息表获取订单ID、店铺ID和商品总额 + * 2. 从订单数据表计算实际支付金额(订单支付金额 - 运费金额) + * 3. 从订单数据表计算折扣金额(商品总额 - 折扣金额 - 调整金额 - 积分抵扣金额) + * 4. 从订单配送地址表获取配送地址的经纬度 + * + * @param orderId 订单ID + * @return OrderCacDeliveryFeeDTO 订单配送费计算参数实体 + */ + @Override + public OrderCacDeliveryFeeDTO getOrderCacDeliveryFeeArgs(String orderId) { + if (StrUtil.isBlank(orderId)) { + return null; + } + return shopOrderInfoMapper.getOrderCacDeliveryFeeArgs(orderId); + } + /** * 根据一个或多个店铺id获取有效店铺的有效营业时间段 diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/order/service/impl/ShopOrderReturnServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/order/service/impl/ShopOrderReturnServiceImpl.java index d356b0fe..a940aaa3 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/order/service/impl/ShopOrderReturnServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/order/service/impl/ShopOrderReturnServiceImpl.java @@ -2581,6 +2581,11 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl 0 (订单商品数量 > 已退货数量) + * 3. 可退金额 > 0 (订单商品金额 > 已同意退款金额) + * + * @param orderItemId 订单子项ID + * @return boolean 是否可以退款 + */ + private boolean ifCanReturnOrderItem(Long orderItemId) { + // 查询订单子项是否存在 + ShopOrderItem orderItem = shopOrderItemService.get(orderItemId); + return ifCanReturnOrderItem(orderItem); + } + + /** + * 判断订单子项是否可以退款 + * 条件: + * 1. 订单子项必须存在 + * 2. 可退数量 > 0 (订单商品数量 > 已退货数量) + * 3. 可退金额 > 0 (订单商品金额 > 已同意退款金额) + * + * @param orderItem 订单子项 + * @return boolean 是否可以退款 + */ + private boolean ifCanReturnOrderItem(ShopOrderItem orderItem) { + // 如果订单子项不存在,不能退款 + if (orderItem == null) { + return false; + } + + // 获取订单子项的相关字段,使用默认值避免空指针 + Integer orderItemQuantity = ObjectUtil.defaultIfNull(orderItem.getOrder_item_quantity(), 0); + Integer orderItemReturnNum = ObjectUtil.defaultIfNull(orderItem.getOrder_item_return_num(), 0); + BigDecimal orderItemAmount = ObjectUtil.defaultIfNull(orderItem.getOrder_item_amount(), BigDecimal.ZERO); + BigDecimal orderItemReturnAgreeAmount = ObjectUtil.defaultIfNull(orderItem.getOrder_item_return_agree_amount(), BigDecimal.ZERO); + + // 判断是否可以退款: + // 1. 可退数量 > 0 + // 2. 可退金额 > 0 + return orderItemQuantity > orderItemReturnNum + && orderItemAmount.compareTo(orderItemReturnAgreeAmount) > 0; + } + } \ No newline at end of file diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/sfexpress/service/impl/SFExpressApiServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/sfexpress/service/impl/SFExpressApiServiceImpl.java index b4e5af13..ac0eaf46 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/sfexpress/service/impl/SFExpressApiServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/sfexpress/service/impl/SFExpressApiServiceImpl.java @@ -269,12 +269,12 @@ public class SFExpressApiServiceImpl implements SFExpressApiService { // 3. 获取或初始化商家配送信息 ShopStoreSameCityTransportBase transportBase = shopStoreSameCityTransportBaseService - .getShopStoreSameCityTransportBaseById(Long.valueOf(storeId)); + .getShopStoreSameCityTransportBaseById(Long.valueOf(storeId), CommonConstant.Disable2); if (transportBase == null) { // 如果没有商家配送运费设置,则初始化 shopStoreSameCityTransportBaseService.initDefaultSameCityTransport(storeId); - transportBase = shopStoreSameCityTransportBaseService.getShopStoreSameCityTransportBaseById(Long.valueOf(storeId)); + transportBase = shopStoreSameCityTransportBaseService.getShopStoreSameCityTransportBaseById(Long.valueOf(storeId), CommonConstant.Disable2); } if (transportBase == null) { @@ -963,7 +963,7 @@ public class SFExpressApiServiceImpl implements SFExpressApiService { return new ThirdApiRes().fail(1003, "缺少店铺 Id!"); } - ShopStoreSameCityTransportBase shopStoreSameCityTransportBase = shopStoreSameCityTransportBaseService.getShopStoreSameCityTransportBaseById(storeId); + ShopStoreSameCityTransportBase shopStoreSameCityTransportBase = shopStoreSameCityTransportBaseService.getShopStoreSameCityTransportBaseById(storeId, CommonConstant.Disable2); if (shopStoreSameCityTransportBase == null) { logger.error("无法获取顺丰店铺 Id!"); return new ThirdApiRes().fail(1003, "无法获取店铺Id"); diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/store/controller/admin/ShopStoreInfoController.java b/mall-shop/src/main/java/com/suisung/mall/shop/store/controller/admin/ShopStoreInfoController.java index 8ef5668c..42178dcb 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/store/controller/admin/ShopStoreInfoController.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/store/controller/admin/ShopStoreInfoController.java @@ -5,10 +5,12 @@ import com.suisung.mall.common.api.CommonResult; import com.suisung.mall.common.domain.UserDto; import com.suisung.mall.common.modules.store.ShopStoreInfo; import com.suisung.mall.common.service.impl.BaseControllerImpl; +import com.suisung.mall.shop.base.service.AccountBaseConfigService; import com.suisung.mall.shop.store.service.ShopStoreInfoService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Lazy; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; @@ -30,6 +32,12 @@ public class ShopStoreInfoController extends BaseControllerImpl { @Autowired private ShopStoreInfoService shopStoreInfoService; + + @Lazy + @Autowired + private AccountBaseConfigService accountBaseConfigService; + + /** * 分页列表查询 * @@ -83,13 +91,13 @@ public class ShopStoreInfoController extends BaseControllerImpl { /** * 获取店铺的内部运费 shopping_fee_inner (远程调用用途) * - * @param store_id + * @param order_id * @return */ @ApiOperation(value = "获取店铺的内部运费 shopping_fee_inner", notes = "获取店铺的内部运费 shopping_fee_inner (远程调用用途)") @RequestMapping(value = "/shopping-fee-inner", method = RequestMethod.POST) - public Integer storeShoppingFeeInner(@RequestParam(name = "store_id") Integer store_id) { - return shopStoreInfoService.getStoreShippingFeeInner(store_id); + public Integer storeShoppingFeeInner(@RequestParam(name = "order_id") String order_id) { + return accountBaseConfigService.getInnerMinDeliveryFee(order_id); } } diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/store/controller/admin/ShopStoreSameCityTransportBaseController.java b/mall-shop/src/main/java/com/suisung/mall/shop/store/controller/admin/ShopStoreSameCityTransportBaseController.java index 4855ecaa..c3d35f76 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/store/controller/admin/ShopStoreSameCityTransportBaseController.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/store/controller/admin/ShopStoreSameCityTransportBaseController.java @@ -10,8 +10,6 @@ import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; -import javax.annotation.Resource; - @Api(tags = "同城配送运费设置控制器") @RestController @RequestMapping("/admin/shop/store/same-city-transport") @@ -25,8 +23,8 @@ public class ShopStoreSameCityTransportBaseController { @ApiOperation(value = "获取同城配送运费设置详情", notes = "获取同城配送运费设置详情") @RequestMapping(value = "/detail", method = {RequestMethod.GET}) - public CommonResult shopStoreSameCityTransportBaseDetail() { - return transportBaseService.ShopStoreSameCityTransportBaseDetail(); + public CommonResult shopStoreSameCityTransportBaseDetail(@RequestParam(name = "is_platfrom", defaultValue = "2") Integer isPlatform) { + return transportBaseService.ShopStoreSameCityTransportBaseDetail(isPlatform); } @ApiOperation(value = "保存(新增或修改)同城配送运费设置", notes = "保存(新增或修改)同城配送运费设置") diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/store/controller/mobile/ShopStoreSameCityTransportBaseMobileController.java b/mall-shop/src/main/java/com/suisung/mall/shop/store/controller/mobile/ShopStoreSameCityTransportBaseMobileController.java index c7cb57b3..040b1028 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/store/controller/mobile/ShopStoreSameCityTransportBaseMobileController.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/store/controller/mobile/ShopStoreSameCityTransportBaseMobileController.java @@ -10,8 +10,6 @@ import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import javax.annotation.Resource; - @Api(tags = "同城配送运费设置控制器") @RestController @RequestMapping("/mobile/shop/store/same-city-transport") @@ -22,7 +20,7 @@ public class ShopStoreSameCityTransportBaseMobileController { @ApiOperation(value = "下单前检测同城订单配送是否符合要求", notes = "下单前检测同城订单配送是否符合要求") @RequestMapping(value = "/check/same-city/delivery", method = {RequestMethod.POST}) - public CommonResult checkSameCityDelivery(@RequestParam(name = "store_id", defaultValue = "0") Integer storeId) { - return transportBaseService.ShopStoreSameCityTransportBaseDetail(); + public CommonResult checkSameCityDelivery(@RequestParam(name = "is_platfrom", defaultValue = "2") Integer isPlatform) { + return transportBaseService.ShopStoreSameCityTransportBaseDetail(isPlatform); } } \ No newline at end of file diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/ShopStoreSameCityTransportBaseService.java b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/ShopStoreSameCityTransportBaseService.java index bbd76846..037a86c1 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/ShopStoreSameCityTransportBaseService.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/ShopStoreSameCityTransportBaseService.java @@ -23,7 +23,7 @@ public interface ShopStoreSameCityTransportBaseService { * * @return */ - CommonResult ShopStoreSameCityTransportBaseDetail(); + CommonResult ShopStoreSameCityTransportBaseDetail(Integer isPlatform); /** * 保存或更新同城配送各项设置 @@ -52,17 +52,19 @@ public interface ShopStoreSameCityTransportBaseService { * 根据店铺 Id 获取同城配送设置详情信息 * * @param storeId + * @param isPlatform 1-平台 2-店铺 * @return */ - ShopStoreSameCityTransportBaseDTO getShopStoreSameCityTransportBaseDTOById(Long storeId); + ShopStoreSameCityTransportBaseDTO getShopStoreSameCityTransportBaseDTOById(Long storeId, Integer isPlatform); /** * 根据店铺Id获取同城配送基础运费记录 * * @param storeId + * @param isPlatform 1-平台 2-店铺 * @return */ - ShopStoreSameCityTransportBase getShopStoreSameCityTransportBaseById(Long storeId); + ShopStoreSameCityTransportBase getShopStoreSameCityTransportBaseById(Long storeId, Integer isPlatform); /** * 保存同城配送基础设置(存在更新,不存在新增) @@ -96,4 +98,25 @@ public interface ShopStoreSameCityTransportBaseService { */ SameCityDeliveryFeeRespDTO computeSameCityTransportFee(Long storeId, String orderLongitude, String orderLatitude, Integer weightGram, BigDecimal orderProductAmount, BigDecimal orderDiscountAmount, BigDecimal orderPayAmount, Boolean canThrow); + /** + * 平台计算同城订单的内部配送费(仅仅作用于平台内部配送费计算,商家配送费忽略此方法,只对下单成功的订单起效果) + * + * @param orderId 订单ID + * @return 配送费,单位为分 + */ + Integer computeSameCityInnerDeliveryFeeByOrderId(String orderId); + + /** + * 平台计算同城订单的内部配送费(仅仅作用于平台内部配送费计算,商家配送费忽略此方法,下单前可以查询) + * + * @param storeId 店铺Id + * @param orderLongitude (订单送达地)目的地经度 + * @param orderLatitude (订单送达地)目的地维度 + * @param orderWeightGram 订单重量(单位克) + * @param orderProductAmount 订单商品原价金额 + * @param orderDiscountAmount 订单商品折扣金额(订单原价减去每个商品折扣费) + * @param orderPayAmount 订单实际支付金额(折扣金额-优惠券-积分扣-人工干预扣费),不包含运费 + * @return 配送费,单位为分 + */ + Integer computeSameCityInnerDeliveryFee(Integer storeId, String orderLongitude, String orderLatitude, Integer orderWeightGram, BigDecimal orderProductAmount, BigDecimal orderDiscountAmount, BigDecimal orderPayAmount); } \ No newline at end of file diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreInfoServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreInfoServiceImpl.java index 5c9631ae..a804394b 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreInfoServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreInfoServiceImpl.java @@ -131,7 +131,7 @@ public class ShopStoreInfoServiceImpl extends BaseServiceImpl - * 店铺内部运费,单位(分)0-使用平台的内部运费;>0 使用店铺的内部运费 + * 店铺内部运费,单位(分)使用店铺的内部运费<=0 的时候 * * @param storeId 店铺ID * @return 内部运费,单位分 @@ -147,7 +147,6 @@ public class ShopStoreInfoServiceImpl extends BaseServiceImpl queryWrapper = new QueryWrapper<>(); queryWrapper.eq("store_id", storeId).select("shopping_fee_inner"); ShopStoreInfo shopStoreInfo = getOne(queryWrapper); - if (shopStoreInfo == null || CheckUtil.isEmpty(shopStoreInfo.getShopping_fee_inner())) { return 0; } diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreSameCityTransportBaseServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreSameCityTransportBaseServiceImpl.java index 46ba9523..8579f4da 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreSameCityTransportBaseServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreSameCityTransportBaseServiceImpl.java @@ -25,6 +25,7 @@ import com.suisung.mall.common.modules.store.ShopStoreBase; import com.suisung.mall.common.modules.store.ShopStoreSameCityTransport; import com.suisung.mall.common.modules.store.ShopStoreSameCityTransportBase; import com.suisung.mall.common.pojo.dto.DeliveryFeeResultDTO; +import com.suisung.mall.common.pojo.dto.OrderCacDeliveryFeeDTO; import com.suisung.mall.common.pojo.dto.SameCityDeliveryFeeRespDTO; import com.suisung.mall.common.pojo.dto.ShopStoreSameCityTransportBaseDTO; import com.suisung.mall.common.utils.CommonUtil; @@ -32,6 +33,7 @@ import com.suisung.mall.common.utils.I18nUtil; import com.suisung.mall.common.utils.PositionUtil; import com.suisung.mall.core.web.service.impl.BaseServiceImpl; import com.suisung.mall.shop.base.service.AccountBaseConfigService; +import com.suisung.mall.shop.order.service.ShopOrderInfoService; import com.suisung.mall.shop.store.mapper.ShopStoreSameCityTransportBaseMapper; import com.suisung.mall.shop.store.service.ShopStoreBaseService; import com.suisung.mall.shop.store.service.ShopStoreSameCityTransportBaseService; @@ -64,6 +66,11 @@ public class ShopStoreSameCityTransportBaseServiceImpl extends BaseServiceImpl 2) { + isPlatform = CommonConstant.Disable2; + } + Long storeId = Convert.toLong(user.getStore_id()); - ShopStoreSameCityTransportBaseDTO retDTO = getShopStoreSameCityTransportBaseDTOById(storeId); + ShopStoreSameCityTransportBaseDTO retDTO = getShopStoreSameCityTransportBaseDTOById(storeId, isPlatform); if (retDTO == null) { return CommonResult.failed("商家未设置店铺地址,请先设置店铺地址!"); } @@ -226,10 +237,11 @@ public class ShopStoreSameCityTransportBaseServiceImpl extends BaseServiceImpl 2) { + isPlatform = 2; + } + QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("store_id", storeId); + queryWrapper.eq("is_platform", isPlatform); queryWrapper.eq("status", CommonConstant.Enable); return getOne(queryWrapper); @@ -298,11 +315,19 @@ public class ShopStoreSameCityTransportBaseServiceImpl extends BaseServiceImpl saveOrUpdateShopStoreSameCityTransportBase(ShopStoreSameCityTransportBase transportBase) { try { + // 参数校验 if (transportBase == null || transportBase.getStore_id() == null || transportBase.getStore_id() <= 0) { + log.warn("保存或更新同城配送基础信息参数校验失败: transportBase={}", transportBase); return Pair.of(0L, "缺少店铺Id必要参数!"); } - // 设置默认值 + Integer isPlatform = transportBase.getIs_platform(); + if (isPlatform == null || isPlatform < 0 || isPlatform > 2) { + isPlatform = 2; + transportBase.setIs_platform(isPlatform); + } + + // 设置默认值 - 使用更清晰的条件判断 if (transportBase.getDistance_base() == null || transportBase.getDistance_base() < 0) { transportBase.setDistance_base(0); } @@ -327,36 +352,51 @@ public class ShopStoreSameCityTransportBaseServiceImpl extends BaseServiceImpl queryWrapper = new QueryWrapper<>(); queryWrapper.eq("store_id", transportBase.getStore_id()); + queryWrapper.eq("is_platform", transportBase.getIs_platform()); + queryWrapper.eq("status", CommonConstant.Enable); ShopStoreSameCityTransportBase exist = getOne(queryWrapper); + Date now = new Date(); if (exist == null) { - // 新增 + // 新增操作 + log.debug("开始新增同城配送基础信息, storeId={}", transportBase.getStore_id()); transportBase.setCreated_by(transportBase.getUpdated_by()); + transportBase.setCreated_at(now); + transportBase.setUpdated_at(now); + if (add(transportBase)) { // 确保获取到ID Long transportBaseId = transportBase.getTransport_base_id(); if (transportBaseId == null || transportBaseId <= 0) { // 补偿机制:若transportBase.getTransport_base_id()==null,重新查询数据 + log.debug("新增后ID为空,重新查询获取ID, storeId={}", transportBase.getStore_id()); exist = getOne(queryWrapper); if (exist != null) { transportBaseId = exist.getTransport_base_id(); } } + log.info("新增同城配送基础信息成功, transportBaseId={}, storeId={}", transportBaseId, transportBase.getStore_id()); return Pair.of(transportBaseId, "添加成功!"); } else { + log.error("新增同城配送基础信息失败, storeId={}", transportBase.getStore_id()); return Pair.of(0L, "添加失败!"); } } else { - // 更新 + // 更新操作 + log.debug("开始更新同城配送基础信息, transportBaseId={}, storeId={}", exist.getTransport_base_id(), transportBase.getStore_id()); transportBase.setTransport_base_id(exist.getTransport_base_id()); + transportBase.setUpdated_at(now); + if (updateById(transportBase)) { + log.info("更新同城配送基础信息成功, transportBaseId={}, storeId={}", transportBase.getTransport_base_id(), transportBase.getStore_id()); return Pair.of(transportBase.getTransport_base_id(), "更新成功!"); } else { + log.error("更新同城配送基础信息失败, transportBaseId={}, storeId={}", transportBase.getTransport_base_id(), transportBase.getStore_id()); return Pair.of(0L, "更新失败!"); } } } catch (Exception e) { - log.error("保存或更新同城配送基础信息异常: ", e); + log.error("保存或更新同城配送基础信息异常, storeId={}", transportBase != null ? transportBase.getStore_id() : "unknown", e); return Pair.of(0L, "系统内部错误"); } } @@ -406,6 +446,11 @@ public class ShopStoreSameCityTransportBaseServiceImpl extends BaseServiceImpl 2) { + isPlatform = 2; + } + transportBase.setIs_platform(isPlatform); transportBase.setStore_id(Convert.toLong(storeBase.getStore_id())); transportBase.setStore_longitude(storeBase.getStore_longitude()); transportBase.setStore_latitude(storeBase.getStore_latitude()); @@ -461,7 +506,6 @@ public class ShopStoreSameCityTransportBaseServiceImpl extends BaseServiceImpl 0 && diffWeightKg.intValue() > transportBase.getWeight_increase_kg()) { // 末尾非零进位,比如:2.1将是3, 2.0将是2,2.001将是3 - times = NumberUtil.div(diffWeightKg, transportBase.getDistance_increase_km()).setScale(0, RoundingMode.UP); + times = NumberUtil.div(diffWeightKg, transportBase.getWeight_increase_kg()).setScale(0, RoundingMode.UP); } deliveryBaseFee = deliveryBaseFee.add(transportBase.getWeight_increase_fee().multiply(times)); @@ -690,4 +734,213 @@ public class ShopStoreSameCityTransportBaseServiceImpl extends BaseServiceImpl transportList = shopStoreSameCityTransportService.selectShopStoreSameCityTransportList(Convert.toLong(storeId)); + + if (CollUtil.isEmpty(transportList)) { + // 没有配送范围规则的时候,直接以基础配送费来配送 + return deliveryBaseFee.multiply(BigDecimal.valueOf(100)).intValue(); + } + + // 判断配送范围和起送金额条件 + String canNotDeliveryReason = ""; + boolean canDelivery = false; + + // 优先处理距离和金额都满足的规则 + for (ShopStoreSameCityTransport transport : transportList) { + // 判断订单距离是否在配送范围内 + if (transport.getMax_delivery_radius() >= distance) { + // 距离在配送范围内,判断金额是否符合起配金额额度 + boolean moneyPassed = false; + if (CommonConstant.Delivery_Amount_Comput_Type_Original.equals(transport.getMin_delivery_amount_type())) { + moneyPassed = orderProductAmount != null && transport.getMin_delivery_amount().compareTo(orderProductAmount) <= 0; + } else if (CommonConstant.Delivery_Amount_Comput_Type_Discounted.equals(transport.getMin_delivery_amount_type())) { + moneyPassed = orderDiscountAmount != null && transport.getMin_delivery_amount().compareTo(orderDiscountAmount) <= 0; + } else if (CommonConstant.Delivery_Amount_Comput_Type_Payment.equals(transport.getMin_delivery_amount_type())) { + moneyPassed = orderPayAmount != null && transport.getMin_delivery_amount().compareTo(orderPayAmount) <= 0; + } + + // 距离和金额都满足条件 + if (moneyPassed) { + canDelivery = true; + break; + } + } + } + + // 如果没有找到完全满足条件的规则,再详细检查找出失败原因 + if (!canDelivery) { + for (ShopStoreSameCityTransport transport : transportList) { + // 判断订单距离是否在配送范围内 + if (transport.getMax_delivery_radius() < distance) { + // 记录距离不满足的原因 + canNotDeliveryReason = storeName + "的订单不在配送范围内,订单无法配送。"; + } else { + // 距离在配送范围内,判断金额是否符合起配金额额度 + if (CommonConstant.Delivery_Amount_Comput_Type_Original.equals(transport.getMin_delivery_amount_type())) { + if (orderProductAmount != null && transport.getMin_delivery_amount().compareTo(orderProductAmount) > 0) { + BigDecimal diffMoney = transport.getMin_delivery_amount().subtract(orderProductAmount); + canNotDeliveryReason = String.format("%s商品原价金额还差%.2f元,才满足配送条件,请检查订单。", storeName, diffMoney); + } else { + canDelivery = true; + break; + } + } else if (CommonConstant.Delivery_Amount_Comput_Type_Discounted.equals(transport.getMin_delivery_amount_type())) { + if (orderDiscountAmount != null && transport.getMin_delivery_amount().compareTo(orderDiscountAmount) > 0) { + BigDecimal diffMoney = transport.getMin_delivery_amount().subtract(orderDiscountAmount); + canNotDeliveryReason = String.format("%s订单折后金额还差%.2f元,才满足配送条件,请检查订单。", storeName, diffMoney); + } else { + canDelivery = true; + break; + } + } else if (CommonConstant.Delivery_Amount_Comput_Type_Payment.equals(transport.getMin_delivery_amount_type())) { + if (orderPayAmount != null && transport.getMin_delivery_amount().compareTo(orderPayAmount) > 0) { + BigDecimal diffMoney = transport.getMin_delivery_amount().subtract(orderPayAmount); + canNotDeliveryReason = String.format("%s订单应支付金额还差%.2f元,才满足配送条件,请检查订单。", storeName, diffMoney); + } else { + canDelivery = true; + break; + } + } + } + } + } + + // 如果仍然不能配送,记录日志并返回0 + if (!canDelivery) { + logger.warn(canNotDeliveryReason.isEmpty() ? (storeName + "订单不在配送范围内或未达起送金额,请检查!") : canNotDeliveryReason); + return 0; + } + + // 额外配送费计算 + // 每增加一个距离累加运费 + if (transportBase.getDistance_increase_km() != null && transportBase.getDistance_increase_fee() != null && distance > transportBase.getDistance_base() * 1000) { + // 实际配送距离超出基础距离,单位km + BigDecimal diffDistanceM = CommonUtil.DecimalRoundHalfUp(BigDecimal.valueOf(distance - transportBase.getDistance_base() * 1000).divide(BigDecimal.valueOf(1000))); + // 倍数 + BigDecimal times = BigDecimal.ZERO; + if (transportBase.getDistance_increase_km() > 0 && diffDistanceM.intValue() > transportBase.getDistance_increase_km()) { + // 末尾非零进位,比如:2.1将是3, 2.0将是2,2.001将是3 + times = NumberUtil.div(diffDistanceM, transportBase.getDistance_increase_km()).setScale(0, RoundingMode.UP); + } + + // 超过基础运费距离后,累加上运费 + deliveryBaseFee = deliveryBaseFee.add(transportBase.getDistance_increase_fee().multiply(times)); + } + + // 每增加一个重量累加运费(重量暂时忽略,配置的时候设置0) + if (transportBase.getWeight_increase_kg() != null && transportBase.getWeight_increase_fee() != null && orderWeightGram != null && orderWeightGram > transportBase.getWeight_base() * 1000) { + // 实际配送重量超出基础重量,单位kg + BigDecimal diffWeightKg = CommonUtil.DecimalRoundHalfUp(BigDecimal.valueOf(orderWeightGram - transportBase.getWeight_base() * 1000).divide(BigDecimal.valueOf(1000))); + // 倍数 + BigDecimal times = BigDecimal.ZERO; + if (transportBase.getWeight_increase_kg() > 0 && diffWeightKg.intValue() > transportBase.getWeight_increase_kg()) { + // 末尾非零进位,比如:2.1将是3, 2.0将是2,2.001将是3 + times = NumberUtil.div(diffWeightKg, transportBase.getWeight_increase_kg()).setScale(0, RoundingMode.UP); // 修正:应该除以weight_increase_kg而不是distance_increase_km + } + + deliveryBaseFee = deliveryBaseFee.add(transportBase.getWeight_increase_fee().multiply(times)); + } + + // 返回单位为分的配送费 + return deliveryBaseFee.multiply(BigDecimal.valueOf(100)).intValue(); + } + + } diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/user/service/impl/ShopUserCartServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/user/service/impl/ShopUserCartServiceImpl.java index 2487ec1c..4dc94d45 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/user/service/impl/ShopUserCartServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/user/service/impl/ShopUserCartServiceImpl.java @@ -2644,7 +2644,7 @@ public class ShopUserCartServiceImpl extends BaseServiceImpl Date: Thu, 11 Dec 2025 17:49:16 +0800 Subject: [PATCH 08/28] =?UTF-8?q?=E5=B9=B3=E5=8F=B0=E5=86=85=E9=83=A8?= =?UTF-8?q?=E9=85=8D=E9=80=81=E8=B4=B9=E7=9A=84=E9=80=BB=E8=BE=91=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E3=80=82=E6=97=A5=E5=BF=97=E6=89=93=E5=8D=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../impl/AccountBaseConfigServiceImpl.java | 8 +-- .../impl/ShopOrderBaseServiceImpl.java | 11 ++-- .../impl/ShopOrderReturnServiceImpl.java | 50 ++++++++++++++----- 3 files changed, 49 insertions(+), 20 deletions(-) diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/base/service/impl/AccountBaseConfigServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/base/service/impl/AccountBaseConfigServiceImpl.java index 0995fce2..22cacbdb 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/base/service/impl/AccountBaseConfigServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/base/service/impl/AccountBaseConfigServiceImpl.java @@ -417,7 +417,6 @@ public class AccountBaseConfigServiceImpl extends BaseServiceImpl Date: Fri, 12 Dec 2025 00:14:24 +0800 Subject: [PATCH 09/28] =?UTF-8?q?=E5=B9=B3=E5=8F=B0=E5=86=85=E9=83=A8?= =?UTF-8?q?=E9=85=8D=E9=80=81=E8=B4=B9=E7=9A=84=E9=80=BB=E8=BE=91=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E3=80=82=E6=8E=A5=E5=8F=A3=E5=B1=82=E9=9D=A2=E4=BF=AE?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...pStoreSameCityTransportBaseController.java | 4 +- ...SameCityTransportBaseMobileController.java | 4 +- ...ShopStoreSameCityTransportBaseService.java | 3 +- ...StoreSameCityTransportBaseServiceImpl.java | 52 +++++++++++++------ 4 files changed, 41 insertions(+), 22 deletions(-) diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/store/controller/admin/ShopStoreSameCityTransportBaseController.java b/mall-shop/src/main/java/com/suisung/mall/shop/store/controller/admin/ShopStoreSameCityTransportBaseController.java index c3d35f76..cd3b2ff7 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/store/controller/admin/ShopStoreSameCityTransportBaseController.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/store/controller/admin/ShopStoreSameCityTransportBaseController.java @@ -23,8 +23,8 @@ public class ShopStoreSameCityTransportBaseController { @ApiOperation(value = "获取同城配送运费设置详情", notes = "获取同城配送运费设置详情") @RequestMapping(value = "/detail", method = {RequestMethod.GET}) - public CommonResult shopStoreSameCityTransportBaseDetail(@RequestParam(name = "is_platfrom", defaultValue = "2") Integer isPlatform) { - return transportBaseService.ShopStoreSameCityTransportBaseDetail(isPlatform); + public CommonResult shopStoreSameCityTransportBaseDetail(@RequestParam(name = "store_id", required = false, defaultValue = "0") Long store_id) { + return transportBaseService.ShopStoreSameCityTransportBaseDetail(store_id); } @ApiOperation(value = "保存(新增或修改)同城配送运费设置", notes = "保存(新增或修改)同城配送运费设置") diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/store/controller/mobile/ShopStoreSameCityTransportBaseMobileController.java b/mall-shop/src/main/java/com/suisung/mall/shop/store/controller/mobile/ShopStoreSameCityTransportBaseMobileController.java index 040b1028..de83613e 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/store/controller/mobile/ShopStoreSameCityTransportBaseMobileController.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/store/controller/mobile/ShopStoreSameCityTransportBaseMobileController.java @@ -20,7 +20,7 @@ public class ShopStoreSameCityTransportBaseMobileController { @ApiOperation(value = "下单前检测同城订单配送是否符合要求", notes = "下单前检测同城订单配送是否符合要求") @RequestMapping(value = "/check/same-city/delivery", method = {RequestMethod.POST}) - public CommonResult checkSameCityDelivery(@RequestParam(name = "is_platfrom", defaultValue = "2") Integer isPlatform) { - return transportBaseService.ShopStoreSameCityTransportBaseDetail(isPlatform); + public CommonResult checkSameCityDelivery(@RequestParam(name = "store_id", required = false, defaultValue = "0") Long store_id) { + return transportBaseService.ShopStoreSameCityTransportBaseDetail(store_id); } } \ No newline at end of file diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/ShopStoreSameCityTransportBaseService.java b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/ShopStoreSameCityTransportBaseService.java index 037a86c1..1ceef44b 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/ShopStoreSameCityTransportBaseService.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/ShopStoreSameCityTransportBaseService.java @@ -21,9 +21,10 @@ public interface ShopStoreSameCityTransportBaseService { /** * 获取同城配送设置详情信息 * + * @param storeId * @return */ - CommonResult ShopStoreSameCityTransportBaseDetail(Integer isPlatform); + CommonResult ShopStoreSameCityTransportBaseDetail(Long storeId); /** * 保存或更新同城配送各项设置 diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreSameCityTransportBaseServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreSameCityTransportBaseServiceImpl.java index 8579f4da..688e39e5 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreSameCityTransportBaseServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreSameCityTransportBaseServiceImpl.java @@ -28,6 +28,7 @@ import com.suisung.mall.common.pojo.dto.DeliveryFeeResultDTO; import com.suisung.mall.common.pojo.dto.OrderCacDeliveryFeeDTO; import com.suisung.mall.common.pojo.dto.SameCityDeliveryFeeRespDTO; import com.suisung.mall.common.pojo.dto.ShopStoreSameCityTransportBaseDTO; +import com.suisung.mall.common.utils.CheckUtil; import com.suisung.mall.common.utils.CommonUtil; import com.suisung.mall.common.utils.I18nUtil; import com.suisung.mall.common.utils.PositionUtil; @@ -78,24 +79,30 @@ public class ShopStoreSameCityTransportBaseServiceImpl extends BaseServiceImpl 2) { - isPlatform = CommonConstant.Disable2; + Integer isPlatform = CommonConstant.Disable2; + if (user.isPlatform()) { + if (CheckUtil.isEmpty(storeId)) { + return CommonResult.failed("平台操作,请传入店铺Id"); + } + isPlatform = CommonConstant.Enable; + } else { + storeId = Convert.toLong(user.getStore_id()); } - Long storeId = Convert.toLong(user.getStore_id()); ShopStoreSameCityTransportBaseDTO retDTO = getShopStoreSameCityTransportBaseDTOById(storeId, isPlatform); if (retDTO == null) { - return CommonResult.failed("商家未设置店铺地址,请先设置店铺地址!"); + return CommonResult.failed("商家未设置店铺地址及经纬度相关信息,请先设置再试!"); } return CommonResult.success(retDTO); @@ -109,21 +116,30 @@ public class ShopStoreSameCityTransportBaseServiceImpl extends BaseServiceImpl pair = saveOrUpdateShopStoreSameCityTransportBase(transportBase); @@ -257,6 +274,7 @@ public class ShopStoreSameCityTransportBaseServiceImpl extends BaseServiceImpl Date: Fri, 12 Dec 2025 09:23:13 +0800 Subject: [PATCH 10/28] =?UTF-8?q?=E5=B9=B3=E5=8F=B0=E5=86=85=E9=83=A8?= =?UTF-8?q?=E9=85=8D=E9=80=81=E8=B4=B9=E7=9A=84=E9=80=BB=E8=BE=91=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E3=80=82=E5=A2=9E=E5=8A=A0=E6=97=A5=E5=BF=97=E6=89=93?= =?UTF-8?q?=E5=8D=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...StoreSameCityTransportBaseServiceImpl.java | 98 +++++++++++++------ 1 file changed, 70 insertions(+), 28 deletions(-) diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreSameCityTransportBaseServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreSameCityTransportBaseServiceImpl.java index 688e39e5..d91d4b18 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreSameCityTransportBaseServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreSameCityTransportBaseServiceImpl.java @@ -79,94 +79,123 @@ public class ShopStoreSameCityTransportBaseServiceImpl extends BaseServiceImpl pair = saveOrUpdateShopStoreSameCityTransportBase(transportBase); - - // 新增或更新同城配送扩展设置列表 - shopStoreSameCityTransportBaseDTO.setTransportBase(transportBase); - shopStoreSameCityTransportBaseDTO.rebuildTransportList(); - shopStoreSameCityTransportService.saveOrUpdateShopStoreSameCityTransportList(shopStoreSameCityTransportBaseDTO.getTransportList()); - - if (pair.getFirst() > 0) { - return CommonResult.success(null, pair.getSecond()); + // 保存或更新同城配送基础设置 + Pair saveResult = saveOrUpdateShopStoreSameCityTransportBase(transportBase); + if (saveResult.getFirst() <= 0) { + logger.error("保存或更新同城配送基础设置失败, storeId={}, errorMsg={}", storeId, saveResult.getSecond()); + return CommonResult.failed(saveResult.getSecond()); } - return CommonResult.failed(pair.getSecond()); + // 更新DTO中的基础设置和运输列表 + shopStoreSameCityTransportBaseDTO.setTransportBase(transportBase); + shopStoreSameCityTransportBaseDTO.rebuildTransportList(); + + // 保存或更新同城配送扩展设置列表 + int updateCount = shopStoreSameCityTransportService.saveOrUpdateShopStoreSameCityTransportList(shopStoreSameCityTransportBaseDTO.getTransportList()); + logger.debug("保存或更新同城配送扩展设置列表完成, storeId={}, 更新条数={}", storeId, updateCount); + + logger.info("成功保存或更新店铺 {} 的同城配送设置", storeId); + return CommonResult.success(shopStoreSameCityTransportBaseDTO, saveResult.getSecond()); } + /** * 店铺主营商品类型 * @@ -331,6 +360,13 @@ public class ShopStoreSameCityTransportBaseServiceImpl extends BaseServiceImpl + */ public Pair saveOrUpdateShopStoreSameCityTransportBase(ShopStoreSameCityTransportBase transportBase) { try { // 参数校验 @@ -339,13 +375,14 @@ public class ShopStoreSameCityTransportBaseServiceImpl extends BaseServiceImpl 2) { - isPlatform = 2; + isPlatform = CommonConstant.Disable2; // 默认为商户级别 transportBase.setIs_platform(isPlatform); } - // 设置默认值 - 使用更清晰的条件判断 + // 设置默认值 - 确保数值合理性 if (transportBase.getDistance_base() == null || transportBase.getDistance_base() < 0) { transportBase.setDistance_base(0); } @@ -368,25 +405,29 @@ public class ShopStoreSameCityTransportBaseServiceImpl extends BaseServiceImpl queryWrapper = new QueryWrapper<>(); queryWrapper.eq("store_id", transportBase.getStore_id()); queryWrapper.eq("is_platform", transportBase.getIs_platform()); queryWrapper.eq("status", CommonConstant.Enable); + + // 先尝试查找已存在的记录 ShopStoreSameCityTransportBase exist = getOne(queryWrapper); Date now = new Date(); if (exist == null) { // 新增操作 - log.debug("开始新增同城配送基础信息, storeId={}", transportBase.getStore_id()); + log.debug("开始新增同城配送基础信息, storeId={}, isPlatform={}", transportBase.getStore_id(), transportBase.getIs_platform()); transportBase.setCreated_by(transportBase.getUpdated_by()); transportBase.setCreated_at(now); transportBase.setUpdated_at(now); + transportBase.setStatus(CommonConstant.Enable); // 确保状态为启用 if (add(transportBase)) { // 确保获取到ID Long transportBaseId = transportBase.getTransport_base_id(); if (transportBaseId == null || transportBaseId <= 0) { - // 补偿机制:若transportBase.getTransport_base_id()==null,重新查询数据 + // 补偿机制:若新增后ID仍为空,重新查询获取ID log.debug("新增后ID为空,重新查询获取ID, storeId={}", transportBase.getStore_id()); exist = getOne(queryWrapper); if (exist != null) { @@ -400,10 +441,11 @@ public class ShopStoreSameCityTransportBaseServiceImpl extends BaseServiceImpl Date: Fri, 12 Dec 2025 11:07:46 +0800 Subject: [PATCH 11/28] =?UTF-8?q?=E7=A0=8D=E4=BB=B7=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E6=91=87=E8=89=B2=E5=AD=90=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../activity/ShopActivityCutprice.java | 3 + .../activity/ShopActivityCutpriceHistory.java | 13 +- .../mall/common/modules/page/ShopPageApp.java | 6 +- .../store/ShopActivityCutLotteryHistory.java | 53 ++ .../modules/store/ShopStoreActivityBase.java | 4 + .../mall/common/utils/RollDiceUtils.java | 290 ++++++++ .../mobile/UserActivityController.java | 15 +- .../ShopActivityCutLotteryHistoryMapper.java | 10 + .../ShopActivityCutLotteryHistoryService.java | 11 + .../service/ShopActivityCutpriceService.java | 9 + .../ShopActivityCutLotteryHistoryImpl.java | 15 + .../impl/ShopActivityCutpriceServiceImpl.java | 663 +++++++++++++----- .../ShopStoreActivityBaseServiceImpl.java | 107 +++ .../shop/sync/Utils/BigDecimalFormatter.java | 23 + sql/shop/dev/20251209_ddl.sql | 19 + sql/shop/dev/20251212_dml.sql | 1 + 16 files changed, 1074 insertions(+), 168 deletions(-) create mode 100644 mall-common/src/main/java/com/suisung/mall/common/modules/store/ShopActivityCutLotteryHistory.java create mode 100644 mall-common/src/main/java/com/suisung/mall/common/utils/RollDiceUtils.java create mode 100644 mall-shop/src/main/java/com/suisung/mall/shop/activity/mapper/ShopActivityCutLotteryHistoryMapper.java create mode 100644 mall-shop/src/main/java/com/suisung/mall/shop/activity/service/ShopActivityCutLotteryHistoryService.java create mode 100644 mall-shop/src/main/java/com/suisung/mall/shop/activity/service/impl/ShopActivityCutLotteryHistoryImpl.java create mode 100644 sql/shop/dev/20251209_ddl.sql create mode 100644 sql/shop/dev/20251212_dml.sql diff --git a/mall-common/src/main/java/com/suisung/mall/common/modules/activity/ShopActivityCutprice.java b/mall-common/src/main/java/com/suisung/mall/common/modules/activity/ShopActivityCutprice.java index 4c349501..67b216d6 100644 --- a/mall-common/src/main/java/com/suisung/mall/common/modules/activity/ShopActivityCutprice.java +++ b/mall-common/src/main/java/com/suisung/mall/common/modules/activity/ShopActivityCutprice.java @@ -69,4 +69,7 @@ public class ShopActivityCutprice implements Serializable { @ApiModelProperty(value = "更新时间") private Date updated_at; + @ApiModelProperty(value = "大转盘次数") + private Integer lottery_num; + } diff --git a/mall-common/src/main/java/com/suisung/mall/common/modules/activity/ShopActivityCutpriceHistory.java b/mall-common/src/main/java/com/suisung/mall/common/modules/activity/ShopActivityCutpriceHistory.java index 0da05526..eb43ad9d 100644 --- a/mall-common/src/main/java/com/suisung/mall/common/modules/activity/ShopActivityCutpriceHistory.java +++ b/mall-common/src/main/java/com/suisung/mall/common/modules/activity/ShopActivityCutpriceHistory.java @@ -1,8 +1,6 @@ package com.suisung.mall.common.modules.activity; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.*; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -52,5 +50,14 @@ public class ShopActivityCutpriceHistory implements Serializable { @ApiModelProperty(value = "砍价编号") private Integer ac_id; + @ApiModelProperty(value = "摇骰子次数") + private Integer lottery_num; + @ApiModelProperty(value = "骰子点数") + @TableField(updateStrategy = FieldStrategy.NOT_EMPTY) + private Integer alh_point; + + @ApiModelProperty(value = "转盘前砍掉的价格") + @TableField(updateStrategy = FieldStrategy.NOT_EMPTY) + private BigDecimal ach_price_pre; } diff --git a/mall-common/src/main/java/com/suisung/mall/common/modules/page/ShopPageApp.java b/mall-common/src/main/java/com/suisung/mall/common/modules/page/ShopPageApp.java index ae5aace8..ae742fe5 100644 --- a/mall-common/src/main/java/com/suisung/mall/common/modules/page/ShopPageApp.java +++ b/mall-common/src/main/java/com/suisung/mall/common/modules/page/ShopPageApp.java @@ -1,9 +1,6 @@ package com.suisung.mall.common.modules.page; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.*; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -84,5 +81,6 @@ public class ShopPageApp implements Serializable { private String app_market_images; @ApiModelProperty(value = "行业类别:1超市,2数码家电, 3水果生鲜, 4烘培饮品, 5社区团购, 6时尚美妆, 7婴儿服饰, 8家居, 9汽车, 10酒店旅游, 11鲜花绿植, 12医药健康, 13工业五金, 14节日模板,0其他行业") + @TableField(updateStrategy = FieldStrategy.NOT_EMPTY) private String app_industry; } diff --git a/mall-common/src/main/java/com/suisung/mall/common/modules/store/ShopActivityCutLotteryHistory.java b/mall-common/src/main/java/com/suisung/mall/common/modules/store/ShopActivityCutLotteryHistory.java new file mode 100644 index 00000000..24e04437 --- /dev/null +++ b/mall-common/src/main/java/com/suisung/mall/common/modules/store/ShopActivityCutLotteryHistory.java @@ -0,0 +1,53 @@ +package com.suisung.mall.common.modules.store; +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +/** + * 砍价抽奖历史记录DTO + */ +@Data +@TableName("shop_activity_cut_lottery_history") +@ApiModel(value = "ShopActivityCutLotteryHistory", description = "砍价大转盘抽奖历史记录") +public class ShopActivityCutLotteryHistory implements Serializable{ + private static final long serialVersionUID = 1L; + + @TableId(value = "alh_id", type = IdType.AUTO) + @ApiModelProperty(value = "用户中奖编号", example = "1") + private Long alhId; + + @TableField(value ="user_id",updateStrategy = FieldStrategy.NOT_EMPTY) + @ApiModelProperty(value = "用户编号", example = "10001") + private Integer userId; + + @TableField(value ="activity_id",updateStrategy = FieldStrategy.NOT_EMPTY) + @ApiModelProperty(value = "活动编号", example = "20001") + private Integer activityId; + + @TableField(value ="alh_item_id",updateStrategy = FieldStrategy.NOT_EMPTY) + @ApiModelProperty(value = "抽奖物品编号", example = "30001") + private Integer alhItemId; + + @TableField(value ="alh_item_name",updateStrategy = FieldStrategy.NOT_EMPTY) + @ApiModelProperty(value = "抽奖物品名称", example = "iPhone 15 Pro") + private String alhItemName; + + @TableField(value = "alh_award_flag",updateStrategy = FieldStrategy.NOT_EMPTY) + @ApiModelProperty(value = "是否中奖:0-未中奖;1-中奖", example = "1") + private Boolean alhAwardFlag; + + @TableField(value ="create_time") + @ApiModelProperty(value = "创建时间", example = "2023-12-01 10:00:00") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date createTime; + + @TableField("update_time") + @ApiModelProperty(value = "更新时间", example = "2023-12-01 10:00:00") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date updateTime; +} diff --git a/mall-common/src/main/java/com/suisung/mall/common/modules/store/ShopStoreActivityBase.java b/mall-common/src/main/java/com/suisung/mall/common/modules/store/ShopStoreActivityBase.java index 47838d78..f375cd9e 100644 --- a/mall-common/src/main/java/com/suisung/mall/common/modules/store/ShopStoreActivityBase.java +++ b/mall-common/src/main/java/com/suisung/mall/common/modules/store/ShopStoreActivityBase.java @@ -135,4 +135,8 @@ public class ShopStoreActivityBase implements Serializable { @ApiModelProperty(value = "参与活动商品的总数量(个)") private Integer product_count; + @ApiModelProperty(value = "规则配置") + @TableField(updateStrategy = NOT_EMPTY) + private String lucky_turn; + } diff --git a/mall-common/src/main/java/com/suisung/mall/common/utils/RollDiceUtils.java b/mall-common/src/main/java/com/suisung/mall/common/utils/RollDiceUtils.java new file mode 100644 index 00000000..06691aff --- /dev/null +++ b/mall-common/src/main/java/com/suisung/mall/common/utils/RollDiceUtils.java @@ -0,0 +1,290 @@ +package com.suisung.mall.common.utils; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.NumberUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.RandomUtil; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +@lombok.extern.slf4j.Slf4j +public class RollDiceUtils { + // 骰子游戏类 + public static class DiceGame { + private List> diceConfigs; + private Random random; + private Double totalProbability; + private double[] probabilityRanges; + + public DiceGame(List> configs) { + this.diceConfigs = configs; + this.random = new Random(); + validateConfigs(); + initializeProbabilityRanges(); + } + + // 验证配置数据 + private void validateConfigs() { + if (diceConfigs == null || diceConfigs.isEmpty()) { + throw new IllegalArgumentException("骰子配置不能为空"); + } + + for (Map config : diceConfigs) { + if (!config.containsKey("doubleValue") || !config.containsKey("probability")) { + throw new IllegalArgumentException("骰子配置缺少必要字段"); + } + + Object value = config.get("doubleValue"); + Object prob = config.get("probability"); + + if (!(value instanceof Integer) || !(prob instanceof Double)) { + throw new IllegalArgumentException("骰子配置字段类型错误"); + } + } + } + + // 初始化概率范围 + private void initializeProbabilityRanges() { + totalProbability = 0.00; + probabilityRanges = new double[diceConfigs.size()]; + + for (int i = 0; i < diceConfigs.size(); i++) { + Map config = diceConfigs.get(i); + double probability = (Double) config.get("probability"); + totalProbability += probability; + probabilityRanges[i] = totalProbability; + } + + // 验证概率总和是否为100 + if (totalProbability != 100) { + log.warn("警告:概率总和为 {}%,不是100%", totalProbability); + } + } + + /** + * 摇骰子(根据概率获取点数) + * @param cutPrice 砍掉的价格 + * @param targetPrice 剩余价格 + * @param targetPrice 目标价 + * @return + */ + public int rollDice(BigDecimal cutPrice,BigDecimal lessPrice,BigDecimal targetPrice,Integer maxNum) { + if (diceConfigs.isEmpty()) { + throw new IllegalStateException("骰子配置为空"); + } + //不能超过最大的点数,如果超过就不能中奖 + BigDecimal suPrice=lessPrice.subtract(targetPrice).setScale(2, RoundingMode.HALF_UP); + BigDecimal maxCutPrice= cutPrice.multiply(new BigDecimal(maxNum)).setScale(2, RoundingMode.HALF_UP); + if(maxCutPrice.compareTo(suPrice)>-1){ + return 1; + } + int randomValue = random.nextInt(100); // 生成0-99的随机数 + // 根据概率范围确定点数 + for (int i = 0; i < probabilityRanges.length; i++) { + double prevRange = (i == 0) ? 0 : probabilityRanges[i - 1]; + if (randomValue >= prevRange && randomValue < probabilityRanges[i]) { + Map config = diceConfigs.get(i); + return (Integer) config.get("doubleValue"); + } + } + + // 如果概率总和不是100,返回第一个非零概率的点数 + Map config = getFirstNonZeroProbabilityConfig(); + return (Integer) config.get("doubleValue"); + } + + // 获取第一个非零概率的配置 + private Map getFirstNonZeroProbabilityConfig() { + for (Map config : diceConfigs) { + double probability = (double) config.get("probability"); + if (probability > 0) { + return config; + } + } + return diceConfigs.get(0); // 如果所有概率都是0,返回第一个配置 + } + public static List randMoney(BigDecimal money, Integer num) { + // 只有一个人直接返回 + if (num == 1) { + return Collections.singletonList(NumberUtil.mul(money, 100).intValue()); + } + + money = NumberUtil.mul(money, 100); // 将元转成分(小数计算有误差,随机数也都是整数) + BigDecimal rest_money = money; // 初始化,剩余钱的变量 + Integer average = NumberUtil.div(rest_money, num, 0).intValue(); // 求出均分情况下,每人的红包值 + List arr = new ArrayList<>(); + + if (ObjectUtil.compare(average, 1) < 0) { + // 钱不够所有人分 + return Stream.generate(() -> 0).limit(num).collect(Collectors.toList()); + } else if (ObjectUtil.compare(average, 1) == 0) { + // 所有人*均分这笔钱(钱数只够这么分的) + for (Integer i = 0; i < num; i++) { + arr.add(average); + } + } else { + // 每个人随机分配 + for (int i = 0; i < num; i++) { + BigDecimal range_money = NumberUtil.div(rest_money, (num - i), 0); + Integer rand_money = RandomUtil.randomInt(1, range_money.intValue()); + arr.add(rand_money); + rest_money = NumberUtil.sub(rest_money, rand_money); // 获取剩下的钱 + } + } + + int arr_sum = 0; // 保存数组和 + if (CollUtil.isNotEmpty(arr)) { + // 随机分配,会调用此方法将剩余的钱分掉,此数组为随机分配后的结果 + arr_sum = arr.stream().mapToInt(Integer::intValue).sum(); // 统计随机分配已经分配了总钱数 + } else { + // 初始化每个人的数组,兼容下边循环处理部分 + arr = Stream.generate(() -> 0).limit(num).collect(Collectors.toList()); + } + + BigDecimal add_money = NumberUtil.sub(money, arr_sum); + // 如果总钱数和之前随机分配的数组的总和差值为0,就说明随机分配已经将钱全部分出去了,就不需要再*均分配处理了 + if (ObjectUtil.compare(add_money, BigDecimal.ZERO) == 0) { + return arr; + } + + // 先把剩余的能均分的部分均分一下,然后若再有剩余,则从前到后,注意分配 + // 如果之前有随机分配,则是将剩余的钱*均追加入随机分配的值里 + Integer avg_add_money = NumberUtil.div(add_money, num, 0).intValue(); + arr = arr.stream().map(s -> s + avg_add_money).collect(Collectors.toList()); + // 分配后,求和,用于修正最后剩余的零钱 + arr_sum = arr.stream().mapToInt(Integer::intValue).sum(); + // 如果还有剩余,这部分说明每人一分都不够,就从头开始没人一分的分下去,直到分完为止 + BigDecimal odd_money = NumberUtil.sub(money, arr_sum, 0); + int i = 0; + while (ObjectUtil.compare(odd_money, BigDecimal.ONE) >= 0) { + arr.set(i, arr.get(i) + 1); // 每人加1分钱 + odd_money = NumberUtil.sub(odd_money, 1); // 剩余的金额,每分掉一个人,就减1分钱 + if (i == num) { + i = 0; + } else { + i++; + } + } + + return arr; + } + + // 批量测试摇骰子结果分布 + public Map testDistribution(int rollCount) { + Map distribution = new HashMap<>(); + + // 初始化分布图 + for (Map config : diceConfigs) { + int point = (Integer) config.get("doubleValue"); + distribution.put(point, 0); + } + BigDecimal salePrice = new BigDecimal("47"); + int accNum=100; + // 摇骰子多次并统计 + for (int i = 0; i < rollCount; i++) { + List arr= randMoney(salePrice, accNum); + Integer randPrice = arr.size() == 1 ? arr.get(0) : arr.get(RandomUtil.randomInt(0, arr.size())); + BigDecimal cutPrice = NumberUtil.div(BigDecimal.valueOf(randPrice), 100, 2); + int result = rollDice(cutPrice,salePrice,new BigDecimal("0.01"),6); + BigDecimal sumPrice = cutPrice.multiply(new BigDecimal(result)).setScale(2, RoundingMode.HALF_UP); + System.out.println("第"+(i+1)+"次;砍价:"+cutPrice+";点数:"+result+",最终砍价数据:"+sumPrice); + salePrice=salePrice.subtract(sumPrice).setScale(2, RoundingMode.HALF_UP); + distribution.put(result, distribution.get(result) + 1); + accNum--; + } + + return distribution; + } + + // 显示概率配置 + public void displayConfig() { + System.out.println("当前骰子概率配置:"); + System.out.println("点数\t概率"); + System.out.println("----------------"); + + for (Map config : diceConfigs) { + int point = (Integer) config.get("doubleValue"); + double probability = (double) config.get("probability"); + System.out.printf("%d\t%f%%\n", point, probability); + } + + System.out.println("----------------"); + System.out.printf("概率总和:%f%%\n\n", totalProbability); + } + + // 获取预期概率 + public Map getExpectedProbabilities() { + Map expected = new HashMap<>(); + + for (Map config : diceConfigs) { + int point = (Integer) config.get("doubleValue"); + double probability = (double) config.get("probability"); + expected.put(point, probability / 100.0); + } + + return expected; + } + } + + // 主程序 + public static void main(String[] args) { + BigDecimal achPrice=new BigDecimal(5.99); + achPrice= achPrice.multiply(new BigDecimal(1)).divide(new BigDecimal(10),3, RoundingMode.HALF_UP).setScale(3, RoundingMode.HALF_UP); + System.out.println(achPrice); + // 创建骰子配置(使用 Map) + List> configs = new ArrayList<>(); + + // 添加配置项 + configs.add(createDiceConfig(1, 45)); + configs.add(createDiceConfig(2, 45)); + configs.add(createDiceConfig(3, 3)); + configs.add(createDiceConfig(4, 2)); + configs.add(createDiceConfig(5, 3)); + configs.add(createDiceConfig(6, 2)); + + // 创建骰子游戏实例 + DiceGame diceGame = new DiceGame(configs); + + // 显示配置 + diceGame.displayConfig(); + + // 模拟摇骰子 + System.out.println("=== 模拟摇骰子10次 ==="); + for (int i = 1; i <= 100; i++) { + int result = diceGame.rollDice(new BigDecimal(0.5),new BigDecimal(50),new BigDecimal(0.01),6); + System.out.println("第" + i + "次摇骰子: " + result); + } + + // 测试概率分布 + System.out.println("\n=== 概率分布测试(100次) ==="); + int testCount = 100; + Map distribution = diceGame.testDistribution(testCount); + + System.out.println("点数\t出现次数\t实际概率\t预期概率"); + System.out.println("----------------------------------------"); + + Map expectedProbabilities = diceGame.getExpectedProbabilities(); + + for (Map.Entry entry : distribution.entrySet()) { + int point = entry.getKey(); + int count = entry.getValue(); + double actualProbability = (double) count / testCount * 100; + double expectedProbability = expectedProbabilities.getOrDefault(point, 0.0) * 100; + + System.out.printf("%d\t%d\t\t%.2f%%\t\t%.2f%%\n", + point, count, actualProbability, expectedProbability); + } + } + + // 辅助方法:创建骰子配置 Map + public static Map createDiceConfig(int value, double probability) { + Map config = new HashMap<>(); + config.put("doubleValue", value); + config.put("probability", probability); + return config; + } +} diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/activity/controller/mobile/UserActivityController.java b/mall-shop/src/main/java/com/suisung/mall/shop/activity/controller/mobile/UserActivityController.java index b58226a1..10b0cc4b 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/activity/controller/mobile/UserActivityController.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/activity/controller/mobile/UserActivityController.java @@ -11,6 +11,7 @@ import com.suisung.mall.common.modules.activity.ShopActivityGroupbookingHistory; import com.suisung.mall.common.modules.activity.ShopActivityGroupbuyStoreHistory; import com.suisung.mall.common.service.impl.BaseControllerImpl; import com.suisung.mall.common.utils.CheckUtil; +import com.suisung.mall.common.utils.ContextUtil; import com.suisung.mall.common.utils.I18nUtil; import com.suisung.mall.shop.activity.service.ShopActivityCutpriceHistoryService; import com.suisung.mall.shop.activity.service.ShopActivityCutpriceService; @@ -121,7 +122,7 @@ public class UserActivityController extends BaseControllerImpl { @ApiOperation(value = "立即砍价", notes = "自己砍价、邀请朋友过来也能砍价") @RequestMapping(value = "/doCutPrice", method = {RequestMethod.GET, RequestMethod.POST}) public CommonResult doCutPrice(@RequestParam(name = "ac_id", defaultValue = "0") Integer ac_id) { - UserDto user = getCurrentUser(); + UserDto user = ContextUtil.getCurrentUser(); if (user == null || CheckUtil.isEmpty(user.getId())) { throw new ApiException(ResultCode.NEED_LOGIN); } @@ -251,5 +252,17 @@ public class UserActivityController extends BaseControllerImpl { public CommonResult getGiftbag(@RequestParam(name = "activity_id") Integer activity_id) { return CommonResult.success(shopStoreActivityBaseService.getGiftbag(activity_id)); } + + @ApiOperation(value = "砍价大转盘", notes = "自己砍价、邀请朋友过来也能转") + @RequestMapping(value = "/dolookTurnCutPrice", method = {RequestMethod.GET, RequestMethod.POST}) + public CommonResult dolookTurnCutPrice(@RequestParam(name = "ac_id", defaultValue = "0") Integer ac_id) { + UserDto user = ContextUtil.getCurrentUser(); + if (user == null || CheckUtil.isEmpty(user.getId())) { + throw new ApiException(ResultCode.NEED_LOGIN); + } + Integer user_id = user.getId(); + return shopActivityCutpriceService.dolookTurnCutPrice(ac_id, user_id); + } + } diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/activity/mapper/ShopActivityCutLotteryHistoryMapper.java b/mall-shop/src/main/java/com/suisung/mall/shop/activity/mapper/ShopActivityCutLotteryHistoryMapper.java new file mode 100644 index 00000000..6855216a --- /dev/null +++ b/mall-shop/src/main/java/com/suisung/mall/shop/activity/mapper/ShopActivityCutLotteryHistoryMapper.java @@ -0,0 +1,10 @@ + +package com.suisung.mall.shop.activity.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.suisung.mall.common.modules.store.ShopActivityCutLotteryHistory; +import org.springframework.stereotype.Repository; + +@Repository +public interface ShopActivityCutLotteryHistoryMapper extends BaseMapper { +} diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/activity/service/ShopActivityCutLotteryHistoryService.java b/mall-shop/src/main/java/com/suisung/mall/shop/activity/service/ShopActivityCutLotteryHistoryService.java new file mode 100644 index 00000000..d74a1f0b --- /dev/null +++ b/mall-shop/src/main/java/com/suisung/mall/shop/activity/service/ShopActivityCutLotteryHistoryService.java @@ -0,0 +1,11 @@ +package com.suisung.mall.shop.activity.service; + + +import com.suisung.mall.common.modules.store.ShopActivityCutLotteryHistory; +import com.suisung.mall.core.web.service.IBaseService; + +public interface ShopActivityCutLotteryHistoryService extends IBaseService { + + + +} diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/activity/service/ShopActivityCutpriceService.java b/mall-shop/src/main/java/com/suisung/mall/shop/activity/service/ShopActivityCutpriceService.java index 8c958650..6c8d1986 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/activity/service/ShopActivityCutpriceService.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/activity/service/ShopActivityCutpriceService.java @@ -65,4 +65,13 @@ public interface ShopActivityCutpriceService extends IBaseService implements ShopActivityCutLotteryHistoryService { + + +} diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/activity/service/impl/ShopActivityCutpriceServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/activity/service/impl/ShopActivityCutpriceServiceImpl.java index bca71d1e..e9b834e9 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/activity/service/impl/ShopActivityCutpriceServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/activity/service/impl/ShopActivityCutpriceServiceImpl.java @@ -7,6 +7,7 @@ import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.NumberUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONArray; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; @@ -19,25 +20,25 @@ import com.suisung.mall.common.domain.UserDto; import com.suisung.mall.common.exception.ApiException; import com.suisung.mall.common.exception.ApiUserException; import com.suisung.mall.common.feignService.AccountService; +import com.suisung.mall.common.modules.account.AccountUserBase; import com.suisung.mall.common.modules.activity.ShopActivityCutprice; import com.suisung.mall.common.modules.activity.ShopActivityCutpriceHistory; import com.suisung.mall.common.modules.activity.ShopActivityGroupbooking; import com.suisung.mall.common.modules.activity.ShopActivityGroupbookingHistory; +import com.suisung.mall.common.modules.store.ShopActivityCutLotteryHistory; import com.suisung.mall.common.modules.store.ShopStoreActivityBase; -import com.suisung.mall.common.utils.CheckUtil; -import com.suisung.mall.common.utils.DateTimeUtils; -import com.suisung.mall.common.utils.I18nUtil; +import com.suisung.mall.common.utils.*; import com.suisung.mall.core.web.service.RedisService; import com.suisung.mall.core.web.service.impl.BaseServiceImpl; import com.suisung.mall.shop.activity.mapper.ShopActivityCutpriceMapper; -import com.suisung.mall.shop.activity.service.ShopActivityCutpriceHistoryService; -import com.suisung.mall.shop.activity.service.ShopActivityCutpriceService; -import com.suisung.mall.shop.activity.service.ShopActivityGroupbookingHistoryService; -import com.suisung.mall.shop.activity.service.ShopActivityGroupbookingService; +import com.suisung.mall.shop.activity.service.*; import com.suisung.mall.shop.base.service.AccountBaseConfigService; import com.suisung.mall.shop.order.service.ShopOrderInfoService; import com.suisung.mall.shop.store.service.ShopStoreActivityBaseService; +import com.suisung.mall.shop.sync.Utils.BigDecimalFormatter; import lombok.extern.slf4j.Slf4j; +import org.redisson.api.RLock; +import org.redisson.api.RedissonClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.data.util.Pair; @@ -45,8 +46,11 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.io.Serializable; +import java.lang.reflect.Type; import java.math.BigDecimal; +import java.math.RoundingMode; import java.util.*; +import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import static com.suisung.mall.common.utils.ContextUtil.getCurrentUser; @@ -95,6 +99,11 @@ public class ShopActivityCutpriceServiceImpl extends BaseServiceImpl check_result = checkCutPriceExpiredAndStock(activityBase); - if (!check_result.getFirst()) { - // 库存不够,立即更改活动状态为已结束 - shopStoreActivityBaseService.updateActivityState(cutprice.getActivity_id(), StateCode.ACTIVITY_STATE_FINISHED); - throw new ApiException(check_result.getSecond()); + } catch (InterruptedException e) { + throw new RuntimeException(e); } - - } catch (Exception e) { - return CommonResult.failed(I18nUtil._("系统繁忙,请稍后再试!")); - } - - // 检查帮砍次数限制 - if (!cutprice.getUser_id().equals(user_id)) { - try { - if (accountBaseConfigService != null && redisService != null) { - DateTime today = DateUtil.beginOfDay(new Date()); - Integer maxCuts = accountBaseConfigService.getConfig("user_cutprice_num", 0); - Integer usedCuts = Convert.toInt(redisService.hGet("cutprice-" + today, user_id.toString()), 0); - - if (maxCuts > 0 && usedCuts >= maxCuts) { - return CommonResult.failed(I18nUtil._("今日帮砍次数已达上限!")); - } - } - } catch (Exception e) { - // Redis检查失败时继续执行砍价操作 - } - } - - BigDecimal salePrice = cutprice.getAc_sale_price(); - BigDecimal minPrice = cutprice.getAc_mix_limit_price(); - - // 检查价格数据完整性 - if (salePrice == null || minPrice == null) { - return CommonResult.failed(I18nUtil._("商品价格数据异常!")); - } - - // 检查是否已达到最低价 - if (NumberUtil.isLessOrEqual(salePrice, minPrice)) { - updateCutPriceState(cutprice.getAc_id(), null, CommonConstant.CutPrice_Order_State_CutFinished); - return CommonResult.failed(I18nUtil._("已砍到最低价啦!")); - } - - // 检查是否已经帮过好友砍价 try { - if (shopActivityCutpriceHistoryService == null) { + // 参数校验 + if (ac_id == null || ac_id <= 0 || user_id == null || user_id <= 0) { + return CommonResult.failed(I18nUtil._("活动或用户编号无效!")); + } + + // 获取砍价记录 + ShopActivityCutprice cutprice = get(ac_id); + if (cutprice == null) { + return CommonResult.failed(I18nUtil._("未找到砍价记录!")); + } + + // 检查活动状态 + if (shopStoreActivityBaseService == null) { return CommonResult.failed(I18nUtil._("系统繁忙,请稍后再试!")); } - QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.eq("user_id", user_id).eq("ac_id", ac_id); - if (shopActivityCutpriceHistoryService.count(queryWrapper) > 0) { - return CommonResult.failed(I18nUtil._("您已帮好友砍过价了!")); + ShopStoreActivityBase activityBase = shopStoreActivityBaseService.get(cutprice.getActivity_id()); + if (activityBase == null) { + updateCutPriceState(cutprice.getAc_id(), null, CommonConstant.CutPrice_Order_State_Canceled); + return CommonResult.failed(I18nUtil._("抱歉,砍价活动已失效啦!")); } - } catch (Exception e) { - return CommonResult.failed(I18nUtil._("系统繁忙,请稍后再试!")); - } - // 计算砍价金额 - BigDecimal cutPrice; - try { - cutPrice = shopStoreActivityBaseService.getCutDownPrice(activityBase, cutprice); - if (cutPrice == null || cutPrice.compareTo(BigDecimal.ZERO) <= 0) { - return CommonResult.failed(I18nUtil._("砍价失败,请重试!")); + // 检查活动状态是否正常 + if (!ObjectUtil.equal(activityBase.getActivity_state(), StateCode.ACTIVITY_STATE_NORMAL)) { + if (ObjectUtil.equal(activityBase.getActivity_state(), StateCode.ACTIVITY_STATE_FINISHED) + || ObjectUtil.equal(activityBase.getActivity_state(), StateCode.ACTIVITY_STATE_CLOSED)) { + updateCutPriceState(cutprice.getAc_id(), null, CommonConstant.CutPrice_Order_State_Canceled); + } + return CommonResult.failed(I18nUtil._("抱歉,砍价活动已结束啦!")); } - } catch (Exception e) { - return CommonResult.failed(I18nUtil._("砍价失败,请重试!")); - } - // 获取商品ID - String ruleStr = activityBase.getActivity_rule(); - if (StrUtil.isBlank(ruleStr)) { - return CommonResult.failed(I18nUtil._("活动规则数据异常!")); - } + Date now = new Date(); + Long expiredAt = cutprice.getExpired_at(); - try { + // 检查砍价记录是否过期 + if (CheckUtil.isNotEmpty(expiredAt) && expiredAt < now.getTime()) { + updateCutPriceState(cutprice.getAc_id(), null, CommonConstant.CutPrice_Order_State_Expired); + return CommonResult.failed(I18nUtil._("抱歉,砍价已过期啦!")); + } + + // 检查活动时间是否有效 + if (!shopStoreActivityBaseService.isActivityTimeValid(activityBase, now)) { + updateCutPriceState(cutprice.getAc_id(), null, CommonConstant.CutPrice_Order_State_Expired); + return CommonResult.failed(I18nUtil._("活动已结束!")); + } + + // 需要检查活动有效期和活动商品库存是否足够 + Pair check_result = checkCutPriceExpiredAndStock(activityBase); + if (!check_result.getFirst()) { + // 库存不够,立即更改活动状态为已结束 + shopStoreActivityBaseService.updateActivityState(cutprice.getActivity_id(), StateCode.ACTIVITY_STATE_FINISHED); + throw new ApiException(check_result.getSecond()); + } + // 检查帮砍次数限制 + if (!cutprice.getUser_id().equals(user_id)) { + if (accountBaseConfigService != null && redisService != null) { + DateTime today = DateUtil.beginOfDay(new Date()); + //Integer maxCuts = accountBaseConfigService.getConfig("user_cutprice_num", 0); + String activityRuleStr= activityBase.getActivity_rule(); + JSONObject jsonObject= JSONUtil.parseObj(activityRuleStr); + Integer maxCuts = jsonObject.getInt("user_cutprice_num",5); + Integer usedCuts = Convert.toInt(redisService.hGet("cutprice-" + today, user_id.toString()), 0); + if (maxCuts > 0 && usedCuts >= maxCuts) { + return CommonResult.failed(I18nUtil._("今日帮砍次数已达上限!")); + } + } + } + + BigDecimal salePrice = cutprice.getAc_sale_price(); + BigDecimal minPrice = cutprice.getAc_mix_limit_price(); + + // 检查价格数据完整性 + if (salePrice == null || minPrice == null) { + return CommonResult.failed(I18nUtil._("商品价格数据异常!")); + } + + // 检查是否已达到最低价 + if (NumberUtil.isLessOrEqual(salePrice, minPrice)) { + updateCutPriceState(cutprice.getAc_id(), null, CommonConstant.CutPrice_Order_State_CutFinished); + return CommonResult.failed(I18nUtil._("已砍到最低价啦!")); + } + + // 检查是否已经帮过好友砍价 + if (shopActivityCutpriceHistoryService == null) { + return CommonResult.failed(I18nUtil._("系统繁忙,请稍后再试!")); + } + + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("user_id", user_id).eq("ac_id", ac_id); + if (shopActivityCutpriceHistoryService.count(queryWrapper) > 0) { + return CommonResult.failed(I18nUtil._("您已帮好友砍过价了!")); + } + // 获取商品ID + String ruleStr = activityBase.getActivity_rule(); + if (StrUtil.isBlank(ruleStr)) { + return CommonResult.failed(I18nUtil._("活动规则数据异常!")); + } JSONObject activityRule = JSONUtil.parseObj(ruleStr); - Long itemId = activityRule.get("item_id", Long.class); - if (itemId == null) { - return CommonResult.failed(I18nUtil._("未找到对应商品!")); - } - // 创建砍价历史记录 - ShopActivityCutpriceHistory history = new ShopActivityCutpriceHistory(); - history.setActivity_id(cutprice.getActivity_id()); - history.setUser_id(user_id); - history.setAch_price(cutPrice); - history.setItem_id(itemId); - history.setAch_datetime(new Date()); - history.setAc_id(ac_id); - // 保存历史记录 - if (!shopActivityCutpriceHistoryService.saveOrUpdate(history)) { - throw new ApiException(I18nUtil._("保存砍价记录失败!")); - } - - // 更新砍价信息 - cutprice.setAc_sale_price(NumberUtil.sub(salePrice, cutPrice)); - cutprice.setAc_num(cutprice.getAc_num() + 1); - if (!edit(cutprice)) { - throw new ApiException(I18nUtil._("更新砍价信息失败!")); - } - - // 更新帮砍次数 - if (!cutprice.getUser_id().equals(user_id) && redisService != null) { - try { - DateTime today = DateUtil.beginOfDay(new Date()); - Integer cutNum = Convert.toInt(redisService.hGet("cutprice-" + today, user_id.toString()), 0); - redisService.hSet("cutprice-" + today, user_id.toString(), cutNum + 1, 24 * 60 * 60 * 1000); - } catch (Exception e) { - // Redis更新失败不影响主流程 + // 计算砍价金额 + BigDecimal cutPrice = null; + Integer lottery_num=0; + if(cutprice.getAc_num()>0){//如不是首刀,不是首刀 + cutPrice = shopStoreActivityBaseService.getCutDownPrice(activityBase, cutprice); + }else {//首刀砍价计算规则 + String cut_first_price=activityRule.getStr("cut_first_price");//首刀砍价 + String cut_first_percent=activityRule.getStr("cut_first_percent");//首刀砍价百分比 + if(StringUtils.isNotEmpty(cut_first_price)){ + cutPrice=new BigDecimal(cut_first_price); + } else if(StringUtils.isNotEmpty(cut_first_percent)) {//百分比计算 + cutPrice=new BigDecimal(cut_first_percent).multiply(cutprice.getAc_sale_price()).divide(new BigDecimal(100),2,RoundingMode.HALF_UP).setScale(2, RoundingMode.HALF_UP); + }else {//兼容旧数据,不存在 + cutPrice = shopStoreActivityBaseService.getCutDownPrice(activityBase, cutprice); } } - - // 如果已达到最低价,更新状态 - if (NumberUtil.isLessOrEqual(cutprice.getAc_sale_price(), minPrice)) { - updateCutPriceState(cutprice.getAc_id(), null, CommonConstant.CutPrice_Order_State_CutFinished); + String luckyTurn=activityBase.getLucky_turn(); + if (StrUtil.isNotBlank(luckyTurn)) {//设置赠送的转盘次数 + JSONObject luckyTurnJson = JSONUtil.parseObj(luckyTurn); + lottery_num=Convert.toInt(luckyTurnJson.get("lottery_num"),1); } - return CommonResult.success(history); - } catch (ApiException e) { - throw e; + if (cutPrice == null || cutPrice.compareTo(BigDecimal.ZERO) <= 0) { + return CommonResult.failed(I18nUtil._("砍价失败,请重试!")); + } + + Long itemId = activityRule.get("item_id", Long.class); + if (itemId == null) { + return CommonResult.failed(I18nUtil._("未找到对应商品!")); + } + // 创建砍价历史记录 + ShopActivityCutpriceHistory history = new ShopActivityCutpriceHistory(); + history.setActivity_id(cutprice.getActivity_id()); + history.setUser_id(user_id); + history.setAch_price(cutPrice); + history.setAch_price_pre(cutPrice); + history.setItem_id(itemId); + history.setAch_datetime(new Date()); + history.setAc_id(ac_id); + history.setLottery_num(lottery_num); + // 保存历史记录 + if (!shopActivityCutpriceHistoryService.saveOrUpdate(history)) { + throw new ApiException(I18nUtil._("保存砍价记录失败!")); + } + + // 更新砍价信息 + cutprice.setAc_sale_price(NumberUtil.sub(salePrice, cutPrice)); + cutprice.setLottery_num(lottery_num); + cutprice.setAc_num(cutprice.getAc_num() + 1); + if (!edit(cutprice)) { + throw new ApiException(I18nUtil._("更新砍价信息失败!")); + } + + // 更新帮砍次数 + if (!cutprice.getUser_id().equals(user_id) && redisService != null) { + DateTime today = DateUtil.beginOfDay(new Date()); + Integer cutNum = Convert.toInt(redisService.hGet("cutprice-" + today, user_id.toString()), 0); + redisService.hSet("cutprice-" + today, user_id.toString(), cutNum + 1, 24 * 60 * 60 * 1000); + } + + // 如果已达到最低价,更新状态 + if (NumberUtil.isLessOrEqual(cutprice.getAc_sale_price(), minPrice)) { + updateCutPriceState(cutprice.getAc_id(), null, CommonConstant.CutPrice_Order_State_CutFinished); + } + return CommonResult.success(history); } catch (Exception e) { - throw new ApiException(I18nUtil._("砍价操作失败!")); - } + throw new RuntimeException(e); + } finally { + // 5. 最终检查并释放锁,确保锁一定被释放 + if (lock != null && lock.isLocked() && lock.isHeldByCurrentThread()) { + lock.unlock(); + } + log.info("成功释放锁:{}", lockKey); + } } @@ -848,4 +886,309 @@ public class ShopActivityCutpriceServiceImpl extends BaseServiceImpl 0 && user_id != null && user_id > 0; + } + + /** + * 核心业务逻辑 + */ + public CommonResult doCutPriceBusiness(Integer ac_id, Integer user_id) { + try { + // 获取砍价记录 + ShopActivityCutprice cutprice = get(ac_id); + if (cutprice == null) { + return CommonResult.failed(I18nUtil._("未找到砍价记录!")); + } + + // 检查活动状态 + if (shopStoreActivityBaseService == null) { + return CommonResult.failed(I18nUtil._("系统繁忙,请稍后再试!")); + } + ShopStoreActivityBase activityBase = shopStoreActivityBaseService.get(cutprice.getActivity_id()); + if (activityBase == null) { + updateCutPriceState(cutprice.getAc_id(), null, CommonConstant.CutPrice_Order_State_Canceled); + return CommonResult.failed(I18nUtil._("抱歉,砍价活动已失效啦!")); + } + + // 检查活动状态是否正常 + if (!ObjectUtil.equal(activityBase.getActivity_state(), StateCode.ACTIVITY_STATE_NORMAL)) { + if (ObjectUtil.equal(activityBase.getActivity_state(), StateCode.ACTIVITY_STATE_FINISHED) + || ObjectUtil.equal(activityBase.getActivity_state(), StateCode.ACTIVITY_STATE_CLOSED)) { + updateCutPriceState(cutprice.getAc_id(), null, CommonConstant.CutPrice_Order_State_Canceled); + } + return CommonResult.failed(I18nUtil._("抱歉,砍价活动已结束啦!")); + } + + Date now = new Date(); + Long expiredAt = cutprice.getExpired_at(); + + // 检查砍价记录是否过期 + if (CheckUtil.isNotEmpty(expiredAt) && expiredAt < now.getTime()) { + updateCutPriceState(cutprice.getAc_id(), null, CommonConstant.CutPrice_Order_State_Expired); + return CommonResult.failed(I18nUtil._("抱歉,砍价已过期啦!")); + } + + // 检查活动时间是否有效 + try { + if (!shopStoreActivityBaseService.isActivityTimeValid(activityBase, now)) { + updateCutPriceState(cutprice.getAc_id(), null, CommonConstant.CutPrice_Order_State_Expired); + return CommonResult.failed(I18nUtil._("活动已结束!")); + } + + // 需要检查活动有效期和活动商品库存是否足够 + Pair check_result = checkCutPriceExpiredAndStock(activityBase); + if (!check_result.getFirst()) { + // 库存不够,立即更改活动状态为已结束 + shopStoreActivityBaseService.updateActivityState(cutprice.getActivity_id(), StateCode.ACTIVITY_STATE_FINISHED); + throw new ApiException(check_result.getSecond()); + } + + } catch (Exception e) { + return CommonResult.failed(I18nUtil._("系统繁忙,请稍后再试!")); + } + + BigDecimal salePrice = cutprice.getAc_sale_price(); + BigDecimal minPrice = cutprice.getAc_mix_limit_price(); + // 检查价格数据完整性 + if (salePrice == null || minPrice == null) { + return CommonResult.failed(I18nUtil._("商品价格数据异常!")); + } + + // 检查是否已达到最低价 + if (NumberUtil.isLessOrEqual(salePrice, minPrice)) { + updateCutPriceState(cutprice.getAc_id(), null, CommonConstant.CutPrice_Order_State_CutFinished); + return CommonResult.failed(I18nUtil._("已砍到最低价啦!")); + } + + // 检查帮砍次数限制 + ShopActivityCutpriceHistory shopActivityCutpriceHistory =null; + Integer lotteryNumHistory=0; + boolean isSelf=false; + //看看有没有转盘次数 + try { + if (shopActivityCutpriceHistoryService == null) { + return CommonResult.failed(I18nUtil._("系统繁忙,请稍后再试!")); + } + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("user_id", user_id).eq("ac_id", ac_id); + List shopActivityCutpriceHistoryList= shopActivityCutpriceHistoryService.list(queryWrapper); + if (shopActivityCutpriceHistoryList.isEmpty()) { + return CommonResult.failed(I18nUtil._("未找到砍价记录!")); + } + shopActivityCutpriceHistory = shopActivityCutpriceHistoryList.get(0); + lotteryNumHistory= shopActivityCutpriceHistory.getLottery_num(); + if(lotteryNumHistory==0){ + return CommonResult.failed(I18nUtil._("没有摇色子记录了!")); + } + } catch (Exception e) { + throw new Exception("系统繁忙,请稍后再试!"); + } + if (cutprice.getUser_id().equals(user_id)) {//自己转 + isSelf=true; + } + + // 开始摇色子逻辑 + Map data = calculateDiceResult(ac_id, user_id, cutprice,isSelf,shopActivityCutpriceHistory); + Integer point= (Integer) data.get("point"); + BigDecimal achPrice= (BigDecimal) data.get("achPrice");//砍掉的总价格 + BigDecimal pointPrice= (BigDecimal) data.get("pointPrice");//自己砍价的价格 + //计算摇色子次数 + Integer lottery_numHistory= shopActivityCutpriceHistory.getLottery_num()-1; + shopActivityCutpriceHistory.setLottery_num(lottery_numHistory); + if(isSelf){ + Integer lottery_numMain=cutprice.getLottery_num()-1; + cutprice.setLottery_num(lottery_numMain); + } + BigDecimal fianalSalePrice= salePrice.subtract(pointPrice).setScale(2, RoundingMode.HALF_UP); + + //计算价格 + BigDecimal oldAchPrice=shopActivityCutpriceHistory.getAch_price(); + shopActivityCutpriceHistory.setAch_price_pre(oldAchPrice); + cutprice.setAc_sale_price(fianalSalePrice);//要减去转盘转出的价格 + shopActivityCutpriceHistory.setAch_price(achPrice);//砍掉的价格 + shopActivityCutpriceHistory.setAlh_point(point);//骰子点数 + + // 更新数据库 + updateCutPriceData(cutprice, shopActivityCutpriceHistory, (Integer) data.get("point")); + return CommonResult.success(data); + + } catch (ApiException e) { + // 业务异常,直接返回错误信息 + return CommonResult.failed(e.getMessage()); + } catch (Exception e) { + // 其他异常,记录日志 + log.error("业务处理异常, ac_id: {}, user_id: {}", ac_id, user_id, e); + throw new RuntimeException("业务处理失败", e); + } + } + + /** + //更新砍后价格 todo + //更新历史砍价 新增转盘点数 todo + //更新转盘次数 todo + //转盘历史新建 todo + */ + public void updateCutPriceData(ShopActivityCutprice cutprice,ShopActivityCutpriceHistory shopActivityCutpriceHistory,Integer point){ + if(cutprice!=null){ + Integer lotteryNum= cutprice.getLottery_num(); + if(lotteryNum<0){ + lotteryNum=0; + cutprice.setLottery_num(lotteryNum); + } + this.updateById(cutprice); + } + if(shopActivityCutpriceHistory!=null){ + Integer lotteryNum= shopActivityCutpriceHistory.getLottery_num(); + if(lotteryNum<0){ + lotteryNum=0; + shopActivityCutpriceHistory.setLottery_num(lotteryNum); + } + shopActivityCutpriceHistoryService.updateById(shopActivityCutpriceHistory); + } + if(cutprice!=null&&shopActivityCutpriceHistory!=null){ + //创建摇色子记录 + ShopActivityCutLotteryHistory shopActivityCutLotteryHistory=new ShopActivityCutLotteryHistory(); + shopActivityCutLotteryHistory.setActivityId(shopActivityCutpriceHistory.getActivity_id()); + shopActivityCutLotteryHistory.setUserId(shopActivityCutpriceHistory.getUser_id()); + shopActivityCutLotteryHistory.setAlhAwardFlag(true); + shopActivityCutLotteryHistory.setAlhItemName("摇出点数:"+point); + shopActivityCutLotteryHistory.setAlhItemId(point); + shopActivityCutLotteryHistoryService.add(shopActivityCutLotteryHistory); + } + + } + + /** + * 安全的锁释放方法 + */ + private void releaseLockSafely(RLock lock, boolean lockAcquired, String lockKey) { + if (lock != null && lockAcquired) { + try { + // 检查锁是否仍然被当前线程持有 + if (lock.isHeldByCurrentThread()) { + // 检查锁是否仍然存在 + if (lock.isLocked()) { + lock.unlock(); + log.info("成功释放锁: {}", lockKey); + } else { + log.warn("锁已自动释放或已过期: {}", lockKey); + } + } else { + log.warn("当前线程未持有锁,无需释放: {}", lockKey); + } + } catch (IllegalMonitorStateException e) { + // 锁已被释放或当前线程未持有锁 + log.warn("锁状态异常,可能已自动释放: {}, error: {}", lockKey, e.getMessage()); + } catch (Exception e) { + // 其他异常,记录但不抛出,避免影响主流程 + log.error("释放锁异常, lockKey: {}", lockKey, e); + } + } else if (lock != null) { + log.debug("锁未获取成功,无需释放: {}", lockKey); + } + } + /** + * 摇色子计算逻辑 + */ + public Map calculateDiceResult(Integer ac_id, Integer user_id, ShopActivityCutprice cutprice,boolean isSelf,ShopActivityCutpriceHistory history) { + try { + Integer lotteryNumHistory = history.getLottery_num(); + + if (lotteryNumHistory == 0) { + throw new RuntimeException("没有摇色子记录了!"); + } + + // 创建骰子游戏实例 + ShopStoreActivityBase activityBase = shopStoreActivityBaseService.get(cutprice.getActivity_id()); + String luckyTurn = activityBase.getLucky_turn(); + JSONObject jsonObject = JSONUtil.parseObj(luckyTurn); + JSONArray luckyList = jsonObject.getJSONArray("luckyList"); + + List> configs = new ArrayList<>(); + luckyList.forEach(object -> { + JSONObject luckyObject = (JSONObject) object; + configs.add(RollDiceUtils.createDiceConfig( + Convert.toInt(luckyObject.get("doubleValue")), + Convert.toDouble(luckyObject.get("probability")) + )); + }); + + RollDiceUtils.DiceGame diceGame = new RollDiceUtils.DiceGame(configs); + int point = diceGame.rollDice(history.getAch_price_pre(),cutprice.getAc_sale_price(),cutprice.getAc_mix_limit_price(),6); + + BigDecimal oldAchPrice = history.getAch_price(); + BigDecimal pointPrice; + BigDecimal achPrice; + if (!isSelf) { + // 帮砍:按倍数计算 + achPrice = oldAchPrice.multiply(new BigDecimal(point)) + .setScale(4, RoundingMode.HALF_UP); + pointPrice=achPrice.subtract(oldAchPrice).setScale(4, RoundingMode.HALF_UP); + } else { + // 自己砍:按百分比计算 + pointPrice = oldAchPrice.multiply(new BigDecimal(point)) + .divide(new BigDecimal(10), 4, RoundingMode.HALF_UP) + .setScale(4, RoundingMode.HALF_UP); + achPrice = oldAchPrice.add(pointPrice); + } + achPrice= BigDecimalFormatter.formatWithoutTrailingZerosBigDecimal(achPrice); + pointPrice= BigDecimalFormatter.formatWithoutTrailingZerosBigDecimal(pointPrice); + Map result=new HashMap(); + result.put("achPrice",achPrice); + result.put("point",point); + result.put("pointPrice",pointPrice); + return result; + } catch (Exception e) { + log.error("计算骰子结果异常, ac_id: {}, user_id: {}", ac_id, user_id, e); + throw new RuntimeException("计算砍价金额失败", e); + } + } } diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreActivityBaseServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreActivityBaseServiceImpl.java index e072ea71..01dd0239 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreActivityBaseServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreActivityBaseServiceImpl.java @@ -3714,6 +3714,58 @@ public class ShopStoreActivityBaseServiceImpl extends BaseServiceImpl 0) { activity_rule.put("product_count", product_count); } + String user_cutprice_num=getParameter("user_cutprice_num"); + if (StringUtils.isNotEmpty(user_cutprice_num)){ + activity_rule.put("user_cutprice_num", Convert.toInt(user_cutprice_num));//砍价次数 + } + + String cut_first_price=getParameter("cut_first_price");//首刀金额 + String cut_first_percent=getParameter("cut_first_percent");//首刀金额比例 + if(StringUtils.isNotEmpty(cut_first_price)&&StringUtils.isNotEmpty(cut_first_percent)) { + throw new ApiException("首刀金额,首刀金额比例只能存在一个"); + } + if(StringUtils.isNotEmpty(cut_first_price)){ + activity_rule.put("cut_first_price", cut_first_price); // 首刀砍掉价格 cut_first_price和cut_first_percent 只能存在一个 + } + if(StringUtils.isNotEmpty(cut_first_percent)){ + activity_rule.put("cut_first_percent", cut_first_percent); // 首刀砍掉百分比 + } + String diceObj=getParameter("diceObj"); + if(StringUtils.isNotEmpty(diceObj)){ + /** + * { + * "luckyList": [ + * { + * "doubleValue": 1,//点数 + * "probability":0//概率 + * }, + * { + * "doubleValue": 2,//点数 + * "probability":10//概率 + * }, + * { + * "doubleValue": 3,//点数 + * "probability":20//概率 + * }, + * { + * "doubleValue": 4,//点数 + * "probability":20//概率 + * }, + * { + * "doubleValue": 5,//点数 + * "probability":20//概率 + * }, + * { + * "doubleValue": 6,//点数 + * "probability":20//概率 + * } + * ], + * "sub_num":"1"//减刀人数,如1,每邀请1个人,减少一刀 todo + * "lottery_num":1 每邀请一人,给一次转盘抽奖 + * } + */ + shopStoreActivityBase.setLucky_turn(diceObj); + } shopStoreActivityBase.setActivity_rule(Convert.toStr(activity_rule)); } else if (base.getActivity_type_id().equals(StateCode.ACTIVITY_TYPE_GIFTBAG)) { @@ -5662,9 +5714,64 @@ public class ShopStoreActivityBaseServiceImpl extends BaseServiceImpl Date: Fri, 12 Dec 2025 11:08:53 +0800 Subject: [PATCH 12/28] =?UTF-8?q?=E5=A4=87=E4=BB=BD=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sql/shop/dev/20251209_01ddl.sql | 94 +++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 sql/shop/dev/20251209_01ddl.sql diff --git a/sql/shop/dev/20251209_01ddl.sql b/sql/shop/dev/20251209_01ddl.sql new file mode 100644 index 00000000..33236695 --- /dev/null +++ b/sql/shop/dev/20251209_01ddl.sql @@ -0,0 +1,94 @@ +-- shop_store_activity_base +CREATE TABLE `shop_store_activity_base_1` ( + `activity_id` int unsigned NOT NULL AUTO_INCREMENT COMMENT '活动编号', + `store_id` int unsigned NOT NULL DEFAULT '0' COMMENT '店铺编号', + `user_id` int unsigned NOT NULL DEFAULT '0' COMMENT '用户编号', + `activity_name` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL DEFAULT '' COMMENT '活动名称', + `activity_title` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL DEFAULT '' COMMENT '活动标题', + `activity_remark` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL DEFAULT '' COMMENT '活动说明', + `activity_combo_id` int unsigned NOT NULL DEFAULT '0' COMMENT '套餐编号', + `activity_type_id` int unsigned NOT NULL DEFAULT '0' COMMENT '活动类型', + `activity_starttime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '活动开始时间', + `activity_endtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '活动结束时间', + `activity_state` tinyint unsigned NOT NULL DEFAULT '1' COMMENT '活动状态(ENUM):0-未开启;1-正常;2-已结束;3-管理员关闭;4-商家关闭', + `activity_rule` varchar(10240) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL DEFAULT '' COMMENT '活动规则(json):不检索{rule_id:{}, rule_id:{}},统一解析规则{"requirement":{"buy":{"item":[1,2,3],"subtotal":"通过计算修正满足的条件"}},"rule":[{"total":100,"max_num":1,"item":{"1":1,"1200":3}},{"total":200,"max_num":1,"item":{"1":1,"1200":3}}]}', + `activity_type` tinyint unsigned NOT NULL DEFAULT '0' COMMENT '参与类型(ENUM):1-免费参与;2-积分参与;3-购买参与;4-分享参与', + `activity_order` tinyint unsigned NOT NULL DEFAULT '50' COMMENT '排序', + `activity_is_finish` tinyint unsigned NOT NULL DEFAULT '0' COMMENT '活动是否完成(ENUM):0-未完成;1-已完成;2-已解散(目前用于团购)', + `item_id` varchar(1024) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL DEFAULT '' COMMENT '单品优惠商品编号DOT', + `subsite_id` varchar(20) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL DEFAULT '0' COMMENT '分站ID', + `version` int unsigned NOT NULL DEFAULT '0' COMMENT '版本', + `activity_on_is_off` tinyint unsigned NOT NULL DEFAULT '0' COMMENT '活动是否线上或线下:0:线上,1:线下', + `activity_share_num` tinyint unsigned NOT NULL DEFAULT '0' COMMENT '活动分享次数', + `activity_use_level` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL DEFAULT '' COMMENT '活动使用等级(DOT)', + `activity_releasetime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '发布时间', + `flow_no` varchar(255) DEFAULT NULL COMMENT '思迅活动id', + `cut_hour` int DEFAULT '72' COMMENT '在活动时间范围内,用户砍价允许的天数', + `product_count` int DEFAULT '5' COMMENT '参加活动商品的总数量', + PRIMARY KEY (`activity_id`) USING BTREE, + KEY `store_id` (`store_id`,`activity_state`) USING BTREE, + KEY `activity_type_id` (`activity_type_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COMMENT='活动表-通过插件实现\r\n当为拼团是activity_rule中的group_remain_quantity用于标识拼团剩余需要人数,如果用户登录了,需要查询出activity_groupbooking中参与该团的剩余情况'; +insert into shop_store_activity_base_1 select * from shop_store_activity_base ; +drop table shop_store_activity_base; +create table shop_store_activity_base select * from shop_store_activity_base_1; + +--shop_activity_cutprice_history +CREATE TABLE `shop_activity_cutprice_history_1` ( + `ach_id` int unsigned NOT NULL AUTO_INCREMENT COMMENT '砍价历史编号', + `activity_id` int unsigned NOT NULL DEFAULT '0' COMMENT '活动编号', + `user_id` int unsigned NOT NULL DEFAULT '0' COMMENT '砍价用户', + `ach_price` decimal(10,2) unsigned NOT NULL DEFAULT '0.00' COMMENT '砍掉价格', + `item_id` int unsigned NOT NULL DEFAULT '0' COMMENT '商品编号', + `ach_datetime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '砍价时间', + `ac_id` int unsigned NOT NULL DEFAULT '0' COMMENT '砍价编号', + PRIMARY KEY (`ach_id`) USING BTREE, + KEY `activity_id` (`activity_id`) USING BTREE, + KEY `idx_shop_activity_cutprice_history_ac_id` (`ac_id`), + KEY `idx_shop_activity_cutprice_history_user_id` (`user_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COMMENT='砍价记录历史'; +insert into shop_activity_cutprice_history_1 select * from shop_activity_cutprice_history; +drop table shop_activity_cutprice_history; +create table shop_activity_cutprice_history as select * FROM shop_activity_cutprice_history_1; + +--shop_store_activity_item +CREATE TABLE `shop_store_activity_item_1` ( + `activity_item_id` int unsigned NOT NULL AUTO_INCREMENT COMMENT '商品表编号', + `store_id` int unsigned NOT NULL DEFAULT '0' COMMENT '店铺编号', + `activity_type_id` int unsigned NOT NULL DEFAULT '0' COMMENT '活动类型编号', + `activity_id` int unsigned NOT NULL DEFAULT '0' COMMENT '活动编号', + `product_id` int unsigned NOT NULL DEFAULT '0', + `item_id` int unsigned NOT NULL DEFAULT '0' COMMENT '商品编号', + `category_id` mediumint unsigned NOT NULL DEFAULT '0' COMMENT '商品分类', + `activity_item_starttime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '开始时间', + `activity_item_endtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '结束时间', + `activity_item_price` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '限时折扣价格', + `activity_item_min_quantity` int unsigned NOT NULL DEFAULT '0' COMMENT '购买下限', + `activity_item_state` tinyint unsigned NOT NULL DEFAULT '1' COMMENT '活动状态(ENUM):0-未开启;1-正常;2-已结束;3-管理员关闭', + `activity_item_recommend` tinyint unsigned NOT NULL DEFAULT '0' COMMENT '推荐标志:0-未推荐;1-已推荐', + `activity_level_limits` tinyint NOT NULL DEFAULT '0' COMMENT '等级限制', + `activity_points_num` int NOT NULL DEFAULT '0' COMMENT '需要积分数', + `activity_points_product_num` int unsigned NOT NULL DEFAULT '0' COMMENT '积分商品剩余数量', + `activity_points_product_sale_num` int NOT NULL DEFAULT '0' COMMENT '积分商品已售数量', + PRIMARY KEY (`activity_item_id`) USING BTREE, + KEY `store_id` (`activity_id`) USING BTREE, + KEY `item_id` (`product_id`,`item_id`) USING BTREE, + KEY `item_id_2` (`item_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COMMENT='参与活动商品表-用户筛选计算'; + +insert into shop_store_activity_item_1 select * from shop_store_activity_item; +drop table shop_store_activity_item; +create table shop_store_activity_item select * from shop_store_activity_item_1; + + +ALTER TABLE shop_store_activity_base MODIFY activity_id int unsigned NOT NULL AUTO_INCREMENT COMMENT '活动编号' PRIMARY KEY; +alter table shop_store_activity_base add key `store_id` (`store_id`,`activity_state`) USING BTREE; +alter table shop_store_activity_base add key `activity_type_id` (`activity_type_id`) USING BTREE; +ALTER TABLE shop_activity_cutprice_history MODIFY ach_id int unsigned NOT NULL AUTO_INCREMENT COMMENT '砍价历史编号' PRIMARY KEY; +alter table shop_activity_cutprice_history add KEY `activity_id` (`activity_id`) USING BTREE; +alter table shop_activity_cutprice_history add KEY `idx_shop_activity_cutprice_history_ac_id` (`ac_id`); +alter table shop_activity_cutprice_history add KEY `idx_shop_activity_cutprice_history_user_id` (`user_id`); +ALTER TABLE shop_store_activity_item MODIFY activity_item_id int unsigned NOT NULL AUTO_INCREMENT COMMENT '商品表编号' PRIMARY KEY; +alter table shop_store_activity_item add KEY `store_id` (`activity_id`) USING BTREE; +alter table shop_store_activity_item add KEY `item_id` (`product_id`,`item_id`) USING BTREE; +alter table shop_store_activity_item add KEY `item_id_2` (`item_id`) USING BTREE; From 390eca8b63accf4bbd89095a276d1853f9c2c96f Mon Sep 17 00:00:00 2001 From: Jack <46790855@qq.com> Date: Fri, 12 Dec 2025 14:17:11 +0800 Subject: [PATCH 13/28] =?UTF-8?q?=E5=B9=B3=E5=8F=B0=E5=86=85=E9=83=A8?= =?UTF-8?q?=E9=85=8D=E9=80=81=E8=B4=B9=E7=9A=84=E9=80=BB=E8=BE=91=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E3=80=82=E7=BB=86=E8=8A=82=E8=B0=83=E6=95=B4=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ShopStoreSameCityTransportService.java | 10 ++- ...StoreSameCityTransportBaseServiceImpl.java | 87 +++++++++++++------ ...ShopStoreSameCityTransportServiceImpl.java | 25 ++++++ pom.xml | 12 ++- 4 files changed, 99 insertions(+), 35 deletions(-) diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/ShopStoreSameCityTransportService.java b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/ShopStoreSameCityTransportService.java index 4c5a399d..137cdd80 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/ShopStoreSameCityTransportService.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/ShopStoreSameCityTransportService.java @@ -22,13 +22,21 @@ public interface ShopStoreSameCityTransportService { */ CommonResult deleteShopStoreSameCityTransport(Long transportId); + /** + * 根据店铺 Id 获取同城配送扩展设置列表 + * + * @param storeId + * @return + */ + List selectShopStoreSameCityTransportList(Long storeId); + /** * 根据同城配送基础配置自增 Id 获取同城配送扩展设置列表 * * @param transportBaseId * @return */ - List selectShopStoreSameCityTransportList(Long transportBaseId); + List selectShopStoreSameCityTransportListByTransportBaseId(Long transportBaseId); /** * 保存同城配送扩展设置列表(存在就更新,不存在就新增) diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreSameCityTransportBaseServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreSameCityTransportBaseServiceImpl.java index d91d4b18..9d2ab37e 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreSameCityTransportBaseServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreSameCityTransportBaseServiceImpl.java @@ -282,60 +282,93 @@ public class ShopStoreSameCityTransportBaseServiceImpl extends BaseServiceImpl transportList = shopStoreSameCityTransportService.selectShopStoreSameCityTransportList(transportBase.getStore_id()); + // 获取配送扩展设置列表 + List transportList; + if (CheckUtil.isEmpty(transportBase.getTransport_base_id())) { + transportList = shopStoreSameCityTransportService.selectShopStoreSameCityTransportList(transportBase.getStore_id()); + } else { + transportList = shopStoreSameCityTransportService.selectShopStoreSameCityTransportListByTransportBaseId(transportBase.getTransport_base_id()); + } shopStoreSameCityTransportBaseDTO.setTransportList(transportList); + logger.debug("成功获取店铺 {} 的同城配送设置详情", storeId); return shopStoreSameCityTransportBaseDTO; } + /** * 根据店铺Id获取同城配送基础运费记录 * diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreSameCityTransportServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreSameCityTransportServiceImpl.java index 1854c561..fc431599 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreSameCityTransportServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreSameCityTransportServiceImpl.java @@ -62,6 +62,31 @@ public class ShopStoreSameCityTransportServiceImpl extends BaseServiceImpl selectShopStoreSameCityTransportListByTransportBaseId(Long transportBaseId) { + if (transportBaseId == null || transportBaseId <= 0) { + return Collections.emptyList(); + } + + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("transport_base_id", transportBaseId); + queryWrapper.eq("status", CommonConstant.Enable); + queryWrapper.orderByAsc("transport_id"); + + List shopStoreSameCityTransportList = list(queryWrapper); + if (CollectionUtil.isEmpty(shopStoreSameCityTransportList)) { + shopStoreSameCityTransportList = Collections.emptyList(); + } + + return shopStoreSameCityTransportList; + } + /** * 根据同城配送基础配置自增 Id 获取同城配送扩展设置列表 * diff --git a/pom.xml b/pom.xml index 68a9333d..47bd110b 100644 --- a/pom.xml +++ b/pom.xml @@ -539,11 +539,6 @@ - - org.apache.maven.plugins - maven-dependency-plugin - - com.spotify docker-maven-plugin @@ -571,7 +566,9 @@ build - + + + ${docker.registry}/mall/${project.artifactId}:${project.version} @@ -592,7 +589,7 @@ true ${project.version} - + latest @@ -609,6 +606,7 @@ + From 09154bcdb428ea7b1c6435eaafa0b3fa685343f7 Mon Sep 17 00:00:00 2001 From: liyj <1617420630@qq.com> Date: Fri, 12 Dec 2025 15:12:32 +0800 Subject: [PATCH 14/28] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E5=8C=96=E6=B5=8B=E8=AF=95=E7=A0=8D=E4=BB=B7=E9=80=BB=E8=BE=91?= =?UTF-8?q?=E5=92=8C=E6=8E=A7=E5=88=B6=E5=A4=A7=E8=BD=AC=E7=9B=98=E7=8E=A9?= =?UTF-8?q?=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mall/common/utils/RollDiceUtils.java | 22 ++++++++++--------- .../impl/ShopActivityCutpriceServiceImpl.java | 7 ++++++ 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/mall-common/src/main/java/com/suisung/mall/common/utils/RollDiceUtils.java b/mall-common/src/main/java/com/suisung/mall/common/utils/RollDiceUtils.java index 06691aff..63db8256 100644 --- a/mall-common/src/main/java/com/suisung/mall/common/utils/RollDiceUtils.java +++ b/mall-common/src/main/java/com/suisung/mall/common/utils/RollDiceUtils.java @@ -182,8 +182,10 @@ public class RollDiceUtils { int point = (Integer) config.get("doubleValue"); distribution.put(point, 0); } - BigDecimal salePrice = new BigDecimal("47"); - int accNum=100; + BigDecimal limitPrice=new BigDecimal("9.9"); + BigDecimal salePrice = new BigDecimal("47").subtract(limitPrice).setScale(2, RoundingMode.HALF_UP); + + int accNum=rollCount; // 摇骰子多次并统计 for (int i = 0; i < rollCount; i++) { List arr= randMoney(salePrice, accNum); @@ -196,7 +198,7 @@ public class RollDiceUtils { distribution.put(result, distribution.get(result) + 1); accNum--; } - + System.out.println("最终金额:"+limitPrice); return distribution; } @@ -239,12 +241,12 @@ public class RollDiceUtils { List> configs = new ArrayList<>(); // 添加配置项 - configs.add(createDiceConfig(1, 45)); - configs.add(createDiceConfig(2, 45)); - configs.add(createDiceConfig(3, 3)); - configs.add(createDiceConfig(4, 2)); - configs.add(createDiceConfig(5, 3)); - configs.add(createDiceConfig(6, 2)); + configs.add(createDiceConfig(1, 40)); + configs.add(createDiceConfig(2, 40)); + configs.add(createDiceConfig(3, 5)); + configs.add(createDiceConfig(4, 5)); + configs.add(createDiceConfig(5, 5)); + configs.add(createDiceConfig(6, 5)); // 创建骰子游戏实例 DiceGame diceGame = new DiceGame(configs); @@ -261,7 +263,7 @@ public class RollDiceUtils { // 测试概率分布 System.out.println("\n=== 概率分布测试(100次) ==="); - int testCount = 100; + int testCount = 18; Map distribution = diceGame.testDistribution(testCount); System.out.println("点数\t出现次数\t实际概率\t预期概率"); diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/activity/service/impl/ShopActivityCutpriceServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/activity/service/impl/ShopActivityCutpriceServiceImpl.java index e9b834e9..d691498d 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/activity/service/impl/ShopActivityCutpriceServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/activity/service/impl/ShopActivityCutpriceServiceImpl.java @@ -958,6 +958,13 @@ public class ShopActivityCutpriceServiceImpl extends BaseServiceImpl Date: Fri, 12 Dec 2025 15:33:37 +0800 Subject: [PATCH 15/28] =?UTF-8?q?=E5=8F=91=E8=B5=B7=E4=BA=BA=E6=91=87?= =?UTF-8?q?=E4=B8=AD1=E9=83=BD=E4=B8=8D=E7=BB=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../impl/ShopActivityCutpriceServiceImpl.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/activity/service/impl/ShopActivityCutpriceServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/activity/service/impl/ShopActivityCutpriceServiceImpl.java index d691498d..b9448080 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/activity/service/impl/ShopActivityCutpriceServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/activity/service/impl/ShopActivityCutpriceServiceImpl.java @@ -1181,10 +1181,16 @@ public class ShopActivityCutpriceServiceImpl extends BaseServiceImpl Date: Fri, 12 Dec 2025 15:38:47 +0800 Subject: [PATCH 16/28] =?UTF-8?q?=E5=B9=B3=E5=8F=B0=E5=86=85=E9=83=A8?= =?UTF-8?q?=E9=85=8D=E9=80=81=E8=B4=B9=E7=9A=84=E9=80=BB=E8=BE=91=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E3=80=82=E7=BB=86=E8=8A=82=E8=B0=83=E6=95=B4=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../store/service/impl/ShopStoreBaseServiceImpl.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreBaseServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreBaseServiceImpl.java index 4c541f73..14fb2e54 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreBaseServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreBaseServiceImpl.java @@ -1564,7 +1564,15 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl Date: Fri, 12 Dec 2025 16:17:58 +0800 Subject: [PATCH 17/28] =?UTF-8?q?diy=E6=A8=A1=E6=9D=BF=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E5=88=9B=E5=BB=BA=E7=A9=BA=E7=99=BD=E6=A8=A1=E6=9D=BF=EF=BC=8C?= =?UTF-8?q?=E7=A7=BB=E9=99=A4=E5=8F=AF=E9=80=89=E7=94=A8=E7=9A=84=E5=B7=B2?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E7=9A=84=E6=A8=A1=E6=9D=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/ShopPageAppController.java | 14 ++++++++++ .../shop/page/service/ShopPageAppService.java | 2 ++ .../service/impl/ShopPageAppServiceImpl.java | 28 +++++++++++++++++-- 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/page/controller/admin/ShopPageAppController.java b/mall-shop/src/main/java/com/suisung/mall/shop/page/controller/admin/ShopPageAppController.java index c787c91a..95bb8765 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/page/controller/admin/ShopPageAppController.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/page/controller/admin/ShopPageAppController.java @@ -132,6 +132,7 @@ public class ShopPageAppController extends BaseControllerImpl { }else { if (is_use==1&&(shopStoreInfo.getStore_template().equals(tpl_label))) { current_tpl = item; + it.remove(); } } } else { @@ -553,5 +554,18 @@ public class ShopPageAppController extends BaseControllerImpl { return shopPageAppService.deletePageApp(appId); } + /** + * 创建空白模板 + * @param appName 模板名称 + * @param appIndustry 行业 + * @return + */ + @ApiOperation(value = "店铺风格表-创建空白模板", notes = "店铺风格表-创建空白模板") + @RequestMapping(value = "/createBlankPageApp", method = RequestMethod.POST) + public CommonResult createBlankPageApp(@RequestParam(name = "appName") String appName, + @RequestParam(name = "appIndustry",required = false,defaultValue = "0") String appIndustry) { + return shopPageAppService.createBlankPageApp(appName,appIndustry); + } + } diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/page/service/ShopPageAppService.java b/mall-shop/src/main/java/com/suisung/mall/shop/page/service/ShopPageAppService.java index fc004a73..e115031b 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/page/service/ShopPageAppService.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/page/service/ShopPageAppService.java @@ -60,4 +60,6 @@ public interface ShopPageAppService extends IBaseService { CommonResult copyDiyByAppId(Integer appId,String newAppName,String appIndustry); CommonResult deletePageApp(Integer appId); + + CommonResult createBlankPageApp(String appName,String appIndustry); } diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/page/service/impl/ShopPageAppServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/page/service/impl/ShopPageAppServiceImpl.java index 791f40ac..4cee4e73 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/page/service/impl/ShopPageAppServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/page/service/impl/ShopPageAppServiceImpl.java @@ -1107,6 +1107,32 @@ public class ShopPageAppServiceImpl extends BaseServiceImpl Date: Fri, 12 Dec 2025 16:29:22 +0800 Subject: [PATCH 18/28] =?UTF-8?q?diy=E7=A9=BA=E7=99=BD=E6=A8=A1=E6=9D=BF?= =?UTF-8?q?=E6=9D=83=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sql/shop/dev/20251212_02_dml.sql | 1 + 1 file changed, 1 insertion(+) create mode 100644 sql/shop/dev/20251212_02_dml.sql diff --git a/sql/shop/dev/20251212_02_dml.sql b/sql/shop/dev/20251212_02_dml.sql new file mode 100644 index 00000000..118fd9e3 --- /dev/null +++ b/sql/shop/dev/20251212_02_dml.sql @@ -0,0 +1 @@ +INSERT INTO `admin_base_protocol` (`ctl`, `met`, `db`, `rights_id`, `log`, `path`,`comment`) VALUES ('/admin/shop/shop-page-app/createBlankPageApp', 'index', 'master', '', '0', '/admin/shop/shop-page-app/createBlankPageApp','创建diy空白模板'); \ No newline at end of file From f7887e6b79678091ddf65802046daa4f7bad7ba6 Mon Sep 17 00:00:00 2001 From: liyj <1617420630@qq.com> Date: Fri, 12 Dec 2025 16:34:10 +0800 Subject: [PATCH 19/28] =?UTF-8?q?=E6=A8=A1=E6=9D=BF=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E5=80=92=E5=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mall/shop/page/controller/admin/ShopPageAppController.java | 1 + 1 file changed, 1 insertion(+) diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/page/controller/admin/ShopPageAppController.java b/mall-shop/src/main/java/com/suisung/mall/shop/page/controller/admin/ShopPageAppController.java index 95bb8765..00618d98 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/page/controller/admin/ShopPageAppController.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/page/controller/admin/ShopPageAppController.java @@ -83,6 +83,7 @@ public class ShopPageAppController extends BaseControllerImpl { if(user.isStore()) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("store_id", user.getStore_id()); + queryWrapper.orderByDesc("app_id"); List shopPageAppList= shopPageAppService.list(queryWrapper); if(shopPageAppList.isEmpty()) { String resultStr= accountBaseConfigService.getSystemConfig("service_app_tpl"); From 381ede08ba43552cc0d1db15b5edd99496d8648f Mon Sep 17 00:00:00 2001 From: Jack <46790855@qq.com> Date: Fri, 12 Dec 2025 17:03:44 +0800 Subject: [PATCH 20/28] =?UTF-8?q?=E6=89=93=E5=8D=B0=E6=A8=A1=E7=89=88?= =?UTF-8?q?=E6=9B=B4=E6=94=B9=E5=8A=A8=E6=80=81=E9=85=8D=E9=80=81=E6=96=B9?= =?UTF-8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mall/common/service/impl/CommonService.java | 14 +++++++++++--- .../service/impl/ShopOrderBaseServiceImpl.java | 2 +- .../service/impl/ShopOrderInfoServiceImpl.java | 3 +-- .../src/main/resources/templates/order_printer.txt | 4 ++-- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/mall-common/src/main/java/com/suisung/mall/common/service/impl/CommonService.java b/mall-common/src/main/java/com/suisung/mall/common/service/impl/CommonService.java index 47eeb7f2..68e87869 100644 --- a/mall-common/src/main/java/com/suisung/mall/common/service/impl/CommonService.java +++ b/mall-common/src/main/java/com/suisung/mall/common/service/impl/CommonService.java @@ -90,11 +90,19 @@ public class CommonService { * @return 配送方式名称 */ public static String getDeliveryExpressName(Integer deliveryTypeId) { - if (deliveryTypeId == null) return "其他配送"; - String name = StateCode.DELIVERY_TYPE_MAP.get(deliveryTypeId); - return name != null ? name : "其他配送"; + // 当配送方式ID为空时,默认返回顺丰同城 + if (deliveryTypeId == null) { + log.debug("配送方式ID为空,返回默认配送方式:顺丰同城"); + return "顺丰同城"; + } + + // 从配送方式映射表中获取名称,如果未找到则返回默认值顺丰同城 + String deliveryName = StateCode.DELIVERY_TYPE_MAP.getOrDefault(deliveryTypeId, "顺丰同城"); + log.debug("获取配送方式名称:deliveryTypeId={} deliveryName={}", deliveryTypeId, deliveryName); + return deliveryName; } + /** * 判断配送方式是否为同城配送 * diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/order/service/impl/ShopOrderBaseServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/order/service/impl/ShopOrderBaseServiceImpl.java index 57b38a74..6aa797a0 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/order/service/impl/ShopOrderBaseServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/order/service/impl/ShopOrderBaseServiceImpl.java @@ -8914,7 +8914,7 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl 订单来源:微信小程序
支付方式:微信支付
-配送来源:顺丰同城
+配送来源:${deliver_type_name!'顺丰同城'}
付款时间:${payment_time?string('yyyy-MM-dd HH:mm:ss')}
--------------------------------
商品名称 数量 金额
@@ -103,4 +103,4 @@ ${store_name}
--------------------------------
#${order_pickup_num_str}
买家备注:${order_message!'-'}
配送时间:${payment_time?string('MM-dd HH:mm')}~${delivery_time?string('HH:mm')}
--------------------------------
订单编号:${order_id}
订单来源:微信小程序
支付方式:微信支付
配送来源:顺丰同城
付款时间:${payment_time?string('yyyy-MM-dd HH:mm:ss')}
--------------------------------
商品名称 数量 金额
--------------------------------
<#list order_items as item>${item.s_name}${item.s_quantity}${item.s_amount}
<#if item.s_name_segs??><#list item.s_name_segs as seg>${seg}
<#if item.product_sn?default("")?trim?length gt 1>${item.product_sn}
--------------------------------
商品总件数:${order_items_count!0}
商品总额:¥${order_product_amount?string('0.00')}
运费:¥${order_shipping_fee?string('0.00')}
<#if packing_fee?? && (packing_fee > 0)>打包费:¥${packing_fee?string('0.00')}
优惠金额:-¥${(quanyi!0)?string('0.00')}
实付金额:¥${order_payment_amount?string('0.00')}
<#if seller_message?default("")?trim?length gt 1>--------------------------------
商家备注:${seller_message!'-'}
--------------------------------
收货人:${buyer_user_name!''}
收货人手机:${da_mobile!'-'}
收货地址:${da_province!'-'}${da_city!'-'}${da_address!'-'}
--------------------------------
门店:${store_name}
门店电话:${store_tel!'-'}
收银员:${cashier!'店长'}
第三版带变量的模版(有预约订单) -<#if is_booking_order>【预约订单】
${store_name}
--------------------------------
#${order_pickup_num_str}
买家备注:${order_message!'-'}
配送时间:${payment_time?string('MM-dd HH:mm')}~${delivery_time?string('HH:mm')}
--------------------------------
订单编号:${order_id}
订单来源:微信小程序
支付方式:微信支付
配送来源:顺丰同城
付款时间:${payment_time?string('yyyy-MM-dd HH:mm:ss')}
--------------------------------
商品名称 数量 金额
--------------------------------
<#list order_items as item>${item.s_name}${item.s_quantity}${item.s_amount}
<#if item.s_name_segs??><#list item.s_name_segs as seg>${seg}
<#if item.product_sn?default("")?trim?length gt 1>${item.product_sn}

--------------------------------
商品总件数:${order_items_count!0}
商品总额:¥${order_product_amount?string('0.00')}
运费:¥${order_shipping_fee?string('0.00')}
<#if packing_fee?? && (packing_fee > 0)>打包费:¥${packing_fee?string('0.00')}
优惠金额:-¥${(quanyi!0)?string('0.00')}
实付金额:¥${order_payment_amount?string('0.00')}
<#if seller_message?default("")?trim?length gt 1>--------------------------------
商家备注:${seller_message!'-'}
--------------------------------
收货人:${buyer_user_name!''}
收货人手机:${da_mobile!'-'}
收货地址:${da_province!'-'}${da_city!'-'}${da_address!'-'}
--------------------------------
门店:${store_name}
门店电话:${store_tel!'-'}
收银员:${cashier!'店长'}
\ No newline at end of file +<#if is_booking_order>【预约订单】
${store_name}
--------------------------------
#${order_pickup_num_str}
买家备注:${order_message!'-'}
配送时间:${payment_time?string('MM-dd HH:mm')}~${delivery_time?string('HH:mm')}
--------------------------------
订单编号:${order_id}
订单来源:微信小程序
支付方式:微信支付
配送来源:${deliver_type_name!'顺丰同城'}
付款时间:${payment_time?string('yyyy-MM-dd HH:mm:ss')}
--------------------------------
商品名称 数量 金额
--------------------------------
<#list order_items as item>${item.s_name}${item.s_quantity}${item.s_amount}
<#if item.s_name_segs??><#list item.s_name_segs as seg>${seg}
<#if item.product_sn?default("")?trim?length gt 1>${item.product_sn}

--------------------------------
商品总件数:${order_items_count!0}
商品总额:¥${order_product_amount?string('0.00')}
运费:¥${order_shipping_fee?string('0.00')}
<#if packing_fee?? && (packing_fee > 0)>打包费:¥${packing_fee?string('0.00')}
优惠金额:-¥${(quanyi!0)?string('0.00')}
实付金额:¥${order_payment_amount?string('0.00')}
<#if seller_message?default("")?trim?length gt 1>--------------------------------
商家备注:${seller_message!'-'}
--------------------------------
收货人:${buyer_user_name!''}
收货人手机:${da_mobile!'-'}
收货地址:${da_province!'-'}${da_city!'-'}${da_address!'-'}
--------------------------------
门店:${store_name}
门店电话:${store_tel!'-'}
收银员:${cashier!'店长'}
\ No newline at end of file From cf80b869fe99c7a331e106b71387f302f3851c09 Mon Sep 17 00:00:00 2001 From: liyj <1617420630@qq.com> Date: Sat, 13 Dec 2025 10:21:29 +0800 Subject: [PATCH 21/28] =?UTF-8?q?=E5=9B=BE=E7=89=87=E9=80=89=E6=8B=A9?= =?UTF-8?q?=E4=B8=8D=E6=94=B9=E5=8F=98=E5=9B=BE=E6=A0=87=EF=BC=8C=E7=94=B1?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E6=8E=A7=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/templates/diy.html | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/mall-shop/src/main/resources/templates/diy.html b/mall-shop/src/main/resources/templates/diy.html index 2f71999a..cf63b4a9 100644 --- a/mall-shop/src/main/resources/templates/diy.html +++ b/mall-shop/src/main/resources/templates/diy.html @@ -1830,9 +1830,9 @@ v-if="listType==1 || listType==2 || listType==5 || listType==6 || listType==8 || listType==10 || listType==11 || listType==104">

  • -
    + + + {{item.name}}
    @@ -1844,9 +1844,9 @@
    -
    -
    + + + {{item.name}}
    @@ -1857,10 +1857,10 @@
    -
    -
    + + + + {{item.name}}
    From 16d19d79b2eef008497a701e6c34ec080db22a6d Mon Sep 17 00:00:00 2001 From: liyj <1617420630@qq.com> Date: Sat, 13 Dec 2025 11:41:10 +0800 Subject: [PATCH 22/28] =?UTF-8?q?=E8=A3=85=E4=BF=AE=E5=95=86=E5=93=81?= =?UTF-8?q?=E5=9B=BE=E7=89=87=E4=B8=8D=E5=8F=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mall-shop/src/main/resources/templates/diy.html | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/mall-shop/src/main/resources/templates/diy.html b/mall-shop/src/main/resources/templates/diy.html index cf63b4a9..548e0a82 100644 --- a/mall-shop/src/main/resources/templates/diy.html +++ b/mall-shop/src/main/resources/templates/diy.html @@ -1827,7 +1827,7 @@
      + v-if="listType==2 || listType==5 || listType==6 || listType==8 || listType==10 || listType==11 || listType==104">
    • @@ -1841,6 +1841,21 @@
    +
      +
    • +
      +
      + {{item.name}} +
      +
      +
      +
    • +
    +
    From eae16d69579a87bdc0008dd4c2b84eef6078423e Mon Sep 17 00:00:00 2001 From: Jack <46790855@qq.com> Date: Sat, 13 Dec 2025 13:25:07 +0800 Subject: [PATCH 23/28] =?UTF-8?q?=E9=A2=84=E8=AE=A1=E6=94=B6=E5=85=A5fix?= =?UTF-8?q?=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/mapper/order/ShopOrderBaseMapper.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mall-shop/src/main/resources/mapper/order/ShopOrderBaseMapper.xml b/mall-shop/src/main/resources/mapper/order/ShopOrderBaseMapper.xml index b6507d86..a6519138 100644 --- a/mall-shop/src/main/resources/mapper/order/ShopOrderBaseMapper.xml +++ b/mall-shop/src/main/resources/mapper/order/ShopOrderBaseMapper.xml @@ -819,8 +819,8 @@ (od.order_discount_amount + od.voucher_price + od.order_points_fee + od.order_adjust_fee) as total_discount_amount, - - (ob.order_product_amount-od.order_discount_amount-od.voucher_price-od.order_points_fee-od.order_adjust_fee-od.platform_fee-order_shipping_fee_inner+od.packing_fee) + + (od.order_item_amount-od.order_discount_amount-od.voucher_price-od.order_points_fee-od.order_adjust_fee-od.platform_fee-order_shipping_fee_inner-lkl_fee+od.packing_fee) as order_income_amount, (od.platform_fee+lkl_fee) as platform_fee, od.packing_fee, From 6257fb29bd6527fd9e6d76066c34c5910364b58f Mon Sep 17 00:00:00 2001 From: Jack <46790855@qq.com> Date: Sat, 13 Dec 2025 13:32:11 +0800 Subject: [PATCH 24/28] =?UTF-8?q?=E9=A2=84=E8=AE=A1=E6=94=B6=E5=85=A5fix?= =?UTF-8?q?=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/mapper/order/ShopOrderBaseMapper.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mall-shop/src/main/resources/mapper/order/ShopOrderBaseMapper.xml b/mall-shop/src/main/resources/mapper/order/ShopOrderBaseMapper.xml index a6519138..a09776c4 100644 --- a/mall-shop/src/main/resources/mapper/order/ShopOrderBaseMapper.xml +++ b/mall-shop/src/main/resources/mapper/order/ShopOrderBaseMapper.xml @@ -822,7 +822,7 @@ (od.order_item_amount-od.order_discount_amount-od.voucher_price-od.order_points_fee-od.order_adjust_fee-od.platform_fee-order_shipping_fee_inner-lkl_fee+od.packing_fee) as order_income_amount, - (od.platform_fee+lkl_fee) as platform_fee, + od.platform_fee, od.packing_fee, od.order_message, sb.store_id, From e8c964ddcbea22ca593a79edc57d2ad061d58d08 Mon Sep 17 00:00:00 2001 From: liyj <1617420630@qq.com> Date: Sat, 13 Dec 2025 16:09:59 +0800 Subject: [PATCH 25/28] =?UTF-8?q?=E8=A3=85=E4=BF=AE=E9=99=A4=E5=95=86?= =?UTF-8?q?=E5=93=81=E5=9B=BE=E7=89=87=E5=85=B6=E4=BB=96=E9=80=89=E6=8B=A9?= =?UTF-8?q?=E4=B8=8D=E5=8F=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/static/diy/js/diy.js | 58 ++++++++++++++++--- .../src/main/resources/templates/diy.html | 4 +- 2 files changed, 51 insertions(+), 11 deletions(-) diff --git a/mall-shop/src/main/resources/static/diy/js/diy.js b/mall-shop/src/main/resources/static/diy/js/diy.js index 2b7a9c02..390e0bb1 100644 --- a/mall-shop/src/main/resources/static/diy/js/diy.js +++ b/mall-shop/src/main/resources/static/diy/js/diy.js @@ -13386,10 +13386,47 @@ } function mn(t, e, i) { var n; - Ri(e) ? qi(i) ? t[_x41903[135]](e) : (i = _x41903[3403] === e && _x41903[3404] === t[_x41903[1159]] ? _x41903[364] : e, + Ri(e) ? qi(i) ? t[_x41903[135]](e) : (i = _x41903[3403] === e && _x41903[3404] === t[_x41903[1159]] ? _x41903[364] : e, t[_x41903[24]](e, i)) : Bi(e) ? t[_x41903[24]](e, qi(i) || _x41903[365] === i ? _x41903[365] : _x41903[364]) : Wi(e) ? qi(i) ? t[_x41903[3402]](Fi, Yi(e)) : t[_x41903[3405]](Fi, e, i) : qi(i) ? t[_x41903[135]](e) : (!he || de || _x41903[2418] !== t[_x41903[1159]] || _x41903[1191] !== e || t[_x41903[3406]] || (t[_x41903[153]](_x41903[183], n = function(e) { e[_x41903[439]](), t[_x41903[344]](_x41903[183], n); }), t[_x41903[3406]] = !0), t[_x41903[24]](e, i)); + // if (Ri(e)) { + // if (qi(i)) { + // t[_x41903[135]](e); + // } else { + // i = (_x41903[3403] === e && _x41903[3404] === t[_x41903[1159]]) ? _x41903[364] : e; + // t[_x41903[24]](e, i); + // } + // } else if (Bi(e)) { + // t[_x41903[24]](e, (qi(i) || _x41903[365] === i) ? _x41903[365] : _x41903[364]); + // } else if (Wi(e)) { + // if (qi(i)) { + // t[_x41903[3402]](Fi, Yi(e)); + // } else { + // t[_x41903[3405]](Fi, e, i); + // } + // } else if (qi(i)) { + // t[_x41903[135]](e); + // } else { + // if (!he || de || _x41903[2418] !== t[_x41903[1159]] || _x41903[1191] !== e || t[_x41903[3406]]) { + // // 条件不满足时跳过 + // } else { + // t[_x41903[153]](_x41903[183], n = function(e) { + // e[_x41903[439]](); + // t[_x41903[344]](_x41903[183], n); + // }); + // t[_x41903[3406]] = !0; + // } + // // var src = t.getAttribute("src"); + // // if(src!=null && src!='' && src!="" && src!=undefined){ + // // + // // } + // if(i!=null && i!='' && i!="" && i!=undefined){ + // t.setAttribute('src',i); + // } + // //var src = $("img").attr("src"); + // //t[_x41903[24]](e, i); + // } } cn = { create: fn, @@ -18009,8 +18046,9 @@ t[_x41903[4556]] = s[_x41903[4557]]); }) : $[_x41903[2030]][_x41903[4089]](__(_x41903[4558]))) : 3 == l[_x41903[4522]] || 4 == l[_x41903[4522]] || 6 == l[_x41903[4522]] || 7 == l[_x41903[4522]] || 14 == l[_x41903[4522]] || 17 == l[_x41903[4522]] ? ($[_x41903[39]](l[_x41903[4520]], function(e, t) { t[_x41903[124]] == l[_x41903[4500]] && (t[_x41903[4559]] = s[_x41903[124]], - t[_x41903[184]] = s[_x41903[184]], t[_x41903[4560]] = s[_x41903[4560]], - t[_x41903[2345]] = s[_x41903[2345]], t[_x41903[4561]] = s[_x41903[4561]], + t[_x41903[184]] = s[_x41903[184]], t[_x41903[4560]] = s[_x41903[4560]], + l.listType==1?t[_x41903[2345]] = s[_x41903[2345]]: "", + t[_x41903[4561]] = s[_x41903[4561]], t[_x41903[4562]] = s[_x41903[4562]], t[_x41903[4563]] = s[_x41903[4563]], t[_x41903[4554]] = s[_x41903[4554]], t[_x41903[4557]] = s[_x41903[4557]], t[_x41903[4564]] = s[_x41903[4564]], t[_x41903[4565]] = s[_x41903[4565]]); @@ -18029,8 +18067,10 @@ } }), publicFun[_x41903[3948]](l[_x41903[820]], l[_x41903[4500]], l[_x41903[4520]])) : 1 == l[_x41903[4522]] || 15 == l[_x41903[4522]] ? (l[_x41903[4519]][_x41903[4559]] = s[_x41903[124]], l[_x41903[4519]][_x41903[184]] = s[_x41903[184]], - l[_x41903[4519]][_x41903[4560]] = s[_x41903[4560]], - l[_x41903[4519]][_x41903[2345]] = s[_x41903[2345]], + l[_x41903[4519]][_x41903[4560]] = s[_x41903[4560]], + //console.log("listType"+l.listType), + //l[_x41903[4519]][_x41903[2345]] = s[_x41903[2345]], + l.listType==1? l[_x41903[4519]][_x41903[2345]] = s[_x41903[2345]]: "", l[_x41903[4519]][_x41903[4561]] = s[_x41903[4561]], l[_x41903[4519]][_x41903[4562]] = s[_x41903[4562]], l[_x41903[4519]][_x41903[4563]] = s[_x41903[4563]], @@ -18040,15 +18080,15 @@ l[_x41903[4519]][_x41903[4565]] = s[_x41903[4565]], publicFun[_x41903[3948]](l[_x41903[820]], l[_x41903[4500]], l[_x41903[4519]])) : 16 == l[_x41903[4522]] ? ($[_x41903[39]](l[_x41903[4520]], function(e, t) { t[_x41903[124]] == l[_x41903[4500]] && (t[_x41903[4559]] = s[_x41903[124]], - t[_x41903[184]] = s[_x41903[184]], t[_x41903[4560]] = s[_x41903[4560]], - t[_x41903[2345]] = s[_x41903[2345]], t[_x41903[4567]] = s[_x41903[4567]], + t[_x41903[184]] = s[_x41903[184]], t[_x41903[4560]] = s[_x41903[4560]], + l.listType==1?t[_x41903[2345]] = s[_x41903[2345]]: "", t[_x41903[4567]] = s[_x41903[4567]], t[_x41903[4568]] = s[_x41903[4568]], t[_x41903[4569]] = s[_x41903[4569]], t[_x41903[4570]] = s[_x41903[4570]], t[_x41903[4571]] = s[_x41903[4571]], t[_x41903[4572]] = s[_x41903[4572]]); }), publicFun[_x41903[3948]](l[_x41903[820]], l[_x41903[4500]], l[_x41903[4520]])) : (l[_x41903[4519]][_x41903[4559]] = s[_x41903[124]], l[_x41903[4519]][_x41903[184]] = s[_x41903[184]], - l[_x41903[4519]][_x41903[4560]] = s[_x41903[4560]], - l[_x41903[4519]][_x41903[2345]] = s[_x41903[2345]], + l[_x41903[4519]][_x41903[4560]] = s[_x41903[4560]], + l.listType==1? l[_x41903[4519]][_x41903[2345]] = s[_x41903[2345]]: "", l[_x41903[4519]][_x41903[4561]] = s[_x41903[4561]], l[_x41903[4519]][_x41903[4562]] = s[_x41903[4562]], l[_x41903[4519]][_x41903[4563]] = s[_x41903[184]], diff --git a/mall-shop/src/main/resources/templates/diy.html b/mall-shop/src/main/resources/templates/diy.html index 548e0a82..65d9fdcb 100644 --- a/mall-shop/src/main/resources/templates/diy.html +++ b/mall-shop/src/main/resources/templates/diy.html @@ -1827,7 +1827,7 @@
      + v-if="listType==2 || listType==5 || listType==6 || listType==8 || listType==10 || listType==11">
    • @@ -1842,7 +1842,7 @@
      + v-if="listType==1|| listType==104">
    • Date: Sat, 13 Dec 2025 21:27:05 +0800 Subject: [PATCH 26/28] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=AE=A2=E5=8D=95?= =?UTF-8?q?=E5=8E=9F=E5=95=86=E5=93=81=E4=BB=B7=E6=A0=BC=E7=9A=84=E9=94=99?= =?UTF-8?q?=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../impl/ShopOrderBaseServiceImpl.java | 4 +- .../impl/ShopOrderReturnServiceImpl.java | 43 +++++++++++-------- 2 files changed, 29 insertions(+), 18 deletions(-) diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/order/service/impl/ShopOrderBaseServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/order/service/impl/ShopOrderBaseServiceImpl.java index 6aa797a0..c773836e 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/order/service/impl/ShopOrderBaseServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/order/service/impl/ShopOrderBaseServiceImpl.java @@ -6610,7 +6610,8 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl 0) { - log.debug("[是否禁止退货] 订单已超过退货期限,禁止退货,order_id: {}, orderDealTime: {}, withdrawTime: {}", + log.info("[是否禁止退货] 订单已超过退货期限,禁止退货,order_id: {}, orderDealTime: {}, withdrawTime: {}", orderId, orderDealTime, withdrawTime); return true; } } catch (Exception e) { - log.error("[是否禁止退货] 检查订单退货期限时发生异常,禁止退货,order_id: {}", orderId, e); + log.info("[是否禁止退货] 检查订单退货期限时发生异常,禁止退货,order_id: {}", orderId, e); return true; } } @@ -2533,19 +2533,19 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl contractTypeIds = Convert.toList(Integer.class, contractTypeIdsStr); if (contractTypeIds != null && contractTypeIds.contains(StateCode.CONTRACT_TYPE_DENY_RETURN)) { - log.debug("[是否禁止退货] 商品设置了禁止退货标识,禁止退货,order_id: {}, product_id: {}", orderId, productIndex.getProduct_id()); + log.info("[是否禁止退货] 商品设置了禁止退货标识,禁止退货,order_id: {}, product_id: {}", orderId, productIndex.getProduct_id()); return true; } } catch (Exception e) { @@ -2581,13 +2581,13 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl 0 - // 2. 可退金额 > 0 - return orderItemQuantity > orderItemReturnNum - && orderItemAmount.compareTo(orderItemReturnAgreeAmount) > 0; + // 1. 可退数量 > 0 (订单商品数量 > 已退货数量) + boolean canReturnQuantity = orderItemQuantity > orderItemReturnNum; + // 2. 可退金额 > 0 (订单商品金额 > 已同意退款金额) + boolean canReturnAmount = orderItemAmount.compareTo(orderItemReturnAgreeAmount) > 0; + + log.info("退款条件检查结果 - 可退数量: {}, 可退金额: {}", canReturnQuantity, canReturnAmount); + + return canReturnQuantity && canReturnAmount; } From 74ba36ebd6fbd671b99f7248b890071b54f7556e Mon Sep 17 00:00:00 2001 From: liyj <1617420630@qq.com> Date: Mon, 15 Dec 2025 10:56:42 +0800 Subject: [PATCH 27/28] =?UTF-8?q?=E8=A3=85=E4=BF=AE=E6=A8=A1=E6=9D=BF?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E5=BC=82=E5=B8=B8=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../shop/page/service/impl/ShopPageAppServiceImpl.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/page/service/impl/ShopPageAppServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/page/service/impl/ShopPageAppServiceImpl.java index 4cee4e73..51cbe017 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/page/service/impl/ShopPageAppServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/page/service/impl/ShopPageAppServiceImpl.java @@ -1082,13 +1082,16 @@ public class ShopPageAppServiceImpl extends BaseServiceImpl queryWrapperShopBase = new QueryWrapper<>(); queryWrapperShopBase.eq("app_id", appId); From 7938cad0ccfec3ff332f87a0491cb396700260fe Mon Sep 17 00:00:00 2001 From: liyj <1617420630@qq.com> Date: Mon, 15 Dec 2025 16:19:38 +0800 Subject: [PATCH 28/28] =?UTF-8?q?=E6=8E=A7=E5=88=B6=EF=BC=8C=E6=9C=AA?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E7=9A=84=E6=A8=A1=E6=9D=BF=E5=8F=91=E5=B8=83?= =?UTF-8?q?=EF=BC=8C=E9=98=B2=E6=AD=A2=E6=9F=A5=E8=AF=A2=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mall/shop/page/controller/admin/ShopPageAppController.java | 1 + 1 file changed, 1 insertion(+) diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/page/controller/admin/ShopPageAppController.java b/mall-shop/src/main/java/com/suisung/mall/shop/page/controller/admin/ShopPageAppController.java index 00618d98..88f0ae86 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/page/controller/admin/ShopPageAppController.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/page/controller/admin/ShopPageAppController.java @@ -463,6 +463,7 @@ public class ShopPageAppController extends BaseControllerImpl { return CommonResult.failed("不存在模板"); } String storeId= user.getStore_id(); + shopPageApp.setApp_is_use(0); if(user.isPlatform()){ shopPageApp.setIs_pulish(isPublish); shopPageAppService.edit(shopPageApp);