Compare commits

30 Commits

Author SHA1 Message Date
87dd4cc3ba 条件开通 2025-12-25 19:27:39 +08:00
5df01f5192 订单 累计 2025-12-25 18:40:12 +08:00
3b83d210dc 订单 统计 2025-12-25 18:29:21 +08:00
d70546f55e 更新会员成长值 不对
订单退款 全额 部分 问题
2025-12-25 18:02:31 +08:00
c6102dd4b4 消费返现
充值触发条件成为会员
霸王餐触发条件成为会员
2025-12-25 17:18:46 +08:00
gong
f374c335c4 transactionSafeRun 2025-12-25 17:04:42 +08:00
b171b1a81f 订单 退款 问题 2025-12-25 16:28:19 +08:00
0b5ec53187 空值问题 2025-12-25 15:46:09 +08:00
ec59490f3a 会员 问题 2025-12-25 15:02:57 +08:00
7d434ff5c7 开通 问题 2025-12-25 14:37:11 +08:00
ef48e4e51d 开通 问题 2025-12-25 14:22:28 +08:00
5cb895ac19 数签子 2025-12-25 14:06:43 +08:00
e125eed517 会员 条件开通 2025-12-25 14:06:31 +08:00
gong
621bf2401d 管理端获取商品详情接口 2025-12-25 11:46:14 +08:00
bae1762dba ocr 数签子
登录更新了用户名称的问题
更新用户信息的问题
2025-12-25 11:18:14 +08:00
gong
22a5ae8f68 删除测试方法 2025-12-24 17:43:53 +08:00
gong
ae65bf1814 小程序商品返回相关推荐 2025-12-24 17:42:08 +08:00
gong
b1215acca5 apifox 归类注释 2025-12-24 15:31:52 +08:00
gong
a6dd4f4611 添加商品关联推荐 2025-12-24 15:23:02 +08:00
506e74747a 问题 2025-12-24 14:55:12 +08:00
72c9379e87 Merge branch 'prod' into test 2025-12-24 14:52:16 +08:00
a8bcf991fe 显式抛出 2025-12-24 14:03:38 +08:00
240d672211 sysParam 获取值问题 2025-12-24 13:57:40 +08:00
gong
302504b891 Merge remote-tracking branch 'origin/test' into test 2025-12-23 16:07:32 +08:00
gong
a76c3f75a4 分页总数量为 -1 的情况2 2025-12-23 16:07:27 +08:00
a05d8083bc 返回默认值 2025-12-23 16:03:09 +08:00
ed1b6b2ecf Merge remote-tracking branch 'origin/test' into test 2025-12-23 15:34:11 +08:00
7c9c6d6a02 菜单问题 2025-12-23 15:33:30 +08:00
gong
658c7f14b2 分页总数量为 -1 的情况 2025-12-23 15:15:42 +08:00
8635c42506 用户列表 1 2025-12-23 14:23:58 +08:00
86 changed files with 1545 additions and 815 deletions

1
.gitignore vendored
View File

@@ -61,3 +61,4 @@ build/
/cash-api/product-server/src/main/resources/application-zs.yml /cash-api/product-server/src/main/resources/application-zs.yml
/cash-api/system-server/src/main/resources/application-zs.yml /cash-api/system-server/src/main/resources/application-zs.yml
/cash-service/code-generator/src/main/java/com/czg/Main.java /cash-service/code-generator/src/main/java/com/czg/Main.java
/cash-api/product-server/logs/

View File

@@ -147,32 +147,4 @@ public class NotifyController {
} }
return resultMap; return resultMap;
} }
public static void main(String[] args) {
String str = "<xml><ToUserName><![CDATA[gh_11fc27b7ef34]]></ToUserName><FromUserName><![CDATA[owWHW7Tzeh2gx3WmFsFSxBq2JUTk]]></FromUserName><CreateTime>1761095747</CreateTime><MsgType><![CDATA[event]]></MsgType><Event><![CDATA[subscribe]]></Event><EventKey><![CDATA[qrscene_275]]></EventKey><Ticket><![CDATA[gQGF8DwAAAAAAAAAAS5odHRwOi8vd2VpeGluLnFxLmNvbS9xLzAyUTZDVHRTMXhmbUoxYUlYdk5GY2sAAgSsLvhoAwQAjScA]]></Ticket></xml>";
// 2. 解析 XML 为 Map便于获取字段
Map<String, String> messageMap = new HashMap<>();
try {
messageMap = parseXmlToMap(str);
} catch (DocumentException e) {
log.error("XML 解析失败,", e);
}
log.info("微信 POST 消息内容: {}", messageMap);
//携带参数
String eventKey = messageMap.get("EventKey");
Long userId = null;
if (eventKey != null && eventKey.startsWith("qrscene_")) {
try {
// 截取 "qrscene_" 前缀后的字符串(长度为 8并转为 Long
String numberStr = eventKey.substring("qrscene_".length());
userId = Long.parseLong(numberStr);
} catch (NumberFormatException e) {
log.error("EventKey 后缀不是有效数字eventKey: {}", eventKey, e);
}
}
System.out.println("userId: " + userId);
}
} }

View File

@@ -13,7 +13,7 @@ import org.springframework.web.bind.annotation.RestController;
* @author GYJoker * @author GYJoker
*/ */
@RestController @RestController
@RequestMapping("/test") @RequestMapping("/notify/test")
public class TestController { public class TestController {
@Resource @Resource
private ShopUserFlowService shopUserFlowService; private ShopUserFlowService shopUserFlowService;

View File

@@ -24,6 +24,7 @@ import java.util.Map;
/** /**
* 会员配置管理 * 会员配置管理
* @author ww
*/ */
@RestController @RestController

View File

@@ -89,6 +89,14 @@ public class PpPackageController {
return CzgResult.success(ppPackageService.getPackagePage(reqVo, true)); return CzgResult.success(ppPackageService.getPackagePage(reqVo, true));
} }
/**
* 获取套餐详情
*/
@GetMapping("/detail/{id}")
public CzgResult<PpPackageVO> getPackageDetail(@PathVariable Long id, Long shopId) {
return CzgResult.success(ppPackageService.getPackageDetail(id, shopId));
}
/** /**
* 获取套餐推广开关 * 获取套餐推广开关
* 0: 关闭 1: 开启 * 0: 关闭 1: 开启

View File

@@ -1,7 +1,6 @@
package com.czg.controller.admin; package com.czg.controller.admin;
import com.czg.market.dto.MkShopRechargeDTO; import com.czg.market.dto.MkShopRechargeDTO;
import com.czg.market.entity.MkShopConsumeDiscountRecord;
import com.czg.market.entity.MkShopRechargeFlow; import com.czg.market.entity.MkShopRechargeFlow;
import com.czg.market.service.MkRechargeFlowService; import com.czg.market.service.MkRechargeFlowService;
import com.czg.market.service.MkShopConsumeDiscountRecordService; import com.czg.market.service.MkShopConsumeDiscountRecordService;
@@ -30,12 +29,6 @@ public class ShopRechargeController {
@Resource @Resource
private MkShopConsumeDiscountRecordService shopConsumeDiscountRecordService; private MkShopConsumeDiscountRecordService shopConsumeDiscountRecordService;
@GetMapping("/test")
public CzgResult<MkShopConsumeDiscountRecord> get(@RequestParam Long shopId) {
// return CzgResult.success(shopConsumeDiscountRecordService.get(shopId));
return null;
}
/** /**
* 配置信息获取 * 配置信息获取
* 权限标识: activate:list * 权限标识: activate:list

View File

@@ -4,7 +4,6 @@ import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil; import cn.hutool.core.io.IoUtil;
import com.alibaba.fastjson2.JSONObject; import com.alibaba.fastjson2.JSONObject;
import com.czg.CzgPayUtils; import com.czg.CzgPayUtils;
import com.czg.account.service.ShopUserService;
import com.czg.constants.PayTypeConstants; import com.czg.constants.PayTypeConstants;
import com.czg.entity.CzgBaseRespParams; import com.czg.entity.CzgBaseRespParams;
import com.czg.market.entity.MkShopConsumeDiscountRecord; import com.czg.market.entity.MkShopConsumeDiscountRecord;
@@ -38,10 +37,6 @@ import java.io.IOException;
@RequestMapping("/notify") @RequestMapping("/notify")
public class NotifyController { public class NotifyController {
private static final String SUCCESS = "SUCCESS"; private static final String SUCCESS = "SUCCESS";
@Resource
private ShopUserService shopUserService;
@Resource @Resource
private OrderInfoCustomService orderInfoCustomService; private OrderInfoCustomService orderInfoCustomService;
@Resource @Resource

View File

@@ -8,6 +8,7 @@ import com.czg.market.service.GbWareService;
import com.czg.order.dto.GbOrderQueryParam; import com.czg.order.dto.GbOrderQueryParam;
import com.czg.order.service.GbOrderService; import com.czg.order.service.GbOrderService;
import com.czg.order.vo.GbOrderCountVO; import com.czg.order.vo.GbOrderCountVO;
import com.czg.order.vo.GbWareVO;
import com.czg.resp.CzgResult; import com.czg.resp.CzgResult;
import com.czg.sa.StpKit; import com.czg.sa.StpKit;
import com.czg.utils.AssertUtil; import com.czg.utils.AssertUtil;
@@ -87,4 +88,12 @@ public class GbWareController {
AssertUtil.isNull(id, "操作失败,请选择商品"); AssertUtil.isNull(id, "操作失败,请选择商品");
return CzgResult.success(wareService.deleteGbWare(id)); return CzgResult.success(wareService.deleteGbWare(id));
} }
/**
* 拼团商品详情
*/
@GetMapping("/ware/detail")
public CzgResult<GbWareVO> getWareDetail(@RequestParam Long shopId, @RequestParam Long wareId) {
return CzgResult.success(gbOrderService.getWareDetail(shopId, wareId, null));
}
} }

View File

@@ -5,6 +5,7 @@ import cn.hutool.core.util.URLUtil;
import com.czg.log.annotation.OperationLog; import com.czg.log.annotation.OperationLog;
import com.czg.product.dto.ConsStockFlowDTO; import com.czg.product.dto.ConsStockFlowDTO;
import com.czg.product.dto.OcrDTO; import com.czg.product.dto.OcrDTO;
import com.czg.product.entity.MkOcrService;
import com.czg.product.param.ConsCheckStockParam; import com.czg.product.param.ConsCheckStockParam;
import com.czg.product.param.ConsInOutStockHeadParam; import com.czg.product.param.ConsInOutStockHeadParam;
import com.czg.product.param.ConsReportDamageParam; import com.czg.product.param.ConsReportDamageParam;
@@ -37,6 +38,8 @@ public class ConsStockFlowController {
@Resource @Resource
private ConsStockFlowService consStockFlowService; private ConsStockFlowService consStockFlowService;
@Resource
private MkOcrService ocrService;
/** /**
* 入库单识别 * 入库单识别
@@ -46,17 +49,18 @@ public class ConsStockFlowController {
URI uri = new URI(ocrDTO.getUrl()); URI uri = new URI(ocrDTO.getUrl());
URL url = uri.toURL(); URL url = uri.toURL();
InputStream stream = URLUtil.getStream(url); InputStream stream = URLUtil.getStream(url);
return CzgResult.success(consStockFlowService.ocr(FileUtil.getName(ocrDTO.getUrl()), stream)); return CzgResult.success(ocrService.ocr(FileUtil.getName(ocrDTO.getUrl()), stream, "cons"));
} }
/** /**
* ocr识别结果 * ocr识别结果
*
* @param id ocrId * @param id ocrId
* @return 识别结果 * @return 识别结果
*/ */
@GetMapping("/ocrResult") @GetMapping("/ocrResult")
public CzgResult<ConsInOutStockHeadParam> ocrResult(@RequestParam Long id) { public CzgResult<ConsInOutStockHeadParam> ocrResult(@RequestParam Long id) {
return CzgResult.success(consStockFlowService.ocrDetail(id)); return CzgResult.success(ocrService.ocrDetail(id));
} }

View File

@@ -33,7 +33,7 @@ import java.util.List;
/** /**
* 商品管理 - 商品列表 * 管理端/商品管理 - 商品列表
* *
* @author Tankaikai tankaikai@aliyun.com * @author Tankaikai tankaikai@aliyun.com
* @since 1.0 2025-02-16 * @since 1.0 2025-02-16

View File

@@ -0,0 +1,38 @@
package com.czg.controller.admin;
import com.czg.product.service.MkOcrCountStickService;
import com.czg.resp.CzgResult;
import com.czg.utils.AssertUtil;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
/**
* 拍照数签子
* @author ww
*/
@RestController
@RequestMapping("/admin/stick")
public class StickCountController {
@Resource
private MkOcrCountStickService stickCountService;
/**
* 文件上传并返回点数统计结果
*
* @param file 上传的图片文件
* @return 点数统计结果
*/
@PostMapping("/count")
public CzgResult<Integer> uploadAndCount(MultipartFile file) throws IOException {
AssertUtil.isNull(file, "上传文件不能为空");
// 9. 返回成功结果
return CzgResult.success(stickCountService.getCountStick(file.getBytes(), file.getOriginalFilename()));
}
}

View File

@@ -9,7 +9,6 @@ import com.czg.product.vo.ShopProductSkuInfoVo;
import com.czg.product.vo.ShopProductVo; import com.czg.product.vo.ShopProductVo;
import com.czg.resp.CzgResult; import com.czg.resp.CzgResult;
import com.czg.sa.StpKit; import com.czg.sa.StpKit;
import com.czg.service.RedisService;
import com.czg.utils.AssertUtil; import com.czg.utils.AssertUtil;
import com.czg.validator.ValidatorUtil; import com.czg.validator.ValidatorUtil;
import com.czg.validator.group.DefaultGroup; import com.czg.validator.group.DefaultGroup;
@@ -24,7 +23,7 @@ import java.util.Map;
/** /**
* 店铺商品 * 用户端/店铺商品
* *
* @author Tankaikai tankaikai@aliyun.com * @author Tankaikai tankaikai@aliyun.com
* @since 1.0 2025-02-16 * @since 1.0 2025-02-16
@@ -34,7 +33,6 @@ import java.util.Map;
@RequestMapping("/user/product") @RequestMapping("/user/product")
public class UProductController { public class UProductController {
private final UProductService uProductService; private final UProductService uProductService;
private final RedisService redisService;
/** /**
* 小程序点餐-热销商品列表 * 小程序点餐-热销商品列表

View File

@@ -0,0 +1,33 @@
package com.czg.service;
import com.alibaba.fastjson2.JSONObject;
import com.czg.product.dto.ProductDTO;
import com.czg.product.service.ProductService;
import com.czg.product.service.UProductService;
import com.czg.product.vo.ShopGroupProductVo;
import com.czg.product.vo.ShopProductVo;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
/**
* @author yjjie
* @date 2025/12/24 13:36
*/
@SpringBootTest
public class ProductTest {
@Resource
private ProductService productService;
@Resource
private UProductService uProductService;
@Test
public void testGetById() {
// ProductDTO product = productService.getProductById(169L);
// System.out.println(JSONObject.toJSONString( product));
}
}

View File

@@ -14,6 +14,8 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set;
/** /**
* @author GYJoker * @author GYJoker
@@ -94,18 +96,19 @@ public class VersionController {
@GetMapping(value = "/getCredentials") @GetMapping(value = "/getCredentials")
public CzgResult<Object> getCredentials() { public CzgResult<Object> getCredentials() {
try { try {
Map<String, String> ossKeyMap = paramsService.getParamsByMap("ossKeySet", ParamCodeCst.OSS_KEY_SET);
com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config() com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
// 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID。 // 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID。
.setAccessKeyId(paramsService.getSysParamValue(ParamCodeCst.AliYun.ALI_OSS_ACCESS_KEY)) .setAccessKeyId(ossKeyMap.get(ParamCodeCst.AliYun.ALI_OSS_ACCESS_KEY))
// 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_SECRET。 // 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_SECRET。
.setAccessKeySecret(paramsService.getSysParamValue(ParamCodeCst.AliYun.ALI_OSS_ACCESS_SECRET)); .setAccessKeySecret(ossKeyMap.get(ParamCodeCst.AliYun.ALI_OSS_ACCESS_SECRET));
// Endpoint 请参考 https://api.aliyun.com/product/Sts // Endpoint 请参考 https://api.aliyun.com/product/Sts
config.endpoint = paramsService.getSysParamValue(ParamCodeCst.AliYun.ALI_OSS_ENDPOINT); config.endpoint = ossKeyMap.get(ParamCodeCst.AliYun.ALI_OSS_ENDPOINT);
com.aliyun.sts20150401.Client client = new com.aliyun.sts20150401.Client(config); com.aliyun.sts20150401.Client client = new com.aliyun.sts20150401.Client(config);
com.aliyun.sts20150401.models.AssumeRoleRequest assumeRoleRequest = new com.aliyun.sts20150401.models.AssumeRoleRequest(); com.aliyun.sts20150401.models.AssumeRoleRequest assumeRoleRequest = new com.aliyun.sts20150401.models.AssumeRoleRequest();
assumeRoleRequest.setRoleArn(paramsService.getSysParamValue(ParamCodeCst.AliYun.ALI_OSS_ROLE_ARN)); assumeRoleRequest.setRoleArn(ossKeyMap.get(ParamCodeCst.AliYun.ALI_OSS_ROLE_ARN));
assumeRoleRequest.setRoleSessionName("test"); assumeRoleRequest.setRoleSessionName("test");
com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions(); com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
// 复制代码运行请自行打印 API 的返回值 // 复制代码运行请自行打印 API 的返回值

View File

@@ -26,6 +26,7 @@ public class FilteredNacosRegistry extends NacosRegistry {
"removeByMap", "removeByMap",
"getByIdOpt", "getByIdOpt",
"getOneOpt", "getOneOpt",
"getOneAs",
"getObjOpt", "getObjOpt",
"getObjAs", "getObjAs",
"getObjAsOpt", "getObjAsOpt",

View File

@@ -133,6 +133,7 @@ public class RabbitPublisher {
/** /**
* 订单商品状态消息 * 订单商品状态消息
* type bc 广播
*/ */
public void sendOrderDetailStatusMsg(String shopId, String type) { public void sendOrderDetailStatusMsg(String shopId, String type) {
sendMsg(RabbitConstants.Queue.ORDER_DETAIL_STATUS_QUEUE, JSONObject.toJSONString(Map.of( sendMsg(RabbitConstants.Queue.ORDER_DETAIL_STATUS_QUEUE, JSONObject.toJSONString(Map.of(

View File

@@ -280,5 +280,9 @@ public class ShopInfoEditDTO {
* 上菜时间 分钟 * 上菜时间 分钟
*/ */
private Integer serveTime; private Integer serveTime;
/**
* 数签子
*/
private Integer isCountStick;
} }

View File

@@ -27,5 +27,6 @@ public class ShopUserDTO extends ShopUser {
private String memberLevelName; private String memberLevelName;
private String nextMemberLevelName; private String nextMemberLevelName;
private Long nextExperience; private Long nextExperience;
private Long pointBalance;
private boolean isNew; private boolean isNew;
} }

View File

@@ -127,6 +127,10 @@ public class ShopConfig implements Serializable {
* 套餐推广 开关 * 套餐推广 开关
*/ */
private Integer isPackagePromotion; private Integer isPackagePromotion;
/**
* 数签子
*/
private Integer isCountStick;
private String dingAppKey; private String dingAppKey;

View File

@@ -352,6 +352,11 @@ public class ShopInfo implements Serializable {
private Integer serveTime; private Integer serveTime;
@Column(ignore = true) @Column(ignore = true)
private Integer isGroupBuy; private Integer isGroupBuy;
/**
* 数签子
*/
@Column(ignore = true)
private Integer isCountStick;
/** /**
* 运营端余额 * 运营端余额

View File

@@ -1,5 +1,7 @@
package com.czg.constants; package com.czg.constants;
import java.util.Set;
/** /**
* 系统参数编码常量类 * 系统参数编码常量类
* *
@@ -9,6 +11,65 @@ package com.czg.constants;
*/ */
public interface ParamCodeCst { public interface ParamCodeCst {
/**
* 用户小程序参数
*/
Set<String> USER_MINI_KEY_SET = Set.of(Wechat.Mini.USER_WX_APP_ID, Wechat.Mini.USER_WX_SECRETE);
/**
* 商家小程序参数
*/
Set<String> SHOP_MINI_KEY_SET = Set.of(Wechat.Mini.SHOP_WX_APP_ID, Wechat.Mini.SHOP_WX_SECRETE);
/**
* 商家公众号参数 推送 库存不足等消息
*/
Set<String> SHOP_AC_KEY_SET = Set.of(Wechat.Ac.SHOP_WX_AC_APP_ID, Wechat.Ac.SHOP_WX_AC_SECRETE);
/**
* 用户公众号参数 推送商家模板消息
*/
Set<String> USER_AC_KEY_SET = Set.of(Wechat.Ac.USER_WX_AC_APP_ID, Wechat.Ac.USER_WX_AC_SECRETE);
/**
* 微信支付参数KEY
*/
Set<String> PAY_KEY_SET = Set.of(
Wechat.Pay.WX_PUB_KEY,
Wechat.Pay.WX_API_CLIENT_KEY,
Wechat.Pay.WX_API_CLIENT_CERT,
Wechat.Pay.WX_MCH_ID,
Wechat.Pay.WX_V3_KEY,
System.NATIVE_NOTIFY_URL
);
/**
* 支付宝参数KEY
*/
Set<String> ALI_PAY_KEY_SET = Set.of(
Alipay.Web.ALI_GATEWAY,
Alipay.Mini.ALI_MINI_APP_ID,
Alipay.Mini.ALI_MINI_PRIVATE_KEY,
Alipay.Mini.ALI_MINI_PUBLIC_KEY,
Alipay.Web.ALI_ACCOUNT_APP_ID,
Alipay.Web.ALI_ACCOUNT_PRIVATE_KEY,
Alipay.Web.ALI_ACCOUNT_PUBLIC_KEY
);
/**
* 阿里云OSS参数KEY
*/
Set<String> ALI_OSS_KEY_SET = Set.of(
ParamCodeCst.AliYun.ALI_SMS_KEY,
ParamCodeCst.AliYun.ALI_SMS_SECRET,
ParamCodeCst.AliYun.ALI_SMS_TEMPLATE_CODE
);
/**
* 阿里云临时凭证
*/
Set<String> OSS_KEY_SET = Set.of(AliYun.ALI_OSS_ACCESS_KEY, AliYun.ALI_OSS_ACCESS_SECRET, AliYun.ALI_OSS_ENDPOINT, AliYun.ALI_OSS_ROLE_ARN);
/** /**
* 系统通用配置项 * 系统通用配置项
* <p>存放跨业务模块的通用系统配置</p> * <p>存放跨业务模块的通用系统配置</p>

View File

@@ -21,6 +21,7 @@ public interface MkConsumeCashbackService extends IService<MkConsumeCashback> {
/** /**
* 消费返现 * 消费返现
*
* @param shopId 店铺id * @param shopId 店铺id
* @param userId 用户id * @param userId 用户id
* @param amount 金额 * @param amount 金额
@@ -28,4 +29,9 @@ public interface MkConsumeCashbackService extends IService<MkConsumeCashback> {
* @param orderNo 订单号 * @param orderNo 订单号
*/ */
void cashback(Long shopId, Long userId, BigDecimal amount, Long orderId, String orderNo); void cashback(Long shopId, Long userId, BigDecimal amount, Long orderId, String orderNo);
/**
* 订单退款 删除返现
*/
void removeCashback(Long shopId, Long userId, Long orderId, String orderNo);
} }

View File

@@ -17,4 +17,9 @@ public interface MkPointsConfigService extends IService<MkPointsConfig> {
* *
*/ */
void consumeAwardPoints(ShopUser shopUser, OrderInfo orderInfo); void consumeAwardPoints(ShopUser shopUser, OrderInfo orderInfo);
/**
* 订单退款成功,通过计算 给用户赠送积分
*/
void removeConsumeAwardPoints(Long shopId, Long userId, Long orderId, String orderNo);
} }

View File

@@ -48,4 +48,9 @@ public interface MkPointsUserService extends IService<MkPointsUser> {
*/ */
Long alterPoints(Long userId, Long shopUserId, @NotNull Long shopId, @NotNull PointsConstant floatType, Long alterPoints(Long userId, Long shopUserId, @NotNull Long shopId, @NotNull PointsConstant floatType,
@NotNull Integer points, Long sourceId, @NotBlank String reason); @NotNull Integer points, Long sourceId, @NotBlank String reason);
/**
* 订单退款 赠送的积分 扣除
*/
void removePointByOrder(Long shopId, Long userId, Long orderId, String orderNo, String reason);
} }

View File

@@ -22,6 +22,12 @@ public interface MkShopConsumerCouponService extends IService<MkShopConsumerCoup
*/ */
void receiveConsumerCoupon(Long shopId, Long orderId, BigDecimal orderAmount, Long userId, Long shopUserId); void receiveConsumerCoupon(Long shopId, Long orderId, BigDecimal orderAmount, Long userId, Long shopUserId);
/**
* 订单退款 移除消费赠券
*
*/
void removeConsumerCoupon(Long shopId, Long userId, Long orderId);
MkShopConsumerCouponDTO getConsumerCouponById(Long id); MkShopConsumerCouponDTO getConsumerCouponById(Long id);
void addConsumerCoupon(MkShopConsumerCouponDTO param); void addConsumerCoupon(MkShopConsumerCouponDTO param);

View File

@@ -22,13 +22,19 @@ import java.util.List;
public interface MkShopRechargeService extends IService<MkShopRecharge> { public interface MkShopRechargeService extends IService<MkShopRecharge> {
MkShopRechargeVO detail(Long shopId); MkShopRechargeVO detail(Long shopId);
MkShopRechargeVO detailApp(Long shopId); MkShopRechargeVO detailApp(Long shopId);
Boolean edit(Long shopId, MkShopRechargeDTO shopRechargeDTO); Boolean edit(Long shopId, MkShopRechargeDTO shopRechargeDTO);
BigDecimal checkRecharge(Long mainShopId, @NotNull(message = "店铺不能为空") Long shopId, Long userId, Long rechargeDetailId, @DecimalMin("0.01") BigDecimal money); BigDecimal checkRecharge(Long mainShopId, @NotNull(message = "店铺不能为空") Long shopId, Long userId, Long rechargeDetailId, @DecimalMin("0.01") BigDecimal money);
void recharge(Long shopId, Long shopUserId, Long rechargeDetailId, BigDecimal amount, Long paymentId, String payType, ShopUserFlowBizEnum bizEnum); /**
* 充值
* @param isNoJoin 是否没有执行 加入会员的方法
* 会员如果是条件开通 则 需要统计
*/
void recharge(Long shopId, Long shopUserId, Long rechargeDetailId, BigDecimal amount, Long paymentId, String payType, ShopUserFlowBizEnum bizEnum, boolean isNoJoin);
List<RechargeListVO> getList(long loginIdAsLong); List<RechargeListVO> getList(long loginIdAsLong);

View File

@@ -1,12 +1,14 @@
package com.czg.order.dto; package com.czg.order.dto;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode;
/** /**
* 拼团参与 DTO * 拼团参与 DTO
* *
* @author ww * @author ww
*/ */
@EqualsAndHashCode(callSuper = true)
@Data @Data
public class GroupJoinDTO extends LtPayOtherDTO{ public class GroupJoinDTO extends LtPayOtherDTO{
/** /**

View File

@@ -1,20 +0,0 @@
package com.czg.order.dto;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.math.BigDecimal;
/**
* 积分商品兑换信息
*
* @author ww
*/
@Data
public class PointGoodsExchangeDTO extends LtPayOtherDTO{
/**
* 积分商品id
*/
@NotNull(message = "积分商品不能为空")
private Long pointsGoodsId;
}

View File

@@ -3,6 +3,8 @@ package com.czg.order.service;
import com.mybatisflex.core.service.IService; import com.mybatisflex.core.service.IService;
import com.czg.order.entity.OrderPayment; import com.czg.order.entity.OrderPayment;
import java.math.BigDecimal;
/** /**
* 支付详情 服务层。 * 支付详情 服务层。
* *
@@ -11,4 +13,5 @@ import com.czg.order.entity.OrderPayment;
*/ */
public interface OrderPaymentService extends IService<OrderPayment> { public interface OrderPaymentService extends IService<OrderPayment> {
BigDecimal countMemberInAmount(Long shopId, Long shopUserId);
} }

View File

@@ -1,12 +1,15 @@
package com.czg.product.dto; package com.czg.product.dto;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert; import cn.hutool.core.convert.Convert;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.annotation.JSONField; import com.alibaba.fastjson2.annotation.JSONField;
import com.czg.product.vo.ProductGroupVo; import com.czg.product.vo.ProductGroupVo;
import com.czg.validator.group.DefaultGroup; import com.czg.validator.group.DefaultGroup;
import com.czg.validator.group.InsertGroup; import com.czg.validator.group.InsertGroup;
import com.czg.validator.group.UpdateGroup; import com.czg.validator.group.UpdateGroup;
import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.validation.constraints.*; import jakarta.validation.constraints.*;
import lombok.Data; import lombok.Data;
@@ -235,6 +238,12 @@ public class ProductDTO implements Serializable {
* 是否可售时间 1-是 0-否 * 是否可售时间 1-是 0-否
*/ */
private Integer isSaleTime; private Integer isSaleTime;
/**
* 相关推荐商品
*/
private List<RelatedProductDTO> relatedRecommendJson;
@JsonIgnore
private String relatedRecommend;
public Object getImages() { public Object getImages() {
return JSON.parseArray(Convert.toStr(images, "[]")); return JSON.parseArray(Convert.toStr(images, "[]"));
@@ -250,4 +259,16 @@ public class ProductDTO implements Serializable {
public Object getGroupSnap() { public Object getGroupSnap() {
return JSON.parseArray(Convert.toStr(groupSnap, "[]")); return JSON.parseArray(Convert.toStr(groupSnap, "[]"));
} }
public String getRelatedRecommendStr() {
if (CollUtil.isNotEmpty(relatedRecommendJson)) {
JSONArray array = new JSONArray();
for (RelatedProductDTO relatedProductDTO : relatedRecommendJson) {
array.add(relatedProductDTO.getId());
}
return array.toJSONString();
}
return "[]";
}
} }

View File

@@ -0,0 +1,31 @@
package com.czg.product.dto;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 相关推荐 商品 DTO
*
* @author yjjie
* @date 2025/12/24 13:34
*/
@Data
public class RelatedProductDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 商品 ID
*/
private Long id;
/**
* 商品名称
*/
private String name;
/**
* 商品图片
*/
private String coverImg;
}

View File

@@ -0,0 +1,58 @@
package com.czg.product.entity;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.Table;
import java.io.Serializable;
import java.io.Serial;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 数签子的外链渠道 实体类。
*
* @author ww
* @since 2025-12-24
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table("mk_ocr_count_stick")
public class MkOcrCountStick implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Id
private Long id;
/**
* 渠道名称
*/
private String name;
/**
* 标记
*/
private String mark;
/**
* 地址
*/
private String url;
/**
* 状态 0/1
*/
private Integer status;
private Integer sort;
private String token;
private String account;
private String pwd;
}

View File

@@ -1,8 +1,11 @@
package com.czg.product.entity; package com.czg.product.entity;
import com.czg.product.param.ConsInOutStockHeadParam;
import com.mybatisflex.core.service.IService; import com.mybatisflex.core.service.IService;
import com.czg.market.entity.MkOcr; import com.czg.market.entity.MkOcr;
import java.io.InputStream;
/** /**
* ocr识别结果 服务层。 * ocr识别结果 服务层。
* *
@@ -11,4 +14,7 @@ import com.czg.market.entity.MkOcr;
*/ */
public interface MkOcrService extends IService<MkOcr> { public interface MkOcrService extends IService<MkOcr> {
ConsInOutStockHeadParam ocrDetail(Long id);
Integer ocr(String originalFilename, InputStream inputStream, String type);
} }

View File

@@ -142,6 +142,10 @@ public class Product implements Serializable {
* 退款是否退回库存 * 退款是否退回库存
*/ */
private Integer isRefundStock; private Integer isRefundStock;
/**
* 相关推荐
*/
private String relatedRecommend;
/** /**
* 创建时间 * 创建时间
*/ */

View File

@@ -10,7 +10,6 @@ import com.czg.product.vo.ConsCheckStockRecordVo;
import com.mybatisflex.core.paginate.Page; import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.service.IService; import com.mybatisflex.core.service.IService;
import java.io.InputStream;
import java.util.List; import java.util.List;
/** /**
@@ -25,7 +24,6 @@ public interface ConsStockFlowService extends IService<ConsStockFlow> {
* 手动入库 * 手动入库
* *
* @param param 手动出库入参 * @param param 手动出库入参
* @return
*/ */
ConsInOutStockHeadParam inStock(ConsInOutStockHeadParam param); ConsInOutStockHeadParam inStock(ConsInOutStockHeadParam param);
@@ -78,8 +76,4 @@ public interface ConsStockFlowService extends IService<ConsStockFlow> {
* @param entity 库存变动记录实体 * @param entity 库存变动记录实体
*/ */
void saveFlow(ConsStockFlow entity); void saveFlow(ConsStockFlow entity);
Integer ocr(String originalFilename, InputStream inputStream);
ConsInOutStockHeadParam ocrDetail(Long id);
} }

View File

@@ -0,0 +1,15 @@
package com.czg.product.service;
import com.czg.product.entity.MkOcrCountStick;
import com.mybatisflex.core.service.IService;
/**
* 数签子的外链渠道 服务层。
*
* @author ww
* @since 2025-12-24
*/
public interface MkOcrCountStickService extends IService<MkOcrCountStick> {
int getCountStick(byte[] stream, String fileName);
}

View File

@@ -1,6 +1,7 @@
package com.czg.product.service; package com.czg.product.service;
import com.czg.product.dto.ProductDTO; import com.czg.product.dto.ProductDTO;
import com.czg.product.dto.RelatedProductDTO;
import com.czg.product.entity.Product; import com.czg.product.entity.Product;
import com.czg.product.entity.ProductStockFlow; import com.czg.product.entity.ProductStockFlow;
import com.czg.product.param.*; import com.czg.product.param.*;

View File

@@ -3,12 +3,14 @@ package com.czg.product.vo;
import cn.hutool.core.convert.Convert; import cn.hutool.core.convert.Convert;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.annotation.JSONField; import com.alibaba.fastjson2.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data; import lombok.Data;
import java.io.Serial; import java.io.Serial;
import java.io.Serializable; import java.io.Serializable;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.LocalTime; import java.time.LocalTime;
import java.util.List;
/** /**
* 商品规格详情 * 商品规格详情
@@ -109,6 +111,12 @@ public class ShopProductInfoVo implements Serializable {
*/ */
@JSONField(serialize = false) @JSONField(serialize = false)
private LocalTime endTime; private LocalTime endTime;
/**
* 相关推荐商品
*/
private List<ShopProductVo> relatedRecommendJson;
@JsonIgnore
private String relatedRecommend;
public Object getImages() { public Object getImages() {
return JSON.parseArray(Convert.toStr(images, "[]")); return JSON.parseArray(Convert.toStr(images, "[]"));

View File

@@ -72,9 +72,7 @@ public interface SysParamsService extends IService<SysParams> {
* dubbo 调用需要 显式抛出 异常类型 * dubbo 调用需要 显式抛出 异常类型
* *
* @param type 参数类型 * @param type 参数类型
* userMiniKeys 用户小程序参数 appId appSecret * @param keyList 内容为 {@link com.czg.constants.ParamCodeCst}的Set集合
* shopMiniKeys 商家小程序参数 appId appSecret
* payKeys 微信支付参数
*/ */
Map<String, String> getParamsByMap(String type, Set<String> keyList) throws CzgException; Map<String, String> getParamsByMap(String type, Set<String> keyList) throws CzgException;
} }

View File

@@ -11,6 +11,8 @@ public enum ShopUserFlowBizEnum {
// 会员充值 // 会员充值
CASH_IN("cashIn", "会员充值"), CASH_IN("cashIn", "会员充值"),
CASHBACK("cashback", "消费返现"), CASHBACK("cashback", "消费返现"),
CASHBACK_REFUND("cashback_refund", "消费返现扣减"),
FREE_IN("freeIn", "霸王餐充值"), FREE_IN("freeIn", "霸王餐充值"),
// 重置奖励 // 重置奖励
AWARD_IN("awardIn", "充值奖励"), AWARD_IN("awardIn", "充值奖励"),

View File

@@ -16,9 +16,6 @@ import com.czg.exception.CzgException;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.io.DataOutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -35,9 +32,8 @@ public class AliOcrUtil {
/** /**
* <b>description</b> : * <b>description</b> :
* <p>使用凭据初始化账号Client</p> * <p>使用凭据初始化账号Client</p>
* @return Client
* *
* @throws Exception * @return Client
*/ */
public static com.aliyun.bailian20231229.Client createClient() { public static com.aliyun.bailian20231229.Client createClient() {
@@ -56,7 +52,6 @@ public class AliOcrUtil {
} }
public static ApplyFileUploadLeaseResponseBody.ApplyFileUploadLeaseResponseBodyData applyFileUpload(byte[] bytes, String fileName) { public static ApplyFileUploadLeaseResponseBody.ApplyFileUploadLeaseResponseBodyData applyFileUpload(byte[] bytes, String fileName) {
String md5 = DigestUtil.md5Hex(bytes); String md5 = DigestUtil.md5Hex(bytes);
@@ -118,7 +113,7 @@ public class AliOcrUtil {
// 复制代码运行请自行打印 API 的返回值 // 复制代码运行请自行打印 API 的返回值
DescribeFileResponse describeFileResponse = client.describeFileWithOptions("llm-9zg04s7wlbvi32tq", fileId, headers, runtime); DescribeFileResponse describeFileResponse = client.describeFileWithOptions("llm-9zg04s7wlbvi32tq", fileId, headers, runtime);
log.info("file status: {}", describeFileResponse.getBody()); log.info("file status: {}", describeFileResponse.getStatusCode());
return describeFileResponse.getBody().getData() != null && "FILE_IS_READY".equals(describeFileResponse.getBody().getData().getStatus()); return describeFileResponse.getBody().getData() != null && "FILE_IS_READY".equals(describeFileResponse.getBody().getData().getStatus());
} catch (Exception error) { } catch (Exception error) {
throw new RuntimeException(error); throw new RuntimeException(error);
@@ -158,9 +153,9 @@ public class AliOcrUtil {
} }
//地址 https://bailian.console.aliyun.com
public static String appCall(byte[] bytes, String fileName) { public static String appCall(byte[] bytes, String fileName, String detail) {
String id = null; String id;
try { try {
id = getSessionId(bytes, fileName); id = getSessionId(bytes, fileName);
} catch (Exception e) { } catch (Exception e) {
@@ -169,7 +164,7 @@ public class AliOcrUtil {
ApplicationParam param = ApplicationParam.builder() ApplicationParam param = ApplicationParam.builder()
.apiKey("sk-2343af4413834ad1ab43b036e3a903de") .apiKey("sk-2343af4413834ad1ab43b036e3a903de")
.appId("cd612ac509a4499f8ac68a656532d4ae") .appId("cd612ac509a4499f8ac68a656532d4ae")
.prompt("你是一名票据OCR结构化专家请从我提供的票据图片中智能提取信息并只输出JSON不得添加解释、不补充不存在内容、不得返回空字符串、字段缺失填null、字段不可省略、数字一律用字符串使用以下固定JSON结构{\"documentType\":\"\",\"orderNumber\":\"\",\"date\":\"\",\"customerName\":\"\",\"operator\":\"\",\"items\":[{\"conName\":\"\",\"spec\":\"\",\"unitName\":\"\",\"inOutNumber\":\"\",\"purchasePrice\":\"\",\"subTotal\":\"\"}],\"totalAmount\":\"\",\"remark\":\"\"}。字段映射规则documentType对应单据类型/销售单/采购单/出货单orderNumber对应单号/编号/Nodate对应日期/开单日期customerName对应客户名称/收货单位/供应商operator对应业务员/经办人/制单人/操作员items.conName对应品名/名称items.spec对应规格/型号items.unitName对应单位items.inOutNumber对应数量items.purchasePrice对应单价items.subTotal对应金额/小计totalAmount对应总金额/合计金额remark对应备注。严禁生成图片中不存在的字段内容看不清或未出现的字段必须为null不允许推测或补全不得生成多余字段items只能根据识别到的行生成不得虚构。必须能识别旋转、倾斜、模糊、撕裂、光照差异、列顺序混乱、无表格线等情况并尽量恢复信息。最终输出必须是纯JSON不得包含任何非JSON字符。") .prompt(detail)
.ragOptions(RagOptions.builder() .ragOptions(RagOptions.builder()
.sessionFileIds(List.of(id)) .sessionFileIds(List.of(id))
.build()) .build())
@@ -187,11 +182,4 @@ public class AliOcrUtil {
return result.getOutput().getText(); return result.getOutput().getText();
} }
public static void main(String[] args) {
}
static void main() throws Exception {
}
} }

View File

@@ -2,9 +2,12 @@ package com.czg.utils;
import cn.hutool.core.lang.func.Func0; import cn.hutool.core.lang.func.Func0;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import java.util.function.Consumer; /**
* @author zs
*/
@Slf4j @Slf4j
public class FunUtils { public class FunUtils {
/** /**
@@ -38,4 +41,27 @@ public class FunUtils {
log.error(errorMsg, args, e); log.error(errorMsg, args, e);
} }
} }
/**
* 在事务提交后执行方法
* 异步 执行
*
* @param func 方法
*/
public static void transactionSafeRun(Runnable func) {
try {
if (TransactionSynchronizationManager.isSynchronizationActive()) {
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
@Override
public void afterCommit() {
safeRunVoid(func, "");
}
});
} else {
safeRunVoid(func, "");
}
} catch (Exception e) {
log.error("方法执行失败: {}", e.getMessage());
}
}
} }

View File

@@ -62,6 +62,15 @@ public class PageUtil {
return new Page<>(pageNum, pageSize); return new Page<>(pageNum, pageSize);
} }
/**
* 获取空Page对象
*/
public <T> Page<T> emptyPage() {
return Page.of(1,10,0) ;
}
/** /**
* 构造排序QueryWrapper * 构造排序QueryWrapper
* 从param体获取 * 从param体获取

View File

@@ -22,7 +22,6 @@ import com.czg.market.vo.MemberConfigVO;
import com.czg.order.entity.OrderInfo; import com.czg.order.entity.OrderInfo;
import com.czg.sa.StpKit; import com.czg.sa.StpKit;
import com.czg.service.account.mapper.ShopUserMapper; import com.czg.service.account.mapper.ShopUserMapper;
import com.czg.system.service.SysParamsService;
import com.czg.utils.PageUtil; import com.czg.utils.PageUtil;
import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo; import com.github.pagehelper.PageInfo;
@@ -35,7 +34,6 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.text.ParseException;
import java.util.List; import java.util.List;
@@ -57,8 +55,6 @@ public class AShopUserServiceImpl implements AShopUserService {
@Resource @Resource
private UserInfoService userInfoService; private UserInfoService userInfoService;
@DubboReference @DubboReference
private SysParamsService sysParamsService;
@DubboReference
private OrderInfoService orderInfoService; private OrderInfoService orderInfoService;
@DubboReference @DubboReference
private MkShopCouponRecordService couponRecordService; private MkShopCouponRecordService couponRecordService;
@@ -66,8 +62,6 @@ public class AShopUserServiceImpl implements AShopUserService {
private MemberLevelConfigService memberLevelConfigService; private MemberLevelConfigService memberLevelConfigService;
@DubboReference @DubboReference
private TbMemberConfigService memberConfigService; private TbMemberConfigService memberConfigService;
// @DubboReference
// private MkShopConsumeDiscountRecordService consumeDiscountService;
private ShopUser getUserInfo(Long shopUserId) { private ShopUser getUserInfo(Long shopUserId) {
ShopUser shopUser = shopUserService.queryChain().eq(ShopUser::getId, shopUserId).one(); ShopUser shopUser = shopUserService.queryChain().eq(ShopUser::getId, shopUserId).one();
@@ -94,12 +88,8 @@ public class AShopUserServiceImpl implements AShopUserService {
public Page<ShopUserDTO> getPage(String key, Integer isVip, BigDecimal amount) { public Page<ShopUserDTO> getPage(String key, Integer isVip, BigDecimal amount) {
Long mainIdByShopId = shopInfoService.getMainIdByShopId(StpKit.USER.getShopId()); Long mainIdByShopId = shopInfoService.getMainIdByShopId(StpKit.USER.getShopId());
PageHelper.startPage(PageUtil.buildPageHelp()); PageHelper.startPage(PageUtil.buildPageHelp());
PageInfo<ShopUserDTO> shopUserDTOPageInfo = new PageInfo<>(shopUserMapper.selectPageByKeyAndIsVip(mainIdByShopId, isVip, key, amount)); PageInfo<ShopUserDTO> shopUsers = new PageInfo<>(shopUserMapper.selectPageByKeyAndIsVip(mainIdByShopId, isVip, key, amount));
// shopUserDTOPageInfo.getList().forEach(item -> { return PageUtil.convert(shopUsers);
// item.setNew(consumeDiscountService.isNewUser(item, StpKit.USER.getShopId()));
// setUserDiscount(item);
// });
return PageUtil.convert(shopUserDTOPageInfo);
} }
@Override @Override
@@ -177,16 +167,6 @@ public class AShopUserServiceImpl implements AShopUserService {
return shopUserService.save(shopUser); return shopUserService.save(shopUser);
} }
private void setUserDiscount(ShopUserDTO shopUserDTO) {
if (shopUserDTO.getMemberLevelId() != null) {
MemberLevelConfig memberLevelConfig = memberLevelConfigService.getById(shopUserDTO.getMemberLevelId());
shopUserDTO.setMemberLevelName(memberLevelConfig == null ? null : memberLevelConfig.getName());
if (memberLevelConfig != null) {
shopUserDTO.setDiscount(memberLevelConfig.getDiscount());
}
}
}
@Override @Override
public ShopUser getDetail(Integer id, Integer userId) { public ShopUser getDetail(Integer id, Integer userId) {
Long mainId = shopInfoService.getMainIdByShopId(StpKit.USER.getShopId()); Long mainId = shopInfoService.getMainIdByShopId(StpKit.USER.getShopId());

View File

@@ -473,7 +473,7 @@ public class CallTableServiceImpl extends ServiceImpl<CallTableMapper, CallTable
} else { } else {
List<CallTable> list = queryChain().eq(CallTable::getShopId, shopId).eq(CallTable::getState, 1).list(); List<CallTable> list = queryChain().eq(CallTable::getShopId, shopId).eq(CallTable::getState, 1).list();
if (list.isEmpty()) { if (list.isEmpty()) {
return new Page<>(); return PageUtil.emptyPage();
} }
tableIds = list.stream() tableIds = list.stream()
.map(CallTable::getId) .map(CallTable::getId)

View File

@@ -1,16 +1,13 @@
package com.czg.service.account.service.impl; package com.czg.service.account.service.impl;
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.BeanUtil;
import com.czg.account.dto.ShopConfigDTO;
import com.czg.account.entity.ShopConfig; import com.czg.account.entity.ShopConfig;
import com.czg.account.entity.ShopInfo; import com.czg.account.entity.ShopInfo;
import com.czg.account.service.ShopConfigService; import com.czg.account.service.ShopConfigService;
import com.czg.exception.CzgException; import com.czg.exception.CzgException;
import com.czg.sa.StpKit;
import com.czg.service.RedisService; import com.czg.service.RedisService;
import com.czg.service.account.mapper.ShopConfigMapper; import com.czg.service.account.mapper.ShopConfigMapper;
import com.czg.service.account.mapper.ShopInfoMapper; import com.czg.service.account.mapper.ShopInfoMapper;
import com.czg.utils.PageUtil;
import com.mybatisflex.core.query.QueryWrapper; import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl; import com.mybatisflex.spring.service.impl.ServiceImpl;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
@@ -90,19 +87,10 @@ public class ShopConfigServiceImpl extends ServiceImpl<ShopConfigMapper, ShopCon
}); });
if (isEnable == 0 && !onyUpValid) { if (isEnable == 0 && !onyUpValid) {
updateChain().in(ShopConfig::getId, childShopIdList).set(property, 0).update();
updateChain().or(or -> {
or.eq(ShopConfig::getId, mainShopId);
}).or(or -> {
or.in(ShopConfig::getId, childShopIdList);
}).set(property, 0).update();
}else { }else {
if ("all".equals(useShopType)) { if ("all".equals(useShopType)) {
updateChain().or(or -> { updateChain().in(ShopConfig::getId, childShopIdList).set(property, 1).update();
or.eq(ShopConfig::getId, mainShopId);
}).or(or -> {
or.in(ShopConfig::getId, childShopIdList);
}).set(property, 1).update();
}else { }else {
if (shopIdList.isEmpty()) { if (shopIdList.isEmpty()) {
updateChain().eq(ShopConfig::getId, mainShopId).set(property, 1).update(); updateChain().eq(ShopConfig::getId, mainShopId).set(property, 1).update();
@@ -115,7 +103,6 @@ public class ShopConfigServiceImpl extends ServiceImpl<ShopConfigMapper, ShopCon
} }
} }
extistList.forEach(item -> redisService.del("shopInfo::" + item)); extistList.forEach(item -> redisService.del("shopInfo::" + item));
redisService.del("shopInfo::" + mainShopId); redisService.del("shopInfo::" + mainShopId);
} }

View File

@@ -152,9 +152,6 @@ public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> impl
// Step 2: 解析 apiInfo 并判断菜单是否已绑定 // Step 2: 解析 apiInfo 并判断菜单是否已绑定
for (BaseMenu menu : menuList) { for (BaseMenu menu : menuList) {
if (menu.getMenuId() == 1L) {
continue;
}
// 解析 apiInfo // 解析 apiInfo
if (StrUtil.isNotBlank(menu.getApiInfo())) { if (StrUtil.isNotBlank(menu.getApiInfo())) {
List<MenuApiInfoItemDTO> itemDTOS = JSONArray.parseArray(menu.getApiInfo()) List<MenuApiInfoItemDTO> itemDTOS = JSONArray.parseArray(menu.getApiInfo())
@@ -180,9 +177,6 @@ public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> impl
List<SysMenu> matchedMenus = sysMenuService.list(wrapper); List<SysMenu> matchedMenus = sysMenuService.list(wrapper);
for (SysMenu matched : matchedMenus) { for (SysMenu matched : matchedMenus) {
if (matched.getMenuId() == 1L) {
continue;
}
long count = sysRolesMenusService.count(new QueryWrapper() long count = sysRolesMenusService.count(new QueryWrapper()
.eq("menu_id", matched.getMenuId()) .eq("menu_id", matched.getMenuId())
.eq("role_id", roleId) .eq("role_id", roleId)

View File

@@ -6,7 +6,6 @@ import com.alibaba.fastjson2.JSONObject;
import com.czg.account.dto.auth.GetPhoneDTO; import com.czg.account.dto.auth.GetPhoneDTO;
import com.czg.account.dto.auth.LoginTokenDTO; import com.czg.account.dto.auth.LoginTokenDTO;
import com.czg.account.dto.auth.UserAuthorizationLoginDTO; import com.czg.account.dto.auth.UserAuthorizationLoginDTO;
import com.czg.account.dto.auth.WechatRawDataDTO;
import com.czg.account.entity.UserInfo; import com.czg.account.entity.UserInfo;
import com.czg.account.service.UserAuthorizationService; import com.czg.account.service.UserAuthorizationService;
import com.czg.account.service.UserInfoService; import com.czg.account.service.UserInfoService;
@@ -95,19 +94,13 @@ public class UserAuthorizationServiceImpl implements UserAuthorizationService {
openId = wechatAuthUtil.getSessionKeyOrOpenId(userAuthorizationLoginDTO.getCode(), false); openId = wechatAuthUtil.getSessionKeyOrOpenId(userAuthorizationLoginDTO.getCode(), false);
userInfo = userInfoService.queryChain().eq(UserInfo::getWechatOpenId, openId).one(); userInfo = userInfoService.queryChain().eq(UserInfo::getWechatOpenId, openId).one();
userInfo = userInfo == null ? new UserInfo() : userInfo; userInfo = userInfo == null ? new UserInfo() : userInfo;
if (StrUtil.isNotBlank(userAuthorizationLoginDTO.getRawData())) { userInfo.setNickName(StrUtil.isNotBlank(userInfo.getNickName()) ? userInfo.getNickName() : "微信用户");
WechatRawDataDTO wechatRawDataDTO = JSONObject.parseObject(userAuthorizationLoginDTO.getRawData(), WechatRawDataDTO.class);
userInfo.setHeadImg(wechatRawDataDTO.getAvatarUrl());
userInfo.setNickName(StrUtil.isNotBlank(wechatRawDataDTO.getNickName()) ? wechatRawDataDTO.getNickName() : "微信用户");
} else {
userInfo.setNickName("微信用户");
}
userInfo.setWechatOpenId(openId); userInfo.setWechatOpenId(openId);
} else { } else {
openId = alipayUtil.getOpenId(userAuthorizationLoginDTO.getCode(), false); openId = alipayUtil.getOpenId(userAuthorizationLoginDTO.getCode(), false);
userInfo = userInfoService.queryChain().eq(UserInfo::getAlipayOpenId, openId).one(); userInfo = userInfoService.queryChain().eq(UserInfo::getAlipayOpenId, openId).one();
userInfo = userInfo == null ? new UserInfo() : userInfo; userInfo = userInfo == null ? new UserInfo() : userInfo;
userInfo.setNickName("支付宝用户"); userInfo.setNickName(StrUtil.isNotBlank(userInfo.getNickName()) ? userInfo.getNickName() : "支付宝用户");
userInfo.setAlipayOpenId(openId); userInfo.setAlipayOpenId(openId);
} }

View File

@@ -10,6 +10,7 @@ import com.czg.account.dto.user.userinfo.UserInfoEditDTO;
import com.czg.account.dto.user.userinfo.UserInfoPwdEditDTO; import com.czg.account.dto.user.userinfo.UserInfoPwdEditDTO;
import com.czg.account.entity.ShopUser; import com.czg.account.entity.ShopUser;
import com.czg.account.entity.UserInfo; import com.czg.account.entity.UserInfo;
import com.czg.account.service.ShopInfoService;
import com.czg.account.service.UserInfoService; import com.czg.account.service.UserInfoService;
import com.czg.config.RedisCst; import com.czg.config.RedisCst;
import com.czg.exception.CzgException; import com.czg.exception.CzgException;
@@ -38,6 +39,8 @@ public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> i
@Resource @Resource
private ShopUserMapper shopUserMapper; private ShopUserMapper shopUserMapper;
@Resource @Resource
private ShopInfoService shopInfoService;
@Resource
private RedisService redisService; private RedisService redisService;
@Resource @Resource
private AcAccountUtil acAccountUtil; private AcAccountUtil acAccountUtil;
@@ -62,9 +65,10 @@ public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> i
UserInfo userInfo = getById(userId); UserInfo userInfo = getById(userId);
BeanUtil.copyProperties(userInfoEditDTO, userInfo); BeanUtil.copyProperties(userInfoEditDTO, userInfo);
if (updateById(userInfo)) { if (updateById(userInfo)) {
if (shopId != -1L) { if (shopId != 0L) {
ShopUser shopUser = BeanUtil.copyProperties(userInfo, ShopUser.class); ShopUser shopUser = BeanUtil.copyProperties(userInfo, ShopUser.class);
return shopUserMapper.updateByQuery(shopUser, new QueryWrapper().eq(ShopUser::getSourceShopId, shopId).eq(ShopUser::getUserId, userId)) > 0; Long mainIdByShopId = shopInfoService.getMainIdByShopId(shopId);
return shopUserMapper.updateByQuery(shopUser, new QueryWrapper().eq(ShopUser::getMainShopId, mainIdByShopId).eq(ShopUser::getUserId, userId)) > 0;
} }
return true; return true;
} }

View File

@@ -15,6 +15,7 @@ import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map;
/** /**
* 微信公众号 * 微信公众号
@@ -90,8 +91,10 @@ public class AcAccountUtil {
if (StrUtil.isNotEmpty(accessToken)) { if (StrUtil.isNotEmpty(accessToken)) {
return accessToken; return accessToken;
} }
String acAppId = paramsService.getSysParamValue(ParamCodeCst.Wechat.Ac.USER_WX_AC_APP_ID); Map<String, String> userAc = paramsService.getParamsByMap("user_ac_key_set", ParamCodeCst.USER_AC_KEY_SET);
String acSecrete = paramsService.getSysParamValue(ParamCodeCst.Wechat.Ac.USER_WX_AC_SECRETE); // 用户小程序参数
String acAppId = userAc.get(ParamCodeCst.Wechat.Ac.USER_WX_AC_APP_ID);
String acSecrete = userAc.get(ParamCodeCst.Wechat.Ac.USER_WX_AC_SECRETE);
String resp = HttpUtil.get(StrUtil.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={}&secret={}", acAppId, acSecrete)); String resp = HttpUtil.get(StrUtil.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={}&secret={}", acAppId, acSecrete));
JSONObject respInfo = JSONObject.parseObject(resp); JSONObject respInfo = JSONObject.parseObject(resp);
if (!respInfo.containsKey("access_token")) { if (!respInfo.containsKey("access_token")) {
@@ -103,26 +106,4 @@ public class AcAccountUtil {
redisService.set("wx:ac:AccessToken", accessToken, expiresIn - 10); redisService.set("wx:ac:AccessToken", accessToken, expiresIn - 10);
return accessToken; return accessToken;
} }
public static void main(String[] args) {
// String resp = HttpUtil.get(StrUtil.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={}&secret={}", "wx1fb600d0f5ea6279", "b4c0534c9b5e6c84a7fe5c2078dff876"));
// System.out.println(resp);
// String accessToken = "97_HZVThQrtvOiCZGrr23ZHN0cVpHBJHc18RSFHU6dvkQDMAme4GsG0NU-Dax1HP5Wx-aGa1l35KaqiMVv61TCj0Qk8DK1LC6kQ8uKLDfgRYVJjX3QjcelmIjp4PCkERBeABAUHR";
// JSONObject bodyJson = new JSONObject();
// //二维码有效时间最大2592000仅临时二维码需要
// bodyJson.put("expire_seconds", "2592000");
// //二维码类型QR_SCENE(临时整型)/QR_STR_SCENE(临时字符串)/QR_LIMIT_SCENE(永久整型)/QR_LIMIT_STR_SCENE(永久字符串)
// bodyJson.put("action_name", "QR_STR_SCENE");
// JSONObject actionInfo = new JSONObject();
// JSONObject scene = new JSONObject();
// scene.put("scene_str", "43525423");
// actionInfo.put("scene", scene);
// bodyJson.put("action_info", actionInfo);
// System.out.println(bodyJson);
//创建临时二维码失败,发送参数: {"action_info":{"scene":{"scene_id":36449}},"action_name":"QR_SCENE","expire_seconds":"2592000"}, 响应内容: {"errcode":40052,"errmsg":"invalid action name rid: 68f5fa37-20fb3162-0f87b4f2"}
//创建临时二维码失败,发送参数: {"action_info":{"scene":{"scene_id":36449}},"action_name":"QR_SCENE","expire_seconds":"2592000"}, 响应内容: {"errcode":40052,"errmsg":"invalid action name rid: 68f5f970-2a84749c-78e4d78f"}
// String resps = HttpUtil.post(StrUtil.format("https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token={}", accessToken), JSONObject.toJSONString(bodyJson));
// JSONObject respInfos = JSONObject.parseObject(resps);
// System.out.println(respInfos);
}
} }

View File

@@ -17,6 +17,9 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference; import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.Map;
import java.util.Set;
/** /**
* 支付宝通用SDK工具类 * 支付宝通用SDK工具类
* *
@@ -37,13 +40,15 @@ public class AlipayUtil {
*/ */
@SneakyThrows @SneakyThrows
public AlipayClient createClient(boolean isAccount) { public AlipayClient createClient(boolean isAccount) {
String serverUrl = sysParamsService.getSysParamValue(ParamCodeCst.Alipay.Web.ALI_GATEWAY); Map<String, String> aliPayKeySet = sysParamsService.getParamsByMap("ali_pay_key_set", ParamCodeCst.ALI_PAY_KEY_SET);
String appId = sysParamsService.getSysParamValue(ParamCodeCst.Alipay.Mini.ALI_MINI_APP_ID);
String privateKey = sysParamsService.getSysParamValue(ParamCodeCst.Alipay.Mini.ALI_MINI_PRIVATE_KEY); String serverUrl = aliPayKeySet.get(ParamCodeCst.Alipay.Web.ALI_GATEWAY);
String alipayPublicKey = sysParamsService.getSysParamValue(ParamCodeCst.Alipay.Mini.ALI_MINI_PUBLIC_KEY); String appId = aliPayKeySet.get(ParamCodeCst.Alipay.Mini.ALI_MINI_APP_ID);
String accountAppId = sysParamsService.getSysParamValue(ParamCodeCst.Alipay.Web.ALI_ACCOUNT_APP_ID); String privateKey = aliPayKeySet.get(ParamCodeCst.Alipay.Mini.ALI_MINI_PRIVATE_KEY);
String accountPrivateKey = sysParamsService.getSysParamValue(ParamCodeCst.Alipay.Web.ALI_ACCOUNT_PRIVATE_KEY); String alipayPublicKey = aliPayKeySet.get(ParamCodeCst.Alipay.Mini.ALI_MINI_PUBLIC_KEY);
String accountPublicKey = sysParamsService.getSysParamValue(ParamCodeCst.Alipay.Web.ALI_ACCOUNT_PUBLIC_KEY); String accountAppId = aliPayKeySet.get(ParamCodeCst.Alipay.Web.ALI_ACCOUNT_APP_ID);
String accountPrivateKey = aliPayKeySet.get(ParamCodeCst.Alipay.Web.ALI_ACCOUNT_PRIVATE_KEY);
String accountPublicKey = aliPayKeySet.get(ParamCodeCst.Alipay.Web.ALI_ACCOUNT_PUBLIC_KEY);
AlipayConfig alipayConfig = new AlipayConfig(); AlipayConfig alipayConfig = new AlipayConfig();
//设置网关地址 //设置网关地址
alipayConfig.setServerUrl(serverUrl); alipayConfig.setServerUrl(serverUrl);

View File

@@ -56,8 +56,9 @@ public class WechatAuthUtil {
} }
public String getAccountOpenId(String code) { public String getAccountOpenId(String code) {
String accountAppId = sysParamsService.getSysParamValue(ParamCodeCst.Wechat.Ac.SHOP_WX_AC_APP_ID); Map<String, String> shopAc = sysParamsService.getParamsByMap("shop_ac_key_set", ParamCodeCst.SHOP_AC_KEY_SET);
String accountSecrete = sysParamsService.getSysParamValue(ParamCodeCst.Wechat.Ac.SHOP_WX_AC_SECRETE); String accountAppId = shopAc.get(ParamCodeCst.Wechat.Ac.SHOP_WX_AC_APP_ID);
String accountSecrete = shopAc.get(ParamCodeCst.Wechat.Ac.SHOP_WX_AC_SECRETE);
String requestUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?"; String requestUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?";
Map<String, Object> requestUrlParam = new HashMap<>(); Map<String, Object> requestUrlParam = new HashMap<>();
// https://mp.weixin.qq.com/wxopen/devprofile?action=get_profile&token=164113089&lang=zh_CN // https://mp.weixin.qq.com/wxopen/devprofile?action=get_profile&token=164113089&lang=zh_CN
@@ -78,8 +79,10 @@ public class WechatAuthUtil {
//获取小程序token //获取小程序token
private String getAccessToken() { private String getAccessToken() {
String appId = sysParamsService.getSysParamValue(ParamCodeCst.Wechat.Mini.USER_WX_APP_ID); Map<String, String> userMini = sysParamsService.getParamsByMap("user_mini_key_set", ParamCodeCst.USER_MINI_KEY_SET);
String secrete = sysParamsService.getSysParamValue(ParamCodeCst.Wechat.Mini.USER_WX_SECRETE); // 用户小程序参数
String appId = userMini.get(ParamCodeCst.Wechat.Mini.USER_WX_APP_ID);
String secrete = userMini.get(ParamCodeCst.Wechat.Mini.USER_WX_SECRETE);
String url = String.format("%s?grant_type=client_credential&appid=%s&secret=%s", TOKEN_URL, appId, secrete); String url = String.format("%s?grant_type=client_credential&appid=%s&secret=%s", TOKEN_URL, appId, secrete);
String response = HttpUtil.get(url); String response = HttpUtil.get(url);
com.alibaba.fastjson.JSONObject jsonResponse = com.alibaba.fastjson.JSONObject.parseObject(response); com.alibaba.fastjson.JSONObject jsonResponse = com.alibaba.fastjson.JSONObject.parseObject(response);
@@ -120,8 +123,11 @@ public class WechatAuthUtil {
public JSONObject getSession(String code) { public JSONObject getSession(String code) {
String appId = sysParamsService.getSysParamValue(ParamCodeCst.Wechat.Mini.USER_WX_APP_ID); Map<String, String> userMini = sysParamsService.getParamsByMap("user_mini_key_set", ParamCodeCst.USER_MINI_KEY_SET);
String secrete = sysParamsService.getSysParamValue(ParamCodeCst.Wechat.Mini.USER_WX_SECRETE); // 用户小程序参数
String appId = userMini.get(ParamCodeCst.Wechat.Mini.USER_WX_APP_ID);
String secrete = userMini.get(ParamCodeCst.Wechat.Mini.USER_WX_SECRETE);
String requestUrl = "https://api.weixin.qq.com/sns/jscode2session"; String requestUrl = "https://api.weixin.qq.com/sns/jscode2session";
Map<String, Object> requestUrlParam = new HashMap<>(); Map<String, Object> requestUrlParam = new HashMap<>();
// https://mp.weixin.qq.com/wxopen/devprofile?action=get_profile&token=164113089&lang=zh_CN // https://mp.weixin.qq.com/wxopen/devprofile?action=get_profile&token=164113089&lang=zh_CN

View File

@@ -139,8 +139,9 @@ public class WechatMiniMsgUtil {
} }
public String getAccountOpenId(String code) { public String getAccountOpenId(String code) {
String accountAppId = sysParamsService.getSysParamValue(ParamCodeCst.Wechat.Ac.SHOP_WX_AC_APP_ID); Map<String, String> shopAc = sysParamsService.getParamsByMap("shop_ac_key_set", ParamCodeCst.SHOP_AC_KEY_SET);
String accountSecrete = sysParamsService.getSysParamValue(ParamCodeCst.Wechat.Ac.SHOP_WX_AC_SECRETE); String accountAppId = shopAc.get(ParamCodeCst.Wechat.Ac.SHOP_WX_AC_APP_ID);
String accountSecrete = shopAc.get(ParamCodeCst.Wechat.Ac.SHOP_WX_AC_SECRETE);
String requestUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?"; String requestUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?";
Map<String, Object> requestUrlParam = new HashMap<>(); Map<String, Object> requestUrlParam = new HashMap<>();
// https://mp.weixin.qq.com/wxopen/devprofile?action=get_profile&token=164113089&lang=zh_CN // https://mp.weixin.qq.com/wxopen/devprofile?action=get_profile&token=164113089&lang=zh_CN
@@ -165,8 +166,10 @@ public class WechatMiniMsgUtil {
if (StrUtil.isNotEmpty(accessToken)) { if (StrUtil.isNotEmpty(accessToken)) {
return accessToken; return accessToken;
} }
String appId = sysParamsService.getSysParamValue(ParamCodeCst.Wechat.Mini.SHOP_WX_APP_ID); // 商户小程序参数
String secrete = sysParamsService.getSysParamValue(ParamCodeCst.Wechat.Mini.SHOP_WX_SECRETE); Map<String, String> shopMiniKeyMap = sysParamsService.getParamsByMap("shop_mini_key_set", ParamCodeCst.SHOP_MINI_KEY_SET);
String appId = shopMiniKeyMap.get(ParamCodeCst.Wechat.Mini.SHOP_WX_APP_ID);
String secrete = shopMiniKeyMap.get(ParamCodeCst.Wechat.Mini.SHOP_WX_SECRETE);
String url = String.format("%s?grant_type=client_credential&appid=%s&secret=%s", TOKEN_URL, appId, secrete); String url = String.format("%s?grant_type=client_credential&appid=%s&secret=%s", TOKEN_URL, appId, secrete);
String response = HttpUtil.get(url); String response = HttpUtil.get(url);
@@ -211,8 +214,10 @@ public class WechatMiniMsgUtil {
public JSONObject getSession(String code) { public JSONObject getSession(String code) {
String appId = sysParamsService.getSysParamValue(ParamCodeCst.Wechat.Mini.USER_WX_APP_ID); Map<String, String> userMini = sysParamsService.getParamsByMap("user_mini_key_set", ParamCodeCst.USER_MINI_KEY_SET);
String secrete = sysParamsService.getSysParamValue(ParamCodeCst.Wechat.Mini.USER_WX_SECRETE); // 用户小程序参数
String appId = userMini.get(ParamCodeCst.Wechat.Mini.USER_WX_APP_ID);
String secrete = userMini.get(ParamCodeCst.Wechat.Mini.USER_WX_SECRETE);
String requestUrl = "https://api.weixin.qq.com/sns/jscode2session"; String requestUrl = "https://api.weixin.qq.com/sns/jscode2session";
Map<String, Object> requestUrlParam = new HashMap<>(); Map<String, Object> requestUrlParam = new HashMap<>();
// https://mp.weixin.qq.com/wxopen/devprofile?action=get_profile&token=164113089&lang=zh_CN // https://mp.weixin.qq.com/wxopen/devprofile?action=get_profile&token=164113089&lang=zh_CN

View File

@@ -5,7 +5,7 @@
<mapper namespace="com.czg.service.account.mapper.ShopUserMapper"> <mapper namespace="com.czg.service.account.mapper.ShopUserMapper">
<update id="incrAccount"> <update id="incrAccount">
update tb_shop_user update tb_shop_user
set amount = COALESCE(amount, 0) + #{money}, set amount = amount + #{money},
update_time = #{time} update_time = #{time}
where id = #{id} where id = #{id}
@@ -44,7 +44,7 @@
</select> </select>
<select id="selectVipCard" resultType="com.czg.account.dto.shopuser.ShopUserVipCardDTO"> <select id="selectVipCard" resultType="com.czg.account.dto.shopuser.ShopUserVipCardDTO">
select tb_shop_info.logo, tb_shop_info.shop_name shopName, tb_shop_user.amount, tb_shop_user.shop_id shopId select tb_shop_info.logo, tb_shop_info.shop_name shopName, tb_shop_user.amount, tb_shop_user.main_shop_id shopId
from tb_shop_user from tb_shop_user
left join tb_shop_info on tb_shop_user.main_shop_id = tb_shop_info.id left join tb_shop_info on tb_shop_user.main_shop_id = tb_shop_info.id
${qwSql} ${qwSql}
@@ -72,41 +72,20 @@
IFNULL(c.couponNum, 0) AS couponNum, IFNULL(c.couponNum, 0) AS couponNum,
IFNULL(d.orderNumber, 0) AS orderNumber, IFNULL(d.orderNumber, 0) AS orderNumber,
IFNULL(f.rechargeAmount, 0) AS rechargeAmount, IFNULL(f.rechargeAmount, 0) AS rechargeAmount,
c.name as memberLevelName, point.point_balance as pointBalance,
c.discount c1.name as memberLevelName,
c1.discount
FROM tb_shop_user a FROM tb_shop_user a
LEFT JOIN tb_user_info b ON b.id = a.user_id LEFT JOIN tb_member_level_config c1 on c1.id=a.member_level_id
LEFT JOIN tb_member_level_config c on c.id=a.member_level_id LEFT JOIN mk_points_user point on point.shop_user_id = a.id
-- 预计算优惠券数量 -- 预计算优惠券数量
LEFT JOIN ( LEFT JOIN (SELECT shop_user_id, COUNT(*) AS couponNum FROM mk_shop_coupon_record WHERE is_del = 0 GROUP BY shop_user_id ) c ON c.shop_user_id = a.id
SELECT shop_user_id, COUNT(*) AS couponNum
FROM mk_shop_coupon_record
WHERE
is_del = 0
# AND status = 0
# AND use_start_time &lt; NOW()
# AND use_end_time > NOW()
GROUP BY shop_user_id
) c ON c.shop_user_id = a.id
-- 预计算订单数量 -- 预计算订单数量
LEFT JOIN ( LEFT JOIN (SELECT user_id, shop_id, COUNT(*) AS orderNumber FROM tb_order_info GROUP BY user_id, shop_id) d ON d.user_id = a.user_id AND d.shop_id = a.main_shop_id
SELECT user_id, shop_id, COUNT(*) AS orderNumber
FROM tb_order_info
GROUP BY user_id, shop_id
) d ON d.user_id = a.user_id AND d.shop_id = a.main_shop_id
-- 预计算充值总金额 -- 预计算充值总金额
LEFT JOIN ( LEFT JOIN ( SELECT user_id, shop_id, SUM(amount) AS rechargeAmount
SELECT user_id, shop_id, SUM(amount) AS rechargeAmount FROM tb_shop_user_flow WHERE biz_code IN ('cashIn', 'wechatIn', 'alipayIn') GROUP BY user_id, shop_id ) f ON f.user_id = a.user_id AND f.shop_id = a.main_shop_id
FROM tb_shop_user_flow
WHERE biz_code IN ('cashIn', 'wechatIn', 'alipayIn')
GROUP BY user_id, shop_id
) f ON f.user_id = a.user_id AND f.shop_id = a.main_shop_id
WHERE a.main_shop_id = #{shopId} WHERE a.main_shop_id = #{shopId}
<if test="isVip != null"> <if test="isVip != null">
AND a.is_vip = #{isVip} AND a.is_vip = #{isVip}
</if> </if>

View File

@@ -28,8 +28,6 @@ public class AppWxServiceImpl extends BaseWx {
@DubboReference @DubboReference
private SysParamsService paramsService; private SysParamsService paramsService;
private static final Set<String> USER_MINI_KEYS = Set.of(ParamCodeCst.Wechat.Mini.USER_WX_APP_ID, ParamCodeCst.Wechat.Mini.USER_WX_SECRETE);
public AppWxServiceImpl(@Autowired RedisService autoRedisService) { public AppWxServiceImpl(@Autowired RedisService autoRedisService) {
this.redisService = autoRedisService; this.redisService = autoRedisService;
config = new Config(); config = new Config();
@@ -64,10 +62,10 @@ public class AppWxServiceImpl extends BaseWx {
@Override @Override
public void init() throws CzgException { public void init() throws CzgException {
// 用户小程序参数 // 用户小程序参数
Map<String, String> userMiniKeyMap = paramsService.getParamsByMap("userMiniKeys", USER_MINI_KEYS); Map<String, String> userMiniKeyMap = paramsService.getParamsByMap("user_mini_key_set", ParamCodeCst.USER_MINI_KEY_SET);
// 微信支付参数 // 微信支付参数
Map<String, String> payKeyMap = paramsService.getParamsByMap("payKeys", PAY_KEYS); Map<String, String> payKeyMap = paramsService.getParamsByMap("pay_key_set", ParamCodeCst.PAY_KEY_SET);
// 小程序id // 小程序id
config.appId = userMiniKeyMap.get(ParamCodeCst.Wechat.Mini.USER_WX_APP_ID); config.appId = userMiniKeyMap.get(ParamCodeCst.Wechat.Mini.USER_WX_APP_ID);

View File

@@ -59,18 +59,6 @@ public abstract class BaseWx {
*/ */
protected static final Long EXPIRES_OFFSET = 200L; protected static final Long EXPIRES_OFFSET = 200L;
/**
* 支付参数KEY
*/
protected static final Set<String> PAY_KEYS = Set.of(
ParamCodeCst.Wechat.Pay.WX_PUB_KEY,
ParamCodeCst.Wechat.Pay.WX_API_CLIENT_KEY,
ParamCodeCst.Wechat.Pay.WX_API_CLIENT_CERT,
ParamCodeCst.Wechat.Pay.WX_MCH_ID,
ParamCodeCst.Wechat.Pay.WX_V3_KEY,
ParamCodeCst.System.NATIVE_NOTIFY_URL
);
/** /**
* 初始化配置信息 * 初始化配置信息
*/ */

View File

@@ -11,6 +11,7 @@ import com.czg.market.service.GbWareService;
import com.czg.sa.StpKit; import com.czg.sa.StpKit;
import com.czg.service.market.mapper.GbWareMapper; import com.czg.service.market.mapper.GbWareMapper;
import com.czg.utils.AssertUtil; import com.czg.utils.AssertUtil;
import com.czg.utils.PageUtil;
import com.mybatisflex.core.paginate.Page; import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper; import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl; import com.mybatisflex.spring.service.impl.ServiceImpl;
@@ -32,7 +33,7 @@ public class GbWareServiceImpl extends ServiceImpl<GbWareMapper, GbWare> impleme
@Override @Override
public Page<GbWare> getGbWarePage(GbWareQueryParamDTO param, Long shopId, boolean isAdmin) { public Page<GbWare> getGbWarePage(GbWareQueryParamDTO param, Long shopId, boolean isAdmin) {
if (!isAdmin && !shopInfoService.checkSwitch(shopId, ShopSwitchTypeEnum.GROUP_BUY)) { if (!isAdmin && !shopInfoService.checkSwitch(shopId, ShopSwitchTypeEnum.GROUP_BUY)) {
return new Page<>(); return PageUtil.emptyPage();
} }
Long mainShopId = shopInfoService.getMainIdByShopId(shopId); Long mainShopId = shopInfoService.getMainIdByShopId(shopId);
QueryWrapper queryWrapper = new QueryWrapper(); QueryWrapper queryWrapper = new QueryWrapper();
@@ -54,9 +55,7 @@ public class GbWareServiceImpl extends ServiceImpl<GbWareMapper, GbWare> impleme
}); });
Page<GbWare> page = page(Page.of(param.getPage(), param.getSize()), queryWrapper); Page<GbWare> page = page(Page.of(param.getPage(), param.getSize()), queryWrapper);
if (!isAdmin) { if (!isAdmin) {
page.getRecords().forEach(item -> { page.getRecords().forEach(item -> item.setShopId(shopId));
item.setShopId(shopId);
});
} }
return page; return page;
} }

View File

@@ -160,7 +160,7 @@ public class MkConsumeCashbackServiceImpl extends ServiceImpl<MkConsumeCashbackM
shopUserService.updateMoney(new ShopUserMoneyEditDTO().setId(shopUser.getId()).setType(1) shopUserService.updateMoney(new ShopUserMoneyEditDTO().setId(shopUser.getId()).setType(1)
.setRelationId(mkConsumeCashbackRecord.getId()).setMoney(cashbackAmount).setBizEnum(ShopUserFlowBizEnum.CASHBACK) .setRelationId(mkConsumeCashbackRecord.getId()).setMoney(cashbackAmount).setBizEnum(ShopUserFlowBizEnum.CASHBACK)
.setRemark(StrUtil.format("订单消费: {}, 返现: {}", amount, cashbackAmount))); .setRemark(StrUtil.format("订单消费: {}, 返现: {}", amount, cashbackAmount)));
log.info("订单返现 订单ID:{}, 店铺用户id: {}, 订单消费: {}, 返现: {}",orderId, shopUser.getId(), amount, cashbackAmount); log.info("订单返现 订单ID:{}, 店铺用户id: {}, 订单消费: {}, 返现: {}", orderId, shopUser.getId(), amount, cashbackAmount);
AcUserMsg msg = new AcUserMsg() AcUserMsg msg = new AcUserMsg()
.setUserId(userId) .setUserId(userId)
@@ -176,4 +176,45 @@ public class MkConsumeCashbackServiceImpl extends ServiceImpl<MkConsumeCashbackM
} }
} }
} }
@Override
@Transactional(rollbackFor = Exception.class)
public void removeCashback(Long shopId, Long userId, Long orderId, String orderNo) {
MkConsumeCashbackRecord record = consumeCashbackRecordService.getOne(query()
.eq(MkConsumeCashbackRecord::getShopId, shopId)
.eq(MkConsumeCashbackRecord::getUserId, userId)
.eq(MkConsumeCashbackRecord::getOrderNo, orderNo)
.eq(MkConsumeCashbackRecord::getOrderId, orderId));
if (record == null) {
return;
}
MkConsumeCashbackRecord mkConsumeCashbackRecord = new MkConsumeCashbackRecord()
.setOrderNo(orderNo)
.setOrderId(orderId)
.setMainShopId(record.getMainShopId())
.setShopId(shopId)
.setAmount(BigDecimal.ZERO)
.setCashbackAmount(record.getCashbackAmount().negate())
.setUserId(userId)
.setShopUserId(record.getShopUserId());
consumeCashbackRecordService.save(mkConsumeCashbackRecord);
shopUserService.updateMoney(new ShopUserMoneyEditDTO()
.setId(record.getShopUserId())
.setType(0)
.setRelationId(mkConsumeCashbackRecord.getId())
.setMoney(record.getCashbackAmount())
.setBizEnum(ShopUserFlowBizEnum.CASHBACK_REFUND)
.setRemark(StrUtil.format("订单退款,扣除返现: {}", record.getCashbackAmount())));
log.info("订单退款扣除返现 订单ID:{}, 店铺用户id: {}, 扣除返现: {}", orderId, record.getShopUserId(), record.getCashbackAmount());
AcUserMsg msg = new AcUserMsg()
.setUserId(userId)
.setShopId(shopId)
.setSourceId(orderId)
.setSourceType("order")
.setType("cash")
.setTitle("订单退款,消费返现扣除")
.setContent(StrUtil.format("返现扣除提醒: 订单退款扣除的{}元返现。订单编号:{}", record.getCashbackAmount(), orderNo));
acUserMsgService.addUserMsg(msg);
}
} }

View File

@@ -65,4 +65,9 @@ public class MkPointsConfigServiceImpl extends ServiceImpl<MkPointsConfigMapper,
mkPointsUserService.alterPoints(null, shopUser.getId(), orderInfo.getShopId(), PointsConstant.ADD, mkPointsUserService.alterPoints(null, shopUser.getId(), orderInfo.getShopId(), PointsConstant.ADD,
awardPoints.intValue(), orderInfo.getId(), StrUtil.format("消费¥{}送{}积分", payAmount, awardPoints.intValue())); awardPoints.intValue(), orderInfo.getId(), StrUtil.format("消费¥{}送{}积分", payAmount, awardPoints.intValue()));
} }
@Override
public void removeConsumeAwardPoints(Long shopId, Long userId, Long orderId, String orderNo) {
mkPointsUserService.removePointByOrder(shopId, userId, orderId, orderNo, "订单退款扣除赠送积分");
}
} }

View File

@@ -19,7 +19,6 @@ import com.mybatisflex.spring.service.impl.ServiceImpl;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -43,7 +42,7 @@ public class MkPointsGoodsServiceImpl extends ServiceImpl<MkPointsGoodsMapper, M
public Page<MkPointsGoods> getPointsGoodsPage(BaseQueryParam param, Long shopId) { public Page<MkPointsGoods> getPointsGoodsPage(BaseQueryParam param, Long shopId) {
boolean exists = mkPointsConfigService.exists(query().eq(MkPointsConfig::getShopId, shopId).eq(MkPointsConfig::getEnablePointsMall, 1)); boolean exists = mkPointsConfigService.exists(query().eq(MkPointsConfig::getShopId, shopId).eq(MkPointsConfig::getEnablePointsMall, 1));
if (!exists) { if (!exists) {
return new Page<>(); return PageUtil.emptyPage();
} }
Page<MkPointsGoods> page = page(Page.of(param.getPage(), param.getSize()), Page<MkPointsGoods> page = page(Page.of(param.getPage(), param.getSize()),
query() query()

View File

@@ -31,11 +31,11 @@ public class MkPointsUserRecordServiceImpl extends ServiceImpl<MkPointsUserRecor
@Override @Override
public Page<MkPointsUserRecord> pageByPointsUserId(Integer page, Integer size, Long mkPointsUserId) { public Page<MkPointsUserRecord> pageByPointsUserId(Integer page, Integer size, Long mkPointsUserId) {
if (mkPointsUserId == null) { if (mkPointsUserId == null) {
return new Page<>(); return PageUtil.emptyPage();
} }
ShopInfo shopInfo = shopInfoService.getById(StpKit.USER.getShopId()); ShopInfo shopInfo = shopInfoService.getById(StpKit.USER.getShopId());
if (shopInfo == null) { if (shopInfo == null) {
return new Page<>(); return PageUtil.emptyPage();
} }
Page<MkPointsUserRecord> pages = page(Page.of(page, size), Page<MkPointsUserRecord> pages = page(Page.of(page, size),
query().eq(MkPointsUserRecord::getMkPointsUserId, mkPointsUserId).orderBy(MkPointsUserRecord::getCreateTime, false)); query().eq(MkPointsUserRecord::getMkPointsUserId, mkPointsUserId).orderBy(MkPointsUserRecord::getCreateTime, false));
@@ -46,7 +46,7 @@ public class MkPointsUserRecordServiceImpl extends ServiceImpl<MkPointsUserRecor
@Override @Override
public Page<MkPointsUserRecord> getPointsUserRecord(Integer page, Integer size, Long mkPointsUserId) { public Page<MkPointsUserRecord> getPointsUserRecord(Integer page, Integer size, Long mkPointsUserId) {
if (mkPointsUserId == null) { if (mkPointsUserId == null) {
return new Page<>(); return PageUtil.emptyPage();
} }
PageHelper.startPage(page, size); PageHelper.startPage(page, size);
List<MkPointsUserRecord> record = mapper.getPointsUserRecord(mkPointsUserId); List<MkPointsUserRecord> record = mapper.getPointsUserRecord(mkPointsUserId);

View File

@@ -17,11 +17,13 @@ import com.czg.market.service.MkPointsUserRecordService;
import com.czg.market.service.MkPointsUserService; import com.czg.market.service.MkPointsUserService;
import com.czg.sa.StpKit; import com.czg.sa.StpKit;
import com.czg.service.market.mapper.MkPointsUserMapper; import com.czg.service.market.mapper.MkPointsUserMapper;
import com.czg.utils.PageUtil;
import com.mybatisflex.core.paginate.Page; import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.spring.service.impl.ServiceImpl; import com.mybatisflex.spring.service.impl.ServiceImpl;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.apache.dubbo.config.annotation.DubboReference; import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService; import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.transaction.annotation.Transactional;
import java.util.List; import java.util.List;
@@ -50,7 +52,7 @@ public class MkPointsUserServiceImpl extends ServiceImpl<MkPointsUserMapper, MkP
if (StrUtil.isNotBlank(phone)) { if (StrUtil.isNotBlank(phone)) {
ShopUser one = shopUserService.getOne(query().eq(ShopUser::getPhone, phone).eq(ShopUser::getMainShopId, mainIdByShopId)); ShopUser one = shopUserService.getOne(query().eq(ShopUser::getPhone, phone).eq(ShopUser::getMainShopId, mainIdByShopId));
if (one == null) { if (one == null) {
return new Page<>(); return PageUtil.emptyPage();
} }
shopUserId = one.getId(); shopUserId = one.getId();
} }
@@ -130,9 +132,6 @@ public class MkPointsUserServiceImpl extends ServiceImpl<MkPointsUserMapper, MkP
break; break;
case SUB: case SUB:
pointsUser.setPointBalance(pointsUser.getPointBalance() - points); pointsUser.setPointBalance(pointsUser.getPointBalance() - points);
if (pointsUser.getPointBalance() < 0) {
throw new CzgException("积分操作失败,积分不足");
}
points = -points; points = -points;
break; break;
default: default:
@@ -169,4 +168,49 @@ public class MkPointsUserServiceImpl extends ServiceImpl<MkPointsUserMapper, MkP
acUserMsgService.addUserMsg(msg); acUserMsgService.addUserMsg(msg);
return record.getId(); return record.getId();
} }
@Override
@Transactional
public void removePointByOrder(Long shopId, Long userId, Long orderId, String orderNo, String reason) {
MkPointsUser pointsUser = getPointsUser(shopId, null, userId);
MkPointsUserRecord one = pointsUserRecordService.getOne(query()
.eq(MkPointsUserRecord::getMkPointsUserId, pointsUser.getId())
.eq(MkPointsUserRecord::getShopId, shopId)
.eq(MkPointsUserRecord::getSourceId, orderId.toString())
.eq(MkPointsUserRecord::getFloatType, PointsConstant.ADD.getValue())
.orderBy(MkPointsUserRecord::getId, true)
);
if (one == null) {
return;
}
Long floatPoints = Math.abs(one.getFloatPoints());
pointsUser.setPointBalance(pointsUser.getPointBalance() - floatPoints);
saveOrUpdate(pointsUser);
MkPointsUserRecord record = MkPointsUserRecord.builder()
.mkPointsUserId(pointsUser.getId())
.shopId(pointsUser.getShopId())
.shopUserId(pointsUser.getShopUserId())
.floatType(PointsConstant.SUB.getValue())
.floatPoints(floatPoints)
.balancePoints(pointsUser.getPointBalance())
.sourceId(orderId.toString())
.content(reason)
.build();
boolean save = pointsUserRecordService.save(record);
if (!save) {
throw new CzgException("积分操作失败,积分记录保存失败");
}
AcUserMsg msg = new AcUserMsg()
.setUserId(pointsUser.getUserId())
.setShopId(shopId)
.setSourceId(orderId)
.setSourceType("order")
.setType("points")
.setReadStatus(0)
.setTitle("积分扣除")
.setContent(StrUtil.format("订单退款积分扣除提醒:{} 积分已扣除,订单号:{}", floatPoints, orderNo));
acUserMsgService.addUserMsg(msg);
}
} }

View File

@@ -110,6 +110,17 @@ public class MkShopConsumerCouponServiceImpl extends ServiceImpl<MkShopConsumerC
} }
} }
@Override
public void removeConsumerCoupon(Long shopId, Long userId, Long orderId) {
recordService.remove(query()
.eq(MkShopCouponRecord::getShopId, shopId)
.eq(MkShopCouponRecord::getUserId, userId)
.eq(MkShopCouponRecord::getSourceFlowId, orderId)
.eq(MkShopCouponRecord::getSource, "消费赠券")
);
}
@Override @Override
public MkShopConsumerCouponDTO getConsumerCouponById(Long id) { public MkShopConsumerCouponDTO getConsumerCouponById(Long id) {
AssertUtil.isNull(id, "ID不能为空"); AssertUtil.isNull(id, "ID不能为空");

View File

@@ -20,6 +20,7 @@ import com.czg.market.enums.PointsConstant;
import com.czg.market.service.*; import com.czg.market.service.*;
import com.czg.market.vo.*; import com.czg.market.vo.*;
import com.czg.utils.AssertUtil; import com.czg.utils.AssertUtil;
import com.czg.utils.FunUtils;
import com.mybatisflex.core.query.QueryWrapper; import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl; import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.czg.market.entity.MkShopRecharge; import com.czg.market.entity.MkShopRecharge;
@@ -45,6 +46,8 @@ public class MkShopRechargeServiceImpl extends ServiceImpl<MkShopRechargeMapper,
@Resource @Resource
private MkShopRechargeDetailService shopRechargeDetailService; private MkShopRechargeDetailService shopRechargeDetailService;
@Resource @Resource
private TbMemberConfigService memberConfigService;
@Resource
private ShopCouponService shopCouponService; private ShopCouponService shopCouponService;
@DubboReference @DubboReference
private ShopUserService shopUserService; private ShopUserService shopUserService;
@@ -159,7 +162,8 @@ public class MkShopRechargeServiceImpl extends ServiceImpl<MkShopRechargeMapper,
} }
@Override @Override
public void recharge(Long shopId, Long shopUserId, Long rechargeDetailId, BigDecimal amount, Long paymentId, String payType, ShopUserFlowBizEnum bizEnum) { public void recharge(Long shopId, Long shopUserId, Long rechargeDetailId, BigDecimal amount, Long paymentId,
String payType, ShopUserFlowBizEnum bizEnum, boolean isNoJoin) {
log.info("充值回调, 用户id: {}, 金额: {}, rechargeDetailId: {}", shopUserId, amount, rechargeDetailId); log.info("充值回调, 用户id: {}, 金额: {}, rechargeDetailId: {}", shopUserId, amount, rechargeDetailId);
ShopUser shopUser = shopUserService.getById(shopUserId); ShopUser shopUser = shopUserService.getById(shopUserId);
ShopUserMoneyEditDTO shopUserMoneyEditDTO = new ShopUserMoneyEditDTO() ShopUserMoneyEditDTO shopUserMoneyEditDTO = new ShopUserMoneyEditDTO()
@@ -168,7 +172,6 @@ public class MkShopRechargeServiceImpl extends ServiceImpl<MkShopRechargeMapper,
.setBizEnum(bizEnum) .setBizEnum(bizEnum)
.setRelationId(paymentId); .setRelationId(paymentId);
// 标准充值 // 标准充值
if (rechargeDetailId != null) { if (rechargeDetailId != null) {
MkShopRechargeDetail rechargeDetail = shopRechargeDetailService.getById(rechargeDetailId); MkShopRechargeDetail rechargeDetail = shopRechargeDetailService.getById(rechargeDetailId);
@@ -209,7 +212,9 @@ public class MkShopRechargeServiceImpl extends ServiceImpl<MkShopRechargeMapper,
shopUserMoneyEditDTO.setMoney(amount); shopUserMoneyEditDTO.setMoney(amount);
} }
shopUserService.updateMoney(shopUserMoneyEditDTO); shopUserService.updateMoney(shopUserMoneyEditDTO);
if (isNoJoin) {
FunUtils.transactionSafeRun(() -> memberConfigService.joinMemberByCondition(shopId, shopUser.getUserId(), shopUser));
}
} }
@Override @Override

View File

@@ -20,6 +20,7 @@ import com.czg.sa.StpKit;
import com.czg.service.market.mapper.PpPackageMapper; import com.czg.service.market.mapper.PpPackageMapper;
import com.czg.service.market.mapper.PpPackageOrderMapper; import com.czg.service.market.mapper.PpPackageOrderMapper;
import com.czg.utils.AssertUtil; import com.czg.utils.AssertUtil;
import com.czg.utils.PageUtil;
import com.mybatisflex.core.paginate.Page; import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper; import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.update.UpdateChain; import com.mybatisflex.core.update.UpdateChain;
@@ -168,7 +169,7 @@ public class PpPackageServiceImpl extends ServiceImpl<PpPackageMapper, PpPackage
Integer promotionSwitch = getPackagePromotionSwitch(shopId); Integer promotionSwitch = getPackagePromotionSwitch(shopId);
if (!isAdmin && SystemConstants.OneZero.ZERO == promotionSwitch) { if (!isAdmin && SystemConstants.OneZero.ZERO == promotionSwitch) {
log.info("没有开启套餐推广"); log.info("没有开启套餐推广");
return new Page<>(); return PageUtil.emptyPage();
} }
Long mainShopId = shopInfoService.getMainIdByShopId(shopId); Long mainShopId = shopInfoService.getMainIdByShopId(shopId);

View File

@@ -310,7 +310,7 @@ public class ShopCouponServiceImpl extends ServiceImpl<ShopCouponMapper, ShopCou
} }
return PageUtil.convert(new PageInfo<>(coupons)); return PageUtil.convert(new PageInfo<>(coupons));
} }
return new Page<>(); return PageUtil.emptyPage();
} }
@Override @Override

View File

@@ -11,7 +11,6 @@ import com.czg.account.entity.ShopUser;
import com.czg.account.service.ShopConfigService; import com.czg.account.service.ShopConfigService;
import com.czg.account.service.ShopInfoService; import com.czg.account.service.ShopInfoService;
import com.czg.account.service.ShopUserService; import com.czg.account.service.ShopUserService;
import com.czg.account.service.UserInfoService;
import com.czg.constant.TableValueConstant; import com.czg.constant.TableValueConstant;
import com.czg.exception.CzgException; import com.czg.exception.CzgException;
import com.czg.market.dto.MemberConfigDTO; import com.czg.market.dto.MemberConfigDTO;
@@ -25,7 +24,6 @@ import com.czg.market.enums.PointsConstant;
import com.czg.market.service.*; import com.czg.market.service.*;
import com.czg.market.vo.*; import com.czg.market.vo.*;
import com.czg.order.entity.OrderInfo; import com.czg.order.entity.OrderInfo;
import com.czg.order.entity.OrderPayment;
import com.czg.order.service.OrderPaymentService; import com.czg.order.service.OrderPaymentService;
import com.czg.service.market.enums.OrderStatusEnums; import com.czg.service.market.enums.OrderStatusEnums;
import com.czg.service.market.mapper.TbMemberConfigMapper; import com.czg.service.market.mapper.TbMemberConfigMapper;
@@ -59,8 +57,6 @@ public class TbMemberConfigServiceImpl extends ServiceImpl<TbMemberConfigMapper,
@Resource @Resource
private MemberLevelConfigService levelConfigService; private MemberLevelConfigService levelConfigService;
@DubboReference @DubboReference
private UserInfoService userInfoService;
@DubboReference
private ShopUserService shopUserService; private ShopUserService shopUserService;
@Resource @Resource
private OrderInfoService orderInfoService; private OrderInfoService orderInfoService;
@@ -121,21 +117,21 @@ public class TbMemberConfigServiceImpl extends ServiceImpl<TbMemberConfigMapper,
conditionMap.put("BIND_PHONE", StrUtil.isNotBlank(shopUserInfo.getPhone())); conditionMap.put("BIND_PHONE", StrUtil.isNotBlank(shopUserInfo.getPhone()));
break; break;
case "ORDER": case "ORDER":
conditionMap.put("ORDER", orderInfoService.count(new QueryWrapper().eq(OrderInfo::getShopId, shopUserInfo.getSourceShopId()).eq(OrderInfo::getUserId, shopUserInfo.getUserId()) conditionMap.put("ORDER", orderInfoService.count(query().eq(OrderInfo::getShopId, shopId).eq(OrderInfo::getUserId, shopUserInfo.getUserId())
.notIn(OrderInfo::getStatus, OrderStatusEnums.UNPAID.getCode(), OrderStatusEnums.CANCELLED.getCode())) >= Integer.parseInt(item.getValue())); .eq(OrderInfo::getStatus, OrderStatusEnums.DONE.getCode())) >= Integer.parseInt(item.getValue()));
break; break;
case "COST_AMOUNT": case "COST_AMOUNT":
conditionMap.put("COST_AMOUNT", orderInfoService.list(new QueryWrapper().eq(OrderInfo::getShopId, shopUserInfo.getSourceShopId()).eq(OrderInfo::getUserId, shopUserInfo.getUserId()) conditionMap.put("COST_AMOUNT", orderInfoService.getOneAs(query()
.notIn(OrderInfo::getStatus, OrderStatusEnums.UNPAID.getCode(), OrderStatusEnums.CANCELLED.getCode())) .select("IFNULL(sum(pay_amount), 0) as total_amount ")
.stream().map(OrderInfo::getPayAmount).reduce(BigDecimal.ZERO, BigDecimal::add).compareTo(new BigDecimal(item.getValue())) >= 0); .eq(OrderInfo::getShopId, shopId)
.eq(OrderInfo::getUserId, shopUserInfo.getUserId())
.eq(OrderInfo::getStatus, OrderStatusEnums.DONE.getCode()), BigDecimal.class)
.compareTo(new BigDecimal(item.getValue())) >= 0);
break; break;
case "RECHARGE_AMOUNT": case "RECHARGE_AMOUNT":
conditionMap.put("RECHARGE_AMOUNT", paymentService.list(new QueryWrapper().eq(OrderPayment::getShopId, shopUserInfo.getSourceShopId()) conditionMap.put("RECHARGE_AMOUNT", paymentService.countMemberInAmount(shopId, shopUserInfo.getId())
.eq(OrderPayment::getSourceId, shopUserInfo.getId()).isNotNull(OrderPayment::getTradeNumber)) .compareTo(new BigDecimal(item.getValue())) >= 0);
.stream().map(OrderPayment::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add).compareTo(new BigDecimal(item.getValue())) >= 0);
break; break;
default: default:
throw new CzgException("会员开通条件类型错误"); throw new CzgException("会员开通条件类型错误");
@@ -199,7 +195,10 @@ public class TbMemberConfigServiceImpl extends ServiceImpl<TbMemberConfigMapper,
memberConfig.setMemberPriceShopIdList(JSONObject.toJSONString(memberDTO.getMemberPriceShopIdList())); memberConfig.setMemberPriceShopIdList(JSONObject.toJSONString(memberDTO.getMemberPriceShopIdList()));
} }
shopConfigService.editStatusByShopIdList(memberConfig.getShopId(), memberConfig.getIsOpen().intValue() == 1 && memberConfig.getIsMemberPrice() == 1 ? 1 : 0, false, "is_member_price", shopConfigService.editStatusByShopIdList(memberConfig.getShopId(),
memberConfig.getIsOpen().intValue() == 1 && memberConfig.getIsMemberPrice() == 1 ? 1 : 0,
false,
"is_member_price",
"ALL".equals(memberConfig.getMemberPriceShopType()) ? "all" : "part", "ALL".equals(memberConfig.getMemberPriceShopType()) ? "all" : "part",
StrUtil.isNotBlank(memberConfig.getMemberPriceShopIdList()) ? JSONArray.parseArray(memberConfig.getMemberPriceShopIdList()).toList(Long.class) : new ArrayList<>()); StrUtil.isNotBlank(memberConfig.getMemberPriceShopIdList()) ? JSONArray.parseArray(memberConfig.getMemberPriceShopIdList()).toList(Long.class) : new ArrayList<>());
@@ -304,6 +303,7 @@ public class TbMemberConfigServiceImpl extends ServiceImpl<TbMemberConfigMapper,
return false; return false;
} }
ShopUser upShopUser = new ShopUser(); ShopUser upShopUser = new ShopUser();
upShopUser.setId(shopUser.getId());
if (shopUser.getExperience() == null) { if (shopUser.getExperience() == null) {
upShopUser.setExperience(0L); upShopUser.setExperience(0L);
} }
@@ -337,13 +337,11 @@ public class TbMemberConfigServiceImpl extends ServiceImpl<TbMemberConfigMapper,
} }
if (levelVO.getCycleRewardCouponList() != null && !levelVO.getCycleRewardCouponList().isEmpty()) { if (levelVO.getCycleRewardCouponList() != null && !levelVO.getCycleRewardCouponList().isEmpty()) {
levelVO.getCycleRewardCouponList().forEach(item -> { levelVO.getCycleRewardCouponList().forEach(item ->
shopCouponRecordService.grant(shopUser.getMainShopId(), new MkRewardCouponDTO().setCouponId(item.getCoupon().getId()) shopCouponRecordService.grant(shopUser.getMainShopId(), new MkRewardCouponDTO().setCouponId(item.getCoupon().getId())
.setNum(item.getNum()) .setNum(item.getNum())
.setUserId(shopUser.getUserId()) .setUserId(shopUser.getUserId())
.setShopId(shopUser.getMainShopId()), "购买会员赠券"); .setShopId(shopUser.getMainShopId()), "购买会员赠券"));
});
} }
} }
@@ -381,16 +379,17 @@ public class TbMemberConfigServiceImpl extends ServiceImpl<TbMemberConfigMapper,
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public boolean joinMemberByCondition(Long shopId, Long userId, ShopUser shopUser) { public boolean joinMemberByCondition(Long shopId, Long userId, ShopUser shopUser) {
MemberConfigVO memberConfigVO = detail(shopId);
if (!memberConfigVO.getIsOpen().equals(1L)) {
log.info("超级会员未开启, 店铺id: {}", shopId);
return false;
}
if (shopUser == null) { if (shopUser == null) {
log.warn("用户不存在, 店铺id: {}, 用户id: {}", shopId, userId); log.warn("用户不存在, 店铺id: {}, 用户id: {}", shopId, userId);
return false; return false;
} }
if (shopUser.getStartTime() != null && shopUser.getEndTime() != null && DateUtil.isIn(DateUtil.date(), DateUtil.date(shopUser.getStartTime()), DateUtil.date(shopUser.getEndTime()))) { if (shopUser.getIsVip() == 1 && shopUser.getStartTime() != null && shopUser.getEndTime() != null &&
DateUtil.isIn(DateUtil.date(), DateUtil.date(shopUser.getStartTime()), DateUtil.date(shopUser.getEndTime()))) {
return false;
}
MemberConfigVO memberConfigVO = detail(shopId);
if (!memberConfigVO.getIsOpen().equals(1L)) {
log.info("超级会员未开启, 店铺id: {}", shopId);
return false; return false;
} }
MemberLevelConfig levelConfig = levelConfigService.getOne(new QueryWrapper().eq(MemberLevelConfig::getShopId, shopId).orderBy(MemberLevelConfig::getExperienceValue, true).limit(1)); MemberLevelConfig levelConfig = levelConfigService.getOne(new QueryWrapper().eq(MemberLevelConfig::getShopId, shopId).orderBy(MemberLevelConfig::getExperienceValue, true).limit(1));
@@ -411,16 +410,14 @@ public class TbMemberConfigServiceImpl extends ServiceImpl<TbMemberConfigMapper,
boolean canOpen = switch (item.getCode()) { boolean canOpen = switch (item.getCode()) {
case "BIND_PHONE" -> StrUtil.isNotBlank(shopUser.getPhone()); case "BIND_PHONE" -> StrUtil.isNotBlank(shopUser.getPhone());
case "ORDER" -> case "ORDER" ->
orderInfoService.count(new QueryWrapper().eq(OrderInfo::getShopId, shopUser.getSourceShopId()).eq(OrderInfo::getUserId, shopUser.getUserId()) orderInfoService.count(query().eq(OrderInfo::getShopId, shopId).eq(OrderInfo::getUserId, shopUser.getUserId())
.notIn(OrderInfo::getStatus, OrderStatusEnums.UNPAID.getCode(), OrderStatusEnums.CANCELLED.getCode())) >= Integer.parseInt(item.getValue()); .eq(OrderInfo::getStatus, OrderStatusEnums.DONE.getCode())) >= Integer.parseInt(item.getValue());
case "COST_AMOUNT" -> case "COST_AMOUNT" ->
orderInfoService.list(new QueryWrapper().eq(OrderInfo::getShopId, shopUser.getSourceShopId()).eq(OrderInfo::getUserId, shopUser.getUserId()) orderInfoService.getOneAs(query().select("IFNULL(sum(pay_amount), 0) as total_amount").eq(OrderInfo::getShopId, shopId).eq(OrderInfo::getUserId, shopUser.getUserId())
.notIn(OrderInfo::getStatus, OrderStatusEnums.UNPAID.getCode(), OrderStatusEnums.CANCELLED.getCode())) .eq(OrderInfo::getStatus, OrderStatusEnums.DONE.getCode()), BigDecimal.class)
.stream().map(OrderInfo::getPayAmount).reduce(BigDecimal.ZERO, BigDecimal::add).compareTo(new BigDecimal(item.getValue())) >= 0; .compareTo(new BigDecimal(item.getValue())) >= 0;
case "RECHARGE_AMOUNT" -> case "RECHARGE_AMOUNT" -> paymentService.countMemberInAmount(shopId, shopUser.getId())
paymentService.list(new QueryWrapper().eq(OrderPayment::getShopId, shopUser.getSourceShopId()) .compareTo(new BigDecimal(item.getValue())) >= 0;
.eq(OrderPayment::getSourceId, shopUser.getId()).isNotNull(OrderPayment::getTradeNumber))
.stream().map(OrderPayment::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add).compareTo(new BigDecimal(item.getValue())) >= 0;
default -> throw new CzgException("会员开通条件类型错误"); default -> throw new CzgException("会员开通条件类型错误");
}; };
if (!canOpen) { if (!canOpen) {
@@ -431,10 +428,12 @@ public class TbMemberConfigServiceImpl extends ServiceImpl<TbMemberConfigMapper,
ShopUser upShopUser = new ShopUser(); ShopUser upShopUser = new ShopUser();
upShopUser.setId(shopUser.getId()); upShopUser.setId(shopUser.getId());
upShopUser.setMemberLevelId(levelConfig.getId()); upShopUser.setMemberLevelId(levelConfig.getId());
upShopUser.setStartTime(DateUtil.date().toLocalDateTime()); upShopUser.setStartTime(LocalDateTime.now());
upShopUser.setEndTime(upShopUser.getStartTime().plusDays(20000));
upShopUser.setEndTime(shopUser.getStartTime().plusDays(20000));
upShopUser.setIsVip(1); upShopUser.setIsVip(1);
if (shopUser.getJoinTime() != null) {
upShopUser.setJoinTime(LocalDateTime.now());
}
upShopUser.setOpenType("CONDITION"); upShopUser.setOpenType("CONDITION");
return shopUserService.updateById(upShopUser); return shopUserService.updateById(upShopUser);
} }
@@ -557,20 +556,27 @@ public class TbMemberConfigServiceImpl extends ServiceImpl<TbMemberConfigMapper,
@Override @Override
@Transactional @Transactional
public MemberDetailVO getUserDetail(Long userId, Long shopId) { public MemberDetailVO getUserDetail(Long userId, Long shopId) {
Long mainIdByShopId = shopInfoService.getMainIdByShopId(shopId); ShopInfo shopInfo = shopInfoService.getById(shopId);
Long mainIdByShopId = shopInfo.getMainId() == null ? shopId : shopInfo.getMainId();
ShopUser shopUser = shopUserService.getOne(new QueryWrapper().eq(ShopUser::getUserId, userId).eq(ShopUser::getMainShopId, mainIdByShopId)); ShopUser shopUser = shopUserService.getOne(new QueryWrapper().eq(ShopUser::getUserId, userId).eq(ShopUser::getMainShopId, mainIdByShopId));
MemberLevelVO levelVO = null; MemberLevelVO levelVO = null;
if (shopUser.getMemberLevelId() != null) { if (shopUser.getMemberLevelId() != null) {
levelVO = levelConfigService.detail(shopUser.getMemberLevelId()); levelVO = levelConfigService.detail(shopUser.getMemberLevelId());
} }
TbMemberConfig memberConfig = getOne(new QueryWrapper().eq(TbMemberConfig::getShopId, shopId)); MemberConfigVO memberConfig = detail(shopId);
long nextLevelExperience = 0;
if (memberConfig != null && memberConfig.getIsOpen() == 1) {
if ("CONDITION".equals(memberConfig.getOpenType())) { if ("CONDITION".equals(memberConfig.getOpenType())) {
joinMemberByCondition(shopId, userId, shopUser); joinMemberByCondition(shopId, userId, shopUser);
} }
MemberLevelConfig nextLevel = levelConfigService.getOne(new QueryWrapper()
ShopInfo shopInfo = shopInfoService.getById(shopUser.getSourceShopId()); .eq(MemberLevelConfig::getShopId, mainIdByShopId)
MemberLevelConfig nextLevel = levelConfigService.getOne(new QueryWrapper().eq(MemberLevelConfig::getShopId, shopId).ge(MemberLevelConfig::getExperienceValue, shopUser.getExperience()) .ge(MemberLevelConfig::getExperienceValue, shopUser.getExperience())
.ne(MemberLevelConfig::getId, shopUser.getMemberLevelId()).orderBy(MemberLevelConfig::getExperienceValue, true)); .ne(MemberLevelConfig::getId, shopUser.getMemberLevelId()).orderBy(MemberLevelConfig::getExperienceValue, true));
if (nextLevel != null) {
nextLevelExperience = nextLevel.getExperienceValue() - shopUser.getExperience();
}
}
return new MemberDetailVO() return new MemberDetailVO()
.setMemberCircleName(shopUser.getMemberCircleName()) .setMemberCircleName(shopUser.getMemberCircleName())
.setMemberCircleReward(shopUser.getMemberCircleReward()) .setMemberCircleReward(shopUser.getMemberCircleReward())
@@ -579,6 +585,6 @@ public class TbMemberConfigServiceImpl extends ServiceImpl<TbMemberConfigMapper,
.setMemberLevel(levelVO) .setMemberLevel(levelVO)
.setExperience(shopUser.getExperience()) .setExperience(shopUser.getExperience())
.setEndTime(shopUser.getEndTime()) .setEndTime(shopUser.getEndTime())
.setNextExperienceValue(nextLevel == null ? 0 : nextLevel.getExperienceValue() - shopUser.getExperience()); .setNextExperienceValue(nextLevelExperience);
} }
} }

View File

@@ -64,7 +64,7 @@ public class WxServiceImpl extends BaseWx {
@Override @Override
public void init() { public void init() {
// 商户小程序参数 // 商户小程序参数
Map<String, String> shopMiniKeyMap = paramsService.getParamsByMap("shopMiniKeys", shopMiniKeys); Map<String, String> shopMiniKeyMap = paramsService.getParamsByMap("shop_mini_key_set", ParamCodeCst.SHOP_MINI_KEY_SET);
// 小程序id // 小程序id
config.appId = shopMiniKeyMap.get(ParamCodeCst.Wechat.Mini.SHOP_WX_APP_ID); config.appId = shopMiniKeyMap.get(ParamCodeCst.Wechat.Mini.SHOP_WX_APP_ID);
@@ -72,7 +72,7 @@ public class WxServiceImpl extends BaseWx {
config.appSecret = shopMiniKeyMap.get(ParamCodeCst.Wechat.Mini.SHOP_WX_SECRETE); config.appSecret = shopMiniKeyMap.get(ParamCodeCst.Wechat.Mini.SHOP_WX_SECRETE);
// 微信支付参数 // 微信支付参数
Map<String, String> payKeyMap = paramsService.getParamsByMap("payKeys", PAY_KEYS); Map<String, String> payKeyMap = paramsService.getParamsByMap("pay_key_set", ParamCodeCst.PAY_KEY_SET);
config.certPath = ""; config.certPath = "";
// 微信支付公钥 // 微信支付公钥
config.pubKey = payKeyMap.get(ParamCodeCst.Wechat.Pay.WX_PUB_KEY); config.pubKey = payKeyMap.get(ParamCodeCst.Wechat.Pay.WX_PUB_KEY);

View File

@@ -15,10 +15,7 @@
left join tb_shop_info s on o.shop_id = s.id left join tb_shop_info s on o.shop_id = s.id
left join pp_package p on o.package_id = p.id left join pp_package p on o.package_id = p.id
left join tb_user_info u on o.user_id = u.id left join tb_user_info u on o.user_id = u.id
where 1=1 where o.shop_id = #{shopId}
<if test="shopId != null">
and o.shop_id = #{shopId}
</if>
<choose> <choose>
<!-- userId为空时拼接 and o.status != 'ing' --> <!-- userId为空时拼接 and o.status != 'ing' -->
<when test="userId == null or userId == ''"> <when test="userId == null or userId == ''">

View File

@@ -151,7 +151,9 @@ public class GbOrderServiceImpl extends ServiceImpl<GbOrderMapper, GbOrder> impl
q.eq(GbOrderDetail::getStatus, "待成团").or(GbOrderDetail::getStatus).eq("退款中"); q.eq(GbOrderDetail::getStatus, "待成团").or(GbOrderDetail::getStatus).eq("退款中");
}); });
queryWrapper1.eq(GbOrderDetail::getGroupOrderNo, ing.getGroupOrderNo()); queryWrapper1.eq(GbOrderDetail::getGroupOrderNo, ing.getGroupOrderNo());
if (userId != null) {
queryWrapper1.eq(GbOrderDetail::getUserId, userId); queryWrapper1.eq(GbOrderDetail::getUserId, userId);
}
boolean exists = detailService.exists(queryWrapper1); boolean exists = detailService.exists(queryWrapper1);
if (exists) { if (exists) {
continue; continue;

View File

@@ -162,7 +162,7 @@ public class OrderInfoCustomServiceImpl implements OrderInfoCustomService {
.like(OrderDetail::getProductName, productName); .like(OrderDetail::getProductName, productName);
like = orderDetailService.listAs(queryWrapper, Long.class); like = orderDetailService.listAs(queryWrapper, Long.class);
if (CollUtil.isEmpty(like)) { if (CollUtil.isEmpty(like)) {
return new Page<>(); return PageUtil.emptyPage();
} }
} }
QueryWrapper queryWrapper = PageUtil.buildSortQueryWrapper(); QueryWrapper queryWrapper = PageUtil.buildSortQueryWrapper();
@@ -1060,8 +1060,7 @@ public class OrderInfoCustomServiceImpl implements OrderInfoCustomService {
distributionUserService.costUpgradeLevelBefore(orderInfo.getUserId(), orderInfo.getShopId()); distributionUserService.costUpgradeLevelBefore(orderInfo.getUserId(), orderInfo.getShopId());
// 分销奖励 // 分销奖励
distributionUserService.distribute(orderInfo.getId(), orderInfo.getOrderNo(), payment.getAmount(), orderInfo.getUserId(), orderInfo.getShopId(), "order"); distributionUserService.distribute(orderInfo.getId(), orderInfo.getOrderNo(), payment.getAmount(), orderInfo.getUserId(), orderInfo.getShopId(), "order");
} } else if (PayTypeConstants.SourceType.MEMBER_IN.equals(payment.getSourceType()) || PayTypeConstants.SourceType.FREE.equals(payment.getSourceType())) {
else if (PayTypeConstants.SourceType.MEMBER_IN.equals(payment.getSourceType()) || PayTypeConstants.SourceType.FREE.equals(payment.getSourceType())) {
boolean isFree = PayTypeConstants.SourceType.FREE.equals(payment.getSourceType()); boolean isFree = PayTypeConstants.SourceType.FREE.equals(payment.getSourceType());
ShopUser shopUser = shopUserService.getById(payment.getSourceId()); ShopUser shopUser = shopUserService.getById(payment.getSourceId());
OrderInfo orderInfo = null; OrderInfo orderInfo = null;
@@ -1089,99 +1088,41 @@ public class OrderInfoCustomServiceImpl implements OrderInfoCustomService {
.setRelationId(orderInfo.getId()) .setRelationId(orderInfo.getId())
.setMoney(BigDecimal.valueOf(czgCallBackDto.getAmount()).divide(BigDecimal.valueOf(100), 2, RoundingMode.DOWN)); .setMoney(BigDecimal.valueOf(czgCallBackDto.getAmount()).divide(BigDecimal.valueOf(100), 2, RoundingMode.DOWN));
shopUserService.updateMoney(shopUserMoneyEditDTO); shopUserService.updateMoney(shopUserMoneyEditDTO);
OrderInfo orderInfo1 = new OrderInfo(); upOrderInfo(orderInfo, BigDecimal.ZERO,
orderInfo1.setId(orderInfo.getId()); LocalDateTime.now(), null, PayEnums.FREE_PAY);
orderInfo1.setIsFreeDine(1);
orderInfo1.setStatus(OrderStatusEnums.DONE.getCode());
orderInfo1.setPayAmount(BigDecimal.ZERO);
orderInfo1.setPaidTime(LocalDateTime.now());
orderInfo1.setPayType(PayEnums.FREE_PAY.getValue());
orderInfoService.updateById(orderInfo1);
orderDetailService.updateOrderDetailStatus(orderInfo.getId(), OrderStatusEnums.DONE.getCode());
redisService.del(RedisCst.classKeyExpired.EXPIRED_ORDER + orderInfo.getId());
} }
} else { } else {
shopRechargeService.recharge(payment.getShopId(), payment.getSourceId(), payment.getRelatedId(),
BigDecimal.valueOf(czgCallBackDto.getAmount()).divide(BigDecimal.valueOf(100), 2, RoundingMode.DOWN), payment.getId(), payment.getSourceType(), bizEnum);
//充值并支付 ↓ //充值并支付 ↓
orderInfo = orderInfoService.getOne(new QueryWrapper() orderInfo = orderInfoService.getOne(new QueryWrapper()
.eq(OrderInfo::getPayOrderId, payment.getId()) .eq(OrderInfo::getPayOrderId, payment.getId())
.eq(OrderInfo::getPayType, PayEnums.VIP_PAY.getValue())); .eq(OrderInfo::getPayType, PayEnums.VIP_PAY.getValue()));
if (orderInfo != null) { if (orderInfo != null) {
OrderInfo upOrderInfo = new OrderInfo()
.setId(orderInfo.getId())
.setPayType(PayEnums.VIP_PAY.getValue())
.setPaidTime(LocalDateTime.now())
.setPayAmount(orderInfo.getOrderAmount())
.setStatus(OrderStatusEnums.DONE.getCode());
orderInfoService.updateById(upOrderInfo);
orderDetailService.updateOrderDetailStatus(orderInfo.getId(), OrderStatusEnums.DONE.getCode());
ShopUserMoneyEditDTO shopUserMoneyEditDTO = new ShopUserMoneyEditDTO() ShopUserMoneyEditDTO shopUserMoneyEditDTO = new ShopUserMoneyEditDTO()
.setId(shopUser.getId()) .setId(shopUser.getId())
.setType(0) .setType(0)
.setBizEnum(ShopUserFlowBizEnum.ORDER_PAY) .setBizEnum(ShopUserFlowBizEnum.ORDER_PAY)
.setRelationId(orderInfo.getId()) .setRelationId(orderInfo.getId())
.setMoney(orderInfo.getOrderAmount()); .setMoney(orderInfo.getOrderAmount());
shopUserService.updateMoney(shopUserMoneyEditDTO); shopUserService.updateMoney(shopUserMoneyEditDTO);
redisService.del(RedisCst.classKeyExpired.EXPIRED_ORDER + orderInfo.getId()); upOrderInfo(orderInfo, orderInfo.getOrderAmount(),
LocalDateTime.now(), null, PayEnums.VIP_PAY);
// 发放成长值
shopUser = shopUserService.getById(shopUser);
//充值
memberConfigService.deliver(shopUser,
TableValueConstant.MemberExpFlow.Type.RECHARGE,
BigDecimal.valueOf(czgCallBackDto.getAmount()).divide(BigDecimal.valueOf(100), 2, RoundingMode.DOWN), null, orderInfo.getId());
if (TransactionSynchronizationManager.isSynchronizationActive()) {
OrderInfo finalOrderInfo = orderInfo;
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
@Override
public void afterCommit() {
// 事务成功提交后执行消息发送
String printParam = finalOrderInfo.getId() + "_" + (!"after-pay".equals(finalOrderInfo.getPayMode()) ? 1 : 0) + "_1";
rabbitPublisher.sendOrderPrintMsg(printParam, finalOrderInfo.getIsPrint() == 1);
// log.info("订单{}事务提交后,发送打印消息", orderId);
} }
}); shopRechargeService.recharge(payment.getShopId(), payment.getSourceId(), payment.getRelatedId(),
} else { BigDecimal.valueOf(czgCallBackDto.getAmount()).divide(BigDecimal.valueOf(100), 2, RoundingMode.DOWN),
// 非事务环境下直接发送(兼容无事务场景) payment.getId(), payment.getSourceType(), bizEnum, orderInfo == null);
String printParam = orderInfo.getId() + "_" + (!"after-pay".equals(orderInfo.getPayMode()) ? 1 : 0) + "_1";
rabbitPublisher.sendOrderPrintMsg(printParam, orderInfo.getIsPrint() == 1);
// log.info("非事务环境下,直接发送订单{}打印消息", orderId);
} }
} }
} } else if (PayTypeConstants.SourceType.MEMBER_PAY.equals(payment.getSourceType())) {
}
// 分销奖励
// if (shopUser != null) {
// distributionUserService.distribute(payment.getId(), payment.getOrderNo(), payment.getAmount(), shopUser.getUserId(), payment.getShopId(), "recharge");
// }
// if (orderInfo != null) {
// distributionUserService.distribute(payment.getId(), payment.getOrderNo(), payment.getAmount(), orderInfo.getUserId(), payment.getShopId(), "recharge");
// }
}
else if (PayTypeConstants.SourceType.MEMBER_PAY.equals(payment.getSourceType())) {
//购买会员 //购买会员
ShopUser shopUser = shopUserService.getById(payment.getSourceId()); ShopUser shopUser = shopUserService.getById(payment.getSourceId());
memberConfigService.joinMember(payment.getShopId(), shopUser.getUserId(), payment.getRelatedId()); memberConfigService.joinMember(payment.getShopId(), shopUser.getUserId(), payment.getRelatedId());
// 充值赠送积分 } else if (PayTypeConstants.SourceType.DISTRIBUTION.equals(payment.getSourceType())) {
// memberConfigService.deliver(shopUser.getMainShopId(), shopUser.getUserId(), TableValueConstant.MemberExpFlow.Type.COST, payment.getAmount(), null, payment.getId());
// 分销员开通
}
else if (PayTypeConstants.SourceType.DISTRIBUTION.equals(payment.getSourceType())) {
distributionUserService.open(payment.getSourceId(), payment.getAmount(), payment.getShopId(), payment.getId()); distributionUserService.open(payment.getSourceId(), payment.getAmount(), payment.getShopId(), payment.getId());
} } else if (PayTypeConstants.SourceType.POINT.equals(payment.getSourceType())) {
else if (PayTypeConstants.SourceType.POINT.equals(payment.getSourceType())) {
goodPayService.payCallBack(payment.getSourceId(), payment.getId()); goodPayService.payCallBack(payment.getSourceId(), payment.getId());
} } else if (PayTypeConstants.SourceType.WARE.equals(payment.getSourceType())) {
else if (PayTypeConstants.SourceType.WARE.equals(payment.getSourceType())) {
gbOrderService.payCallBack(payment.getSourceId(), payment.getId()); gbOrderService.payCallBack(payment.getSourceId(), payment.getId());
} } else if (PayTypeConstants.SourceType.PP.equals(payment.getSourceType())) {
else if (PayTypeConstants.SourceType.PP.equals(payment.getSourceType())) {
ppPackageOrderService.paySuccess(payment.getSourceId(), payment.getId()); ppPackageOrderService.paySuccess(payment.getSourceId(), payment.getId());
} }
} }
@@ -1306,14 +1247,14 @@ public class OrderInfoCustomServiceImpl implements OrderInfoCustomService {
shopUserUseInfo(orderInfo, shopUser); shopUserUseInfo(orderInfo, shopUser);
// 后续 赠送等功能 挂账支付不赠送 // 后续 赠送等功能 挂账支付不赠送
if (!orderInfo.getPayType().equals(PayEnums.CREDIT_PAY.getValue())) { if (!orderInfo.getPayType().equals(PayEnums.CREDIT_PAY.getValue())) {
if (!orderInfo.getPayType().equals(PayEnums.FREE_PAY.getValue())) {
FunUtils.safeRunVoid(() -> consumerCouponService.receiveConsumerCoupon(shopUser.getSourceShopId(), orderInfo.getId(), FunUtils.safeRunVoid(() -> consumerCouponService.receiveConsumerCoupon(shopUser.getSourceShopId(), orderInfo.getId(),
orderInfo.getPayAmount(), shopUser.getUserId(), shopUser.getId()), "订单{}消费赠券失败", orderInfo.getId()); orderInfo.getPayAmount(), shopUser.getUserId(), shopUser.getId()), "订单{}消费赠券失败", orderInfo.getId());
FunUtils.safeRunVoid(() -> pointsConfigService.consumeAwardPoints(shopUser, orderInfo), "订单{}赠送积分失败", orderInfo.getId()); FunUtils.safeRunVoid(() -> pointsConfigService.consumeAwardPoints(shopUser, orderInfo), "订单{}赠送积分失败", orderInfo.getId());
FunUtils.safeRunVoid(() -> consumeCashbackService.cashback(orderInfo.getShopId(), shopUser.getUserId(), FunUtils.safeRunVoid(() -> consumeCashbackService.cashback(orderInfo.getShopId(), shopUser.getUserId(),
orderInfo.getPayAmount(), orderInfo.getId(), orderInfo.getOrderNo()), "订单{}消费返现失败", orderInfo.getId()); orderInfo.getPayAmount(), orderInfo.getId(), orderInfo.getOrderNo()), "订单{}消费返现失败", orderInfo.getId());
}
FunUtils.safeRunVoid(() -> { FunUtils.safeRunVoid(() -> {
if (shopUser.getIsVip().equals(0)) { if (shopUser.getIsVip().equals(0)) {
// 消费累计成为会员的情况 // 消费累计成为会员的情况

View File

@@ -1,11 +1,14 @@
package com.czg.service.order.service.impl; package com.czg.service.order.service.impl;
import com.mybatisflex.spring.service.impl.ServiceImpl; import com.czg.constants.PayTypeConstants;
import com.czg.order.entity.OrderPayment; import com.czg.order.entity.OrderPayment;
import com.czg.order.service.OrderPaymentService; import com.czg.order.service.OrderPaymentService;
import com.czg.service.order.mapper.OrderPaymentMapper; import com.czg.service.order.mapper.OrderPaymentMapper;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import org.apache.dubbo.config.annotation.DubboService; import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
/** /**
* 支付详情 服务层实现。 * 支付详情 服务层实现。
@@ -14,6 +17,15 @@ import org.springframework.stereotype.Service;
* @since 2025-02-15 * @since 2025-02-15
*/ */
@DubboService @DubboService
public class OrderPaymentServiceImpl extends ServiceImpl<OrderPaymentMapper, OrderPayment> implements OrderPaymentService{ public class OrderPaymentServiceImpl extends ServiceImpl<OrderPaymentMapper, OrderPayment> implements OrderPaymentService {
@Override
public BigDecimal countMemberInAmount(Long shopId, Long shopUserId) {
return getOneAs(QueryWrapper.create().select("sum(amount)")
.eq(OrderPayment::getShopId, 143)
.eq(OrderPayment::getSourceType, PayTypeConstants.SourceType.MEMBER_IN)
.eq(OrderPayment::getPayType, PayTypeConstants.PayType.PAY)
.eq(OrderPayment::getSourceId, 127452)
.eq(OrderPayment::getPayStatus, PayTypeConstants.PayStatus.SUCCESS), BigDecimal.class);
}
} }

View File

@@ -24,6 +24,7 @@ import com.czg.market.dto.MemberOrderDTO;
import com.czg.market.entity.MemberOrder; import com.czg.market.entity.MemberOrder;
import com.czg.market.entity.MkShopCouponRecord; import com.czg.market.entity.MkShopCouponRecord;
import com.czg.market.entity.MkShopRechargeDetail; import com.czg.market.entity.MkShopRechargeDetail;
import com.czg.market.enums.PointsConstant;
import com.czg.market.service.*; import com.czg.market.service.*;
import com.czg.market.vo.MkShopRechargeVO; import com.czg.market.vo.MkShopRechargeVO;
import com.czg.order.dto.CheckOrderPay; import com.czg.order.dto.CheckOrderPay;
@@ -51,12 +52,14 @@ import com.czg.service.order.service.PayService;
import com.czg.system.service.SysParamsService; import com.czg.system.service.SysParamsService;
import com.czg.utils.AssertUtil; import com.czg.utils.AssertUtil;
import com.czg.utils.CzgRandomUtils; import com.czg.utils.CzgRandomUtils;
import com.czg.utils.FunUtils;
import com.mybatisflex.core.query.QueryWrapper; import com.mybatisflex.core.query.QueryWrapper;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import lombok.NonNull; import lombok.NonNull;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference; import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@@ -116,9 +119,15 @@ public class PayServiceImpl implements PayService {
@Resource @Resource
private MkShopRechargeDetailService shopRechargeDetailService; private MkShopRechargeDetailService shopRechargeDetailService;
@Resource @Resource
private TbMemberConfigService memberConfigService;
@Resource
private MkDistributionUserService distributionUserService; private MkDistributionUserService distributionUserService;
@Resource
private MkShopConsumerCouponService consumerCouponService;
@Resource
private MkPointsUserService mkPointsUserService;
@Resource
private MkConsumeCashbackService consumeCashbackService;
@Resource
private MkPointsConfigService pointsConfigService;
private final BigDecimal MONEY_RATE = new BigDecimal("100"); private final BigDecimal MONEY_RATE = new BigDecimal("100");
@@ -152,7 +161,6 @@ public class PayServiceImpl implements PayService {
throw new CzgException("该店铺未启用霸王餐"); throw new CzgException("该店铺未启用霸王餐");
} }
CheckOrderPay checkOrderPay = payParam.getCheckOrderPay(); CheckOrderPay checkOrderPay = payParam.getCheckOrderPay();
// CheckOrderPay checkOrderPay = BeanUtil.copyProperties(payParam, CheckOrderPay.class);
OrderInfo orderInfo = orderInfoCustomService.checkOrderPay(checkOrderPay.setFreeDine(true).setWithCoupon(freeConfig.getWithCoupon()).setWithPoints(freeConfig.getWithPoints())); OrderInfo orderInfo = orderInfoCustomService.checkOrderPay(checkOrderPay.setFreeDine(true).setWithCoupon(freeConfig.getWithCoupon()).setWithPoints(freeConfig.getWithPoints()));
payParam.setAmount(orderInfo.getOrderAmount().multiply(BigDecimal.valueOf(freeConfig.getRechargeTimes()))); payParam.setAmount(orderInfo.getOrderAmount().multiply(BigDecimal.valueOf(freeConfig.getRechargeTimes())));
return true; return true;
@@ -245,14 +253,9 @@ public class PayServiceImpl implements PayService {
orderInfo.setRemark(payParam.getCheckOrderPay().getRemark()); orderInfo.setRemark(payParam.getCheckOrderPay().getRemark());
} }
// log.info("发放经验值");
// memberConfigService.deliver(shopUser, TableValueConstant.MemberExpFlow.Type.COST, orderInfo.getOrderAmount(), null, orderInfo.getId());
Long flowId = shopUserService.updateMoney(shopUserMoneyEditDTO); Long flowId = shopUserService.updateMoney(shopUserMoneyEditDTO);
orderInfoCustomService.upOrderInfo(orderInfo, orderInfo.getOrderAmount(), orderInfoCustomService.upOrderInfo(orderInfo, orderInfo.getOrderAmount(),
LocalDateTime.now(), flowId, PayEnums.VIP_PAY); LocalDateTime.now(), flowId, PayEnums.VIP_PAY);
return CzgResult.success(); return CzgResult.success();
} }
@@ -261,9 +264,6 @@ public class PayServiceImpl implements PayService {
OrderInfo orderInfo = checkPay(payParam.getCheckOrderPay()); OrderInfo orderInfo = checkPay(payParam.getCheckOrderPay());
ShopInfo shopInfo = shopInfoService.getById(payParam.getShopId()); ShopInfo shopInfo = shopInfoService.getById(payParam.getShopId());
AssertUtil.isNull(shopInfo, "店铺不存在"); AssertUtil.isNull(shopInfo, "店铺不存在");
// if (!shopInfo.getIsAccountPay().equals(1)) {
// return CzgResult.failure("支付失败,店铺暂未开启会员余额支付。");
// }
AssertUtil.isNull(payParam.getShopUserId(), "请选择付款人后重试"); AssertUtil.isNull(payParam.getShopUserId(), "请选择付款人后重试");
ShopUser shopUser = shopUserService.getById(payParam.getShopUserId()); ShopUser shopUser = shopUserService.getById(payParam.getShopUserId());
AssertUtil.isNull(shopUser, "支付失败 该店铺用户不存在"); AssertUtil.isNull(shopUser, "支付失败 该店铺用户不存在");
@@ -427,15 +427,16 @@ public class PayServiceImpl implements PayService {
return CzgResult.failure("支付密码错误"); return CzgResult.failure("支付密码错误");
} }
} }
if (shopUser.getIsVip().equals(0)) { // if (shopUser.getIsVip().equals(0)) {
//更新会员 // //更新会员
ShopUser updateInfo = new ShopUser(); // ShopUser updateInfo = new ShopUser();
updateInfo.setIsVip(1); // updateInfo.setIsVip(1);
updateInfo.setJoinTime(LocalDateTime.now()); // updateInfo.setJoinTime(LocalDateTime.now());
updateInfo.setId(payParam.getShopUserId()); // updateInfo.setId(payParam.getShopUserId());
shopUserService.updateById(updateInfo); // shopUserService.updateById(updateInfo);
} // }
shopRechargeService.recharge(shopUser.getMainShopId(), shopUser.getId(), payParam.getRechargeDetailId(), payParam.getAmount(), null, "cash", ShopUserFlowBizEnum.CASH_IN); shopRechargeService.recharge(shopUser.getMainShopId(), shopUser.getId(), payParam.getRechargeDetailId(),
payParam.getAmount(), null, "cash", ShopUserFlowBizEnum.CASH_IN, true);
return CzgResult.success(); return CzgResult.success();
} }
@@ -687,6 +688,10 @@ public class PayServiceImpl implements PayService {
if (orderInfo.getStatus().equals(OrderStatusEnums.CANCELLED.getCode())) { if (orderInfo.getStatus().equals(OrderStatusEnums.CANCELLED.getCode())) {
throw new CzgException("订单已过期不可退单"); throw new CzgException("订单已过期不可退单");
} }
boolean isFirstRefund = true;
if (orderInfo.getRefundAmount().compareTo(BigDecimal.ZERO) != 0) {
isFirstRefund = false;
}
ShopInfo shopInfo = shopInfoService.getById(orderInfo.getShopId()); ShopInfo shopInfo = shopInfoService.getById(orderInfo.getShopId());
Map<String, BigDecimal> returnProMap = new HashMap<>(); Map<String, BigDecimal> returnProMap = new HashMap<>();
boolean isPay = true; boolean isPay = true;
@@ -755,7 +760,6 @@ public class PayServiceImpl implements PayService {
} }
} else { } else {
orderInfo.setStatus(OrderStatusEnums.REFUND.getCode()); orderInfo.setStatus(OrderStatusEnums.REFUND.getCode());
// ssss
List<OrderDetail> orderDetails = orderDetailService.queryChain() List<OrderDetail> orderDetails = orderDetailService.queryChain()
.select(OrderDetail::getId, OrderDetail::getProductId, OrderDetail::getNum, OrderDetail::getReturnNum, OrderDetail::getPackAmount, OrderDetail::getReturnNum) .select(OrderDetail::getId, OrderDetail::getProductId, OrderDetail::getNum, OrderDetail::getReturnNum, OrderDetail::getPackAmount, OrderDetail::getReturnNum)
.eq(OrderDetail::getOrderId, orderInfo.getId()) .eq(OrderDetail::getOrderId, orderInfo.getId())
@@ -812,16 +816,42 @@ public class PayServiceImpl implements PayService {
} }
orderInfo.setRefundRemark(orderInfo.getRefundRemark() + param.getRefundReason()); orderInfo.setRefundRemark(orderInfo.getRefundRemark() + param.getRefundReason());
orderInfoService.updateById(orderInfo); orderInfoService.updateById(orderInfo);
//退款后续
//退款返还库存 //退款返还库存
if (!returnProMap.isEmpty()) { if (!returnProMap.isEmpty()) {
rabbitPublisher.sendOrderRefundMsg(JSONObject.toJSONString(Map.of("orderId", orderInfo.getId(), "returnProMap", returnProMap))); rabbitPublisher.sendOrderRefundMsg(JSONObject.toJSONString(Map.of("orderId", orderInfo.getId(), "returnProMap", returnProMap)));
} }
refundOrderAfter(orderInfo.getId(), orderInfo.getShopId(), orderInfo.getUserId(), orderInfo.getOrderNo(),
// 退款分销还原 orderInfo.getPointsNum(), isFirstRefund, orderInfo.getStatus().equals(OrderStatusEnums.REFUND.getCode()));
distributionUserService.refund(orderInfo.getId(), orderInfo.getOrderNo());
return CzgResult.success(); return CzgResult.success();
} }
//触发订单退款时 后续处理
@Async
public void refundOrderAfter(@NonNull Long orderId, @NonNull Long shopId, Long userId, String orderNo,
Integer pointsNum, boolean isFirstRefund, boolean isAllRefund) {
if (isFirstRefund) {
// 退款分销还原
FunUtils.safeRunVoid(() -> distributionUserService.refund(orderId, orderNo),
"订单id:{} 退款,分销处理失败", orderId);
if (userId == null) {
return;
}
FunUtils.safeRunVoid(() -> consumerCouponService.removeConsumerCoupon(shopId, userId, orderId),
"订单id:{} 退款,消费赠券回撤处理失败", orderId);
FunUtils.safeRunVoid(() -> consumeCashbackService.removeCashback(shopId, userId, orderId, orderNo),
"订单id:{} 退款,消费返现扣除处理失败", orderId);
FunUtils.safeRunVoid(() -> pointsConfigService.removeConsumeAwardPoints(shopId, userId, orderId, orderNo),
"订单id:{} 退款,赠送积分扣除失败", orderId);
}
if (isAllRefund && userId != null && pointsNum != null && pointsNum > 0) {
FunUtils.safeRunVoid(() -> mkPointsUserService.alterPoints(userId, null, shopId, PointsConstant.ADD,
pointsNum, orderId, StrUtil.format("订单退款返还{}积分", pointsNum)),
"订单id:{} 退款,赠送积分扣除失败", orderId);
}
}
@Override @Override
@Transactional @Transactional
public void refundOrder(@NonNull Long shopId, @NonNull Long orderId, @NonNull Long payOrderId, @NonNull String refPayOrderNo, public void refundOrder(@NonNull Long shopId, @NonNull Long orderId, @NonNull Long payOrderId, @NonNull String refPayOrderNo,

View File

@@ -0,0 +1,14 @@
package com.czg.service.product.mapper;
import com.mybatisflex.core.BaseMapper;
import com.czg.product.entity.MkOcrCountStick;
/**
* 数签子的外链渠道 映射层。
*
* @author ww
* @since 2025-12-24
*/
public interface MkOcrCountStickMapper extends BaseMapper<MkOcrCountStick> {
}

View File

@@ -32,7 +32,7 @@ public interface ProductMapper extends BaseMapper<Product> {
List<ShopProductVo> selectHotsProductList(@Param("shopId") Long shopId); List<ShopProductVo> selectHotsProductList(@Param("shopId") Long shopId);
List<ShopProductVo> selectGroupProductList(@Param("shopId") Long shopId); List<ShopProductVo> selectGroupProductList(@Param("shopId") Long shopId, @Param("idList") List<Long> idList);
ShopProductInfoVo selectOneProductInfo(@Param("id") Long id, @Param("shopId") Long shopId); ShopProductInfoVo selectOneProductInfo(@Param("id") Long id, @Param("shopId") Long shopId);

View File

@@ -1,68 +1,57 @@
package com.czg.service.product.service.impl; package com.czg.service.product.service.impl;
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions; import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.thread.ThreadUtil; import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.NumberUtil; import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil; import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSON; import com.czg.exception.CzgException;
import com.alibaba.fastjson2.JSONObject; import com.czg.product.dto.ConsStockFlowDTO;
import com.czg.exception.CzgException; import com.czg.product.entity.ConsInfo;
import com.czg.market.entity.MkOcr; import com.czg.product.entity.ConsStockFlow;
import com.czg.product.entity.MkOcrService; import com.czg.product.enums.InOutItemEnum;
import com.czg.product.dto.ConsStockFlowDTO; import com.czg.product.enums.InOutTypeEnum;
import com.czg.product.dto.SaleOrderDTO; import com.czg.product.param.*;
import com.czg.product.entity.ConsInfo; import com.czg.product.service.ConsStockFlowService;
import com.czg.product.entity.ConsStockFlow; import com.czg.product.vo.ConsCheckStockRecordVo;
import com.czg.product.enums.InOutItemEnum; import com.czg.sa.StpKit;
import com.czg.product.enums.InOutTypeEnum; import com.czg.service.product.mapper.ConsInfoMapper;
import com.czg.product.param.*; import com.czg.service.product.mapper.ConsStockFlowMapper;
import com.czg.product.service.ConsStockFlowService; import com.czg.service.product.mapper.ProductMapper;
import com.czg.product.vo.ConsCheckStockRecordVo; import com.czg.service.product.util.WxAccountUtil;
import com.czg.sa.StpKit; import com.czg.utils.PageUtil;
import com.czg.service.product.mapper.ConsInfoMapper; import com.github.pagehelper.PageHelper;
import com.czg.service.product.mapper.ConsStockFlowMapper; import com.github.pagehelper.PageInfo;
import com.czg.service.product.mapper.ProductMapper; import com.mybatisflex.core.paginate.Page;
import com.czg.service.product.util.WxAccountUtil; import com.mybatisflex.core.query.QueryWrapper;
import com.czg.utils.AliOcrUtil; import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.czg.utils.PageUtil; import jakarta.annotation.Resource;
import com.github.pagehelper.PageHelper; import lombok.AllArgsConstructor;
import com.github.pagehelper.PageInfo; import lombok.extern.slf4j.Slf4j;
import com.mybatisflex.core.paginate.Page; import org.springframework.stereotype.Service;
import com.mybatisflex.core.query.QueryWrapper; import org.springframework.transaction.annotation.Transactional;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.IOException; import java.math.BigDecimal;
import java.io.InputStream; import java.util.ArrayList;
import java.math.BigDecimal; import java.util.List;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;
/** /**
* 耗材库存变动记录 * 耗材库存变动记录
* *
* @author Tankaikai tankaikai@aliyun.com * @author Tankaikai tankaikai@aliyun.com
* @since 1.0 2025-02-21 * @since 1.0 2025-02-21
*/ */
@AllArgsConstructor @AllArgsConstructor
@Service @Service
@Slf4j @Slf4j
public class ConsStockFlowServiceImpl extends ServiceImpl<ConsStockFlowMapper, ConsStockFlow> implements ConsStockFlowService { public class ConsStockFlowServiceImpl extends ServiceImpl<ConsStockFlowMapper, ConsStockFlow> implements ConsStockFlowService {
private final ConsInfoMapper consInfoMapper; private final ConsInfoMapper consInfoMapper;
private final ProductMapper productMapper; private final ProductMapper productMapper;
@Resource @Resource
private WxAccountUtil wxAccountUtil; private WxAccountUtil wxAccountUtil;
@Resource
private MkOcrService ocrService;
private QueryWrapper buildQueryWrapper(ConsStockFlowDTO param) { private QueryWrapper buildQueryWrapper(ConsStockFlowDTO param) {
QueryWrapper queryWrapper = PageUtil.buildSortQueryWrapper(); QueryWrapper queryWrapper = PageUtil.buildSortQueryWrapper();
@@ -103,14 +92,14 @@
.eq(ConsInfo::getShopId, shopId).limit(1)); .eq(ConsInfo::getShopId, shopId).limit(1));
if (consInfo == null) { if (consInfo == null) {
entity.setFailReason("耗材不存在"); entity.setFailReason("耗材不存在");
}else if (!consInfo.getConUnit().equals(entity.getUnitName())) { } else if (!consInfo.getConUnit().equals(entity.getUnitName())) {
entity.setFailReason("耗材单位不匹配"); entity.setFailReason("耗材单位不匹配");
consInfo = null; consInfo = null;
} }
entity.setConId(consInfo == null ? null : consInfo.getId().toString()); entity.setConId(consInfo == null ? null : consInfo.getId().toString());
consStockFlow.setConId(consInfo == null ? null : consInfo.getId()); consStockFlow.setConId(consInfo == null ? null : consInfo.getId());
}else { } else {
consInfo = consInfoMapper.selectOneById(conId); consInfo = consInfoMapper.selectOneById(conId);
} }
if (consInfo == null) { if (consInfo == null) {
@@ -287,84 +276,4 @@
}); });
} }
} }
}
@Override
public Integer ocr(String originalFilename, InputStream inputStream) {
Long shopId = StpKit.USER.getShopId();
byte[] readAllBytes = null;
try {
readAllBytes = inputStream.readAllBytes();
} catch (IOException e) {
throw new RuntimeException(e);
}
String md5 = DigestUtil.md5Hex(readAllBytes);
MkOcr ocr = ocrService.getOne(new QueryWrapper().eq(MkOcr::getShopId, shopId).eq(MkOcr::getMd5, md5));
if (ocr != null) {
return ocr.getId();
}
MkOcr mkOcr = new MkOcr();
mkOcr.setShopId(shopId);
mkOcr.setMd5(md5);
ocrService.save(mkOcr);
byte[] finalReadAllBytes1 = readAllBytes;
ThreadUtil.execAsync(() -> {
try {
String infoStr = AliOcrUtil.appCall(finalReadAllBytes1, originalFilename);
SaleOrderDTO saleOrderDTO = JSONObject.parseObject(infoStr, SaleOrderDTO.class);
ArrayList<ConsInOutStockBodyParam> bodyList = new ArrayList<>();
Set<String> nameList = saleOrderDTO.getItems().stream().map(SaleOrderDTO.Item::getConName).collect(Collectors.toSet());
Map<String, ConsInfo> consInfoMap = new HashMap<>();
if (!nameList.isEmpty()) {
consInfoMap = consInfoMapper.selectListByQuery(new QueryWrapper().in(ConsInfo::getConName, nameList).eq(ConsInfo::getShopId, shopId))
.stream().collect(Collectors.toMap(ConsInfo::getConName, consInfo -> consInfo));
}
ArrayList<SaleOrderDTO.Item> unInCons = new ArrayList<>();
for (SaleOrderDTO.Item item : saleOrderDTO.getItems()) {
ConsInOutStockBodyParam bodyParam = new ConsInOutStockBodyParam()
.setConName(item.getConName())
.setPurchasePrice(new BigDecimal(item.getPurchasePrice()))
.setUnitName(item.getUnitName())
.setSubTotal(new BigDecimal(item.getSubTotal()))
.setInOutNumber(new BigDecimal(item.getInOutNumber()));
ConsInfo consInfo = consInfoMap.get(item.getConName());
if (consInfo != null) {
unInCons.add(item);
bodyParam.setConId(consInfo.getId().toString());
}
bodyList.add(bodyParam);
}
ConsInOutStockHeadParam headParam = new ConsInOutStockHeadParam();
headParam.setBatchNo(saleOrderDTO.getOrderNumber())
.setInOutDate(LocalDate.parse(saleOrderDTO.getDate()))
.setAmountPayable(new BigDecimal(saleOrderDTO.getTotalAmount()))
.setBodyList(bodyList)
.setUnInCons(unInCons)
.setOcrSaleOrder(saleOrderDTO);
mkOcr.setStatus("SUCCESS");
mkOcr.setResp(JSON.toJSONString(headParam));
}catch (Exception e) {
mkOcr.setErr(e.getMessage());
mkOcr.setStatus("FAILED");
log.error("ocr失败:", e);
}finally {
ocrService.updateById(mkOcr);
}
});
return mkOcr.getId();
}
@Override
public ConsInOutStockHeadParam ocrDetail(Long id) {
MkOcr mkOcr = ocrService.getOne(new QueryWrapper().eq(MkOcr::getShopId, StpKit.USER.getShopId()).eq(MkOcr::getId, id));
if (StrUtil.isNotBlank(mkOcr.getResp())) {
return JSONObject.parseObject(mkOcr.getResp(), ConsInOutStockHeadParam.class);
}
return null;
}
}

View File

@@ -0,0 +1,72 @@
package com.czg.service.product.service.impl;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.StrUtil;
import com.czg.constants.SystemConstants;
import com.czg.product.entity.MkOcrCountStick;
import com.czg.product.service.MkOcrCountStickService;
import com.czg.service.RedisService;
import com.czg.service.product.mapper.MkOcrCountStickMapper;
import com.czg.service.product.util.AISmartCountUtils;
import com.czg.service.product.util.MuSmartCountUtils;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 数签子的外链渠道 服务层实现。
*
* @author ww
* @since 2025-12-24
*/
@Slf4j
@Service
public class MkOcrCountStickServiceImpl extends ServiceImpl<MkOcrCountStickMapper, MkOcrCountStick> implements MkOcrCountStickService {
@Resource
private RedisService redisService;
@Override
public int getCountStick(byte[] fileByte, String fileName) {
List<MkOcrCountStick> list = list(query().eq(MkOcrCountStick::getStatus, SystemConstants.OneZero.ONE).orderBy(MkOcrCountStick::getSort, true));
for (MkOcrCountStick mkOcrCountStick : list) {
if ("znds".equals(mkOcrCountStick.getMark())) {
try {
String tickCount = AISmartCountUtils.getTickCount(mkOcrCountStick.getToken(), fileByte, fileName);
if (StrUtil.isNotBlank(tickCount)) {
return Integer.parseInt(tickCount);
}
} catch (Exception e) {
mkOcrCountStick.setStatus(SystemConstants.OneZero.ZERO);
log.error("智能点数失败", e);
updateById(mkOcrCountStick);
}
} else if ("ygmh".equals(mkOcrCountStick.getMark())) {
try {
String token = getToken(mkOcrCountStick.getAccount(), mkOcrCountStick.getPwd());
return MuSmartCountUtils.detectBambooStick(Base64.encode(fileByte), token);
} catch (Exception e) {
mkOcrCountStick.setStatus(SystemConstants.OneZero.ZERO);
log.error("智能点数失败", e);
updateById(mkOcrCountStick);
}
}
}
return 0;
}
// 一个木涵 获取token
private String getToken(String username, String password) {
Object token = redisService.get("ocr:ygmh:token");
if (token != null) {
return token.toString();
}
String muToken = MuSmartCountUtils.login(username, password);
//时间为3个月减去60秒
redisService.set("ocr:ygmh:token", muToken, 7775940);
return muToken;
}
}

View File

@@ -1,18 +1,148 @@
package com.czg.service.product.service.impl; package com.czg.service.product.service.impl;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.czg.product.dto.SaleOrderDTO;
import com.czg.product.entity.ConsInfo;
import com.czg.product.param.ConsInOutStockBodyParam;
import com.czg.product.param.ConsInOutStockHeadParam;
import com.czg.sa.StpKit;
import com.czg.service.product.mapper.ConsInfoMapper;
import com.czg.service.product.mapper.MkOcrMapper; import com.czg.service.product.mapper.MkOcrMapper;
import com.czg.utils.AliOcrUtil;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl; import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.czg.market.entity.MkOcr; import com.czg.market.entity.MkOcr;
import com.czg.product.entity.MkOcrService; import com.czg.product.entity.MkOcrService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
/** /**
* ocr识别结果 服务层实现。 * ocr识别结果 服务层实现。
* *
* @author zs * @author zs
* @since 2025-11-26 * @since 2025-11-26
*/ */
@Slf4j
@Service @Service
public class MkOcrServiceImpl extends ServiceImpl<MkOcrMapper, MkOcr> implements MkOcrService{ public class MkOcrServiceImpl extends ServiceImpl<MkOcrMapper, MkOcr> implements MkOcrService {
@Resource
private ConsInfoMapper consInfoMapper;
String consOcrDetail = "你是一名票据OCR结构化专家请从我提供的票据图片中智能提取信息并只输出JSON不得添加解释、不补充不存在内容、不得返回空字符串、字段缺失填null、字段不可省略、数字一律用字符串" +
"使用以下固定JSON结构{\"documentType\":\"\",\"orderNumber\":\"\",\"date\":\"\",\"customerName\":\"\",\"operator\":\"\"," +
"\"items\":[{\"conName\":\"\",\"spec\":\"\",\"unitName\":\"\",\"inOutNumber\":\"\",\"purchasePrice\":\"\",\"subTotal\":\"\"}]," +
"\"totalAmount\":\"\",\"remark\":\"\"}。字段映射规则documentType对应单据类型/销售单/采购单/出货单orderNumber对应单号/编号/No" +
"date对应日期/开单日期customerName对应客户名称/收货单位/供应商operator对应业务员/经办人/制单人/操作员items.conName对应品名/名称;" +
"items.spec对应规格/型号items.unitName对应单位items.inOutNumber对应数量items.purchasePrice对应单价items.subTotal对应金额/小计;" +
"totalAmount对应总金额/合计金额remark对应备注。严禁生成图片中不存在的字段内容看不清或未出现的字段必须为null不允许推测或补全不得生成多余字段" +
"items只能根据识别到的行生成不得虚构。必须能识别旋转、倾斜、模糊、撕裂、光照差异、列顺序混乱、无表格线等情况并尽量恢复信息。" +
"最终输出必须是纯JSON不得包含任何非JSON字符。";
@Override
public ConsInOutStockHeadParam ocrDetail(Long id) {
MkOcr mkOcr = getOne(new QueryWrapper().eq(MkOcr::getShopId, StpKit.USER.getShopId()).eq(MkOcr::getId, id));
if (StrUtil.isNotBlank(mkOcr.getResp())) {
return JSONObject.parseObject(mkOcr.getResp(), ConsInOutStockHeadParam.class);
}
return null;
}
@Override
public Integer ocr(String originalFilename, InputStream inputStream, String type) {
Long shopId = StpKit.USER.getShopId();
byte[] readAllBytes = null;
try {
readAllBytes = inputStream.readAllBytes();
} catch (IOException e) {
throw new RuntimeException(e);
}
String md5 = DigestUtil.md5Hex(readAllBytes);
MkOcr ocr = getOne(new QueryWrapper().eq(MkOcr::getShopId, shopId).eq(MkOcr::getMd5, md5));
if (ocr != null) {
return ocr.getId();
}
MkOcr mkOcr = new MkOcr();
mkOcr.setShopId(shopId);
mkOcr.setMd5(md5);
save(mkOcr);
byte[] finalReadAllBytes1 = readAllBytes;
ThreadUtil.execAsync(() -> {
try {
if ("cons".equals(type)) {
mkOcr.setResp(ocrCons(finalReadAllBytes1, originalFilename, shopId));
} else {
}
mkOcr.setStatus("SUCCESS");
} catch (Exception e) {
mkOcr.setErr(e.getMessage());
mkOcr.setStatus("FAILED");
log.error("ocr失败:", e);
} finally {
updateById(mkOcr);
}
});
return mkOcr.getId();
}
/**
* 识别 入库单
*/
private String ocrCons(byte[] finalReadAllBytes1, String originalFilename, Long shopId) {
String infoStr = AliOcrUtil.appCall(finalReadAllBytes1, originalFilename, consOcrDetail);
SaleOrderDTO saleOrderDTO = JSONObject.parseObject(infoStr, SaleOrderDTO.class);
ArrayList<ConsInOutStockBodyParam> bodyList = new ArrayList<>();
Set<String> nameList = saleOrderDTO.getItems().stream().map(SaleOrderDTO.Item::getConName).collect(Collectors.toSet());
Map<String, ConsInfo> consInfoMap = new HashMap<>();
if (!nameList.isEmpty()) {
consInfoMap = consInfoMapper.selectListByQuery(new QueryWrapper().in(ConsInfo::getConName, nameList).eq(ConsInfo::getShopId, shopId))
.stream().collect(Collectors.toMap(ConsInfo::getConName, consInfo -> consInfo));
}
ArrayList<SaleOrderDTO.Item> unInCons = new ArrayList<>();
for (SaleOrderDTO.Item item : saleOrderDTO.getItems()) {
ConsInOutStockBodyParam bodyParam = new ConsInOutStockBodyParam()
.setConName(item.getConName())
.setPurchasePrice(new BigDecimal(item.getPurchasePrice()))
.setUnitName(item.getUnitName())
.setSubTotal(new BigDecimal(item.getSubTotal()))
.setInOutNumber(new BigDecimal(item.getInOutNumber()));
ConsInfo consInfo = consInfoMap.get(item.getConName());
if (consInfo != null) {
unInCons.add(item);
bodyParam.setConId(consInfo.getId().toString());
}
bodyList.add(bodyParam);
}
ConsInOutStockHeadParam headParam = new ConsInOutStockHeadParam();
headParam.setBatchNo(saleOrderDTO.getOrderNumber())
.setInOutDate(LocalDate.parse(saleOrderDTO.getDate()))
.setAmountPayable(new BigDecimal(saleOrderDTO.getTotalAmount()))
.setBodyList(bodyList)
.setUnInCons(unInCons)
.setOcrSaleOrder(saleOrderDTO);
return JSON.toJSONString(headParam);
}
} }

View File

@@ -6,14 +6,12 @@ import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONWriter; import com.alibaba.fastjson2.JSONWriter;
import com.czg.constant.CacheConstant; import com.czg.constant.CacheConstant;
import com.czg.constants.SystemConstants; import com.czg.constants.SystemConstants;
import com.czg.exception.CzgException; import com.czg.exception.CzgException;
import com.czg.product.dto.ProdConsRelationDTO; import com.czg.product.dto.*;
import com.czg.product.dto.ProdSkuDTO;
import com.czg.product.dto.ProductDTO;
import com.czg.product.dto.ShopProdCategoryDTO;
import com.czg.product.entity.*; import com.czg.product.entity.*;
import com.czg.product.enums.*; import com.czg.product.enums.*;
import com.czg.product.param.*; import com.czg.product.param.*;
@@ -310,6 +308,7 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
dto.setSkuList(skuList); dto.setSkuList(skuList);
List<ProdConsRelationDTO> consList = prodConsRelationMapper.selectListByProdId(dto.getId()); List<ProdConsRelationDTO> consList = prodConsRelationMapper.selectListByProdId(dto.getId());
dto.setConsList(consList); dto.setConsList(consList);
dto.setRelatedRecommendJson(getRelateProductList(dto.getRelatedRecommend()));
return dto; return dto;
} }
@@ -336,6 +335,7 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
} }
entity.setIsDel(SystemConstants.OneZero.ZERO); entity.setIsDel(SystemConstants.OneZero.ZERO);
entity.setShopId(shopId); entity.setShopId(shopId);
entity.setRelatedRecommend(dto.getRelatedRecommendStr());
super.save(entity); super.save(entity);
dto.setId(entity.getId()); dto.setId(entity.getId());
// 清除商品分类列表缓存 // 清除商品分类列表缓存
@@ -404,6 +404,7 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
if (!ProductTypeEnum.SKU.value().equals(entity.getType())) { if (!ProductTypeEnum.SKU.value().equals(entity.getType())) {
UpdateChain.of(Product.class).set(Product::getSpecId, null).eq(Product::getId, dto.getId()).update(); UpdateChain.of(Product.class).set(Product::getSpecId, null).eq(Product::getId, dto.getId()).update();
} }
entity.setRelatedRecommend(dto.getRelatedRecommendStr());
super.updateById(entity); super.updateById(entity);
// 清除商品分类列表缓存 // 清除商品分类列表缓存
clearProductCache(old.getCategoryId()); clearProductCache(old.getCategoryId());
@@ -788,4 +789,16 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
String key = StrUtil.format(CacheConstant.SHOP_PRODUCT_STOCK, shopId, productId); String key = StrUtil.format(CacheConstant.SHOP_PRODUCT_STOCK, shopId, productId);
redisService.set(key, stockNumber); redisService.set(key, stockNumber);
} }
private List<RelatedProductDTO> getRelateProductList(String relatedProduct) {
if (StrUtil.isNotBlank(relatedProduct) && !"[]".equals(relatedProduct)) {
List<Long> idList = JSONArray.parseArray(relatedProduct, Long.class);
QueryWrapper wrapper = QueryWrapper.create().select(Product::getId, Product::getName, Product::getCoverImg).eq(Product::getIsDel, SystemConstants.OneZero.ZERO)
.in(Product::getId, idList);
return super.listAs(wrapper, RelatedProductDTO.class);
}
return new ArrayList<>();
}
} }

View File

@@ -6,6 +6,7 @@ import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.NumberUtil; import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONArray;
import com.czg.constant.CacheConstant; import com.czg.constant.CacheConstant;
import com.czg.constants.SystemConstants; import com.czg.constants.SystemConstants;
import com.czg.exception.CzgException; import com.czg.exception.CzgException;
@@ -78,7 +79,7 @@ public class UProductServiceImpl extends ServiceImpl<ProductMapper, Product> imp
query().select(ProdGroup::getId, ProdGroup::getName, ProdGroup::getSortMode, ProdGroup::getUseTime, ProdGroup::getSaleStartTime, ProdGroup::getSaleEndTime) query().select(ProdGroup::getId, ProdGroup::getName, ProdGroup::getSortMode, ProdGroup::getUseTime, ProdGroup::getSaleStartTime, ProdGroup::getSaleEndTime)
.eq(ProdGroup::getShopId, shopId).eq(ProdGroup::getStatus,SystemConstants.OneZero.ONE) .eq(ProdGroup::getShopId, shopId).eq(ProdGroup::getStatus,SystemConstants.OneZero.ONE)
.orderBy(ProdGroup::getSort, true), ShopGroupProductVo.class); .orderBy(ProdGroup::getSort, true), ShopGroupProductVo.class);
List<ShopProductVo> productAllList = productMapper.selectGroupProductList(shopId); List<ShopProductVo> productAllList = productMapper.selectGroupProductList(shopId, null);
productAllList.forEach(item -> { productAllList.forEach(item -> {
List<ProdSkuDTO> skuList = prodSkuMapper.selectListByQueryAs(query() List<ProdSkuDTO> skuList = prodSkuMapper.selectListByQueryAs(query()
.eq(ProdSku::getProductId, item.getId()) .eq(ProdSku::getProductId, item.getId())
@@ -130,6 +131,21 @@ public class UProductServiceImpl extends ServiceImpl<ProductMapper, Product> imp
if (data == null) { if (data == null) {
throw new CzgException("商品不可售"); throw new CzgException("商品不可售");
} }
if (StrUtil.isBlank(data.getRelatedRecommend()) || "[]".equals(data.getRelatedRecommend())) {
data.setRelatedRecommendJson(new ArrayList<>());
} else {
List<ShopProductVo> productAllList = productMapper.selectGroupProductList(shopId, JSONArray.parseArray(data.getRelatedRecommend(), Long.class));
productAllList.forEach(item -> {
List<ProdSkuDTO> skuList = prodSkuMapper.selectListByQueryAs(query()
.eq(ProdSku::getProductId, item.getId())
.eq(ProdSku::getIsGrounding, SystemConstants.OneZero.ONE)
.eq(ProdSku::getIsDel, SystemConstants.OneZero.ZERO), ProdSkuDTO.class);
item.setSkuList(skuList);
});
data.setRelatedRecommendJson(productAllList);
}
return data; return data;
} }

View File

@@ -0,0 +1,132 @@
package com.czg.service.product.util;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.core.util.StrUtil;
import com.czg.exception.CzgException;
import lombok.extern.slf4j.Slf4j;
import java.io.File;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.net.URLEncoder;
/**
* 智能点数上传工具类
* @author ww
*/
@Slf4j
public class AISmartCountUtils {
// 基础配置
private static final String BASE_URL = "https://api.aismartcount.com/api/v1";
private static final int TIMEOUT = 30000;
/**
* 示例:完整调用流程
*/
public static String getTickCount(String token, byte[] file, String fileName) throws Exception {
String uploadResponse = uploadImage(token, file, fileName);
return countImageDots(token, uploadResponse);
}
/**
* 上传图片接口
* 完全使用你提供的header(String, String)方法设置请求头
*
* @param imageData 图片数据InputStream / byte[] / File
* @return 上传响应结果
* @throws Exception 上传异常
*/
private static String uploadImage(String token, Object imageData, String fileName) {
// 1. 构建请求URL
String uploadUrl = BASE_URL + "/upload/image";
// 2. 构建POST请求并设置基础参数
HttpRequest postRequest = HttpUtil.createPost(uploadUrl)
.header("authorization", token)
.timeout(TIMEOUT);
// 3. 根据数据类型设置文件上传参数
if (imageData instanceof File files) {
postRequest.form("file", files);
} else if (imageData instanceof InputStream input) {
postRequest.form("file", input, fileName);
} else if (imageData instanceof byte[] bytes) {
postRequest.form("file", bytes, fileName);
} else {
throw new IllegalArgumentException("不支持的图片数据类型:" + (imageData == null ? "null" : imageData.getClass().getName()));
}
String body = postRequest.execute().body();
// 解析上传响应并校验状态码
JSONObject uploadResult = JSONUtil.parseObj(body);
// 1. 校验响应码(核心)
int code = uploadResult.getInt("code", -1);
if (code != 200) {
log.error("智能点数 图片上传失败 {}", uploadResult);
throw new CzgException("图片上传失败");
}
JSONObject dataObj = uploadResult.getJSONObject("data");
if (dataObj == null) {
log.error("智能点数 图片上传响应中未找到data字段 {}", uploadResult);
throw new CzgException("图片上传失败");
}
String imgUrl = dataObj.getStr("url");
if (StrUtil.isBlank(imgUrl)) {
log.error("智能点数 图片上传成功但未返回图片URL {}", uploadResult);
throw new CzgException("图片上传成功但未返回图片URL");
}
return imgUrl;
}
/**
* 统计图片点数接口
* 手动拼接URL参数使用header方法设置授权头
*
* @param imgUrl 图片URL
* @return 统计响应结果
* @throws Exception 请求异常
*/
private static String countImageDots(String token, String imgUrl) throws Exception {
String countUrl = BASE_URL + "/count/count-image-dots" +
"?img_url=" + encodeParam(imgUrl) +
"&type=stick&secure=true&upload_source=pc";
// 2. 构建请求(仅使用你提供的方法)
String countResponse = HttpUtil.createPost(countUrl)
.header("authorization", token)
.timeout(TIMEOUT)
.execute()
.body();
JSONObject countResult = JSONUtil.parseObj(countResponse);
int countCode = countResult.getInt("code", -1);
if (countCode != 200) {
log.error("智能点数 点数统计失败,未知错误 {}", countResult);
throw new CzgException("点数统计失败,未知错误");
}
// 3. 执行请求并返回结果
return countResult.getStr("total_count");
}
/**
* 通用URL参数编码
*
* @param param 要编码的参数
* @return 编码后的字符串
*/
private static String encodeParam(String param) {
if (StrUtil.isBlank(param)) {
return "";
}
try {
return URLEncoder.encode(param, StandardCharsets.UTF_8);
} catch (Exception e) {
throw new RuntimeException("URL参数编码失败: " + param, e);
}
}
}

View File

@@ -0,0 +1,122 @@
package com.czg.service.product.util;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.czg.exception.CzgException;
import lombok.extern.slf4j.Slf4j;
/**
* 一个木涵
*
* @author: ww
*/
@Slf4j
public class MuSmartCountUtils {
// 基础配置
private static final String LOGIN_URL = "https://uapi.woobx.cn/user/login";
private static final String DETECT_URL = "https://uapi.woobx.cn/app/object-det/bamboo-stick";
// 请求超时时间(毫秒)
private static final int TIMEOUT = 10000;
/**
* 登录接口 - 获取认证Token线程安全
*
* @return 认证Token
*/
public static String login(String username, String password) {
// 构建登录请求
HttpResponse response = HttpRequest.post(LOGIN_URL)
.form("username", username)
.form("password", password)
.timeout(TIMEOUT)
.execute();
// 校验响应状态
if (!response.isOk()) {
log.error("登录失败,响应码:{},数据:{}", response.getStatus(), response.body());
throw new CzgException("登录失败");
}
// 解析响应结果
String responseStr = response.body();
JSONObject result = JSON.parseObject(responseStr);
if (200 != result.getIntValue("code")) {
log.error("登录失败,响应码:{},数据:{}", response.getStatus(), result);
throw new CzgException("登录失败");
}
// 提取并缓存Token
String token = result.getJSONObject("data").getString("authToken");
if (StrUtil.isBlank(token)) {
log.error("登录失败,响应码:{},数据:{}", response.getStatus(), result);
throw new CzgException("登录失败");
}
return token;
}
/**
* 竹签识别核心方法自动处理Token过期重试
*
* @param imageBase64 图片Base64编码字符串
* @return 识别结果JSON对象
* @throws Exception 识别异常
*/
public static int detectBambooStick(String imageBase64, String token) throws Exception {
// 参数校验
if (StrUtil.isBlank(imageBase64)) {
throw new CzgException("图片Base64编码不能为空");
}
// 第一次调用识别接口
JSONObject detectResult = doDetectRequest(imageBase64, token);
return MuSmartCountUtils.countBambooStick(detectResult);
}
/**
* 执行竹签识别请求(核心请求逻辑)
*
* @param imageBase64 图片Base64编码
* @param token 认证Token
* @return 识别结果
*/
private static JSONObject doDetectRequest(String imageBase64, String token){
// 构建识别请求
HttpResponse response = HttpRequest.post(DETECT_URL)
.header("authorization", "Bearer " + token)
.form("image", imageBase64)
.form("base64", "true")
.timeout(TIMEOUT)
.execute();
// 校验响应状态
if (!response.isOk()) {
throw new RuntimeException("识别请求失败,响应码:" + response.getStatus());
}
// 解析响应结果
String responseStr = response.body();
return JSON.parseObject(responseStr);
}
/**
* 解析识别结果,统计竹签数量(自定义分数阈值)
*
* @param detectResult 识别结果JSON
* @return 竹签数量
*/
private static int countBambooStick(JSONObject detectResult) {
// 参数校验
if (detectResult == null || 200 != detectResult.getIntValue("code")) {
return 0;
}
JSONArray dataArray = detectResult.getJSONArray("data");
if (dataArray == null || dataArray.isEmpty()) {
return 0;
}
return dataArray.size();
}
}

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.czg.service.product.mapper.MkOcrCountStickMapper">
</mapper>

View File

@@ -95,7 +95,8 @@
t1.pack_fee, t1.pack_fee,
ifnull(t4.sales_volume, 0) as sales_volume, ifnull(t4.sales_volume, 0) as sales_volume,
t1.shop_id, t1.shop_id,
t1.is_stock t1.is_stock,
t1.related_recommend
from tb_product t1 from tb_product t1
left join (select x.product_id, left join (select x.product_id,
x.id as sku_id, x.id as sku_id,
@@ -147,6 +148,12 @@
and t2.sale_price is not null and t2.sale_price is not null
and t1.shop_id = #{shopId} and t1.shop_id = #{shopId}
</where> </where>
<if test="idList != null">
and t1.id in
<foreach item="item" collection="idList" separator="," open="(" close=")">
#{item}
</foreach>
</if>
order by t1.sort desc,t1.id desc order by t1.sort desc,t1.id desc
</select> </select>
<select id="selectOneProductInfo" resultType="com.czg.product.vo.ShopProductInfoVo"> <select id="selectOneProductInfo" resultType="com.czg.product.vo.ShopProductInfoVo">

View File

@@ -12,6 +12,9 @@ import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboService; import org.apache.dubbo.config.annotation.DubboService;
import java.util.Map;
import java.util.Set;
/** /**
* 验证码工具类 * 验证码工具类
* *
@@ -23,38 +26,24 @@ public class SmsServiceImpl implements SmsService {
@Resource @Resource
private SysParamsService sysParamsService; private SysParamsService sysParamsService;
/**
* 阿里云key
*/
private String key;
/**
* 阿里云secret
*/
private String secret;
/** /**
* 短信模板id * 短信模板id
*/ */
private String templateCode; private String templateCode;
@PostConstruct public Client init() throws Exception {
public void init() {
key = sysParamsService.getSysParamValue(ParamCodeCst.AliYun.ALI_SMS_KEY);
secret = sysParamsService.getSysParamValue(ParamCodeCst.AliYun.ALI_SMS_SECRET);
templateCode = sysParamsService.getSysParamValue(ParamCodeCst.AliYun.ALI_SMS_TEMPLATE_CODE);
log.info("短信工具类初始化完毕key: {}, secret: {}, templateCode: {}", key, secret, templateCode);
}
public Client createClient() throws Exception {
Config config = new Config(); Config config = new Config();
config.accessKeyId = key; Map<String, String> aliOssKeys = sysParamsService.getParamsByMap("ali_oss_key_set", ParamCodeCst.ALI_OSS_KEY_SET);
config.accessKeySecret = secret; config.accessKeyId = aliOssKeys.get(ParamCodeCst.AliYun.ALI_SMS_KEY);
config.accessKeySecret = aliOssKeys.get(ParamCodeCst.AliYun.ALI_SMS_SECRET);
templateCode = aliOssKeys.get(ParamCodeCst.AliYun.ALI_SMS_TEMPLATE_CODE);
return new Client(config); return new Client(config);
} }
@Override @Override
public void sendCode(String phone, String checkCode) { public void sendCode(String phone, String checkCode) {
try { try {
Client client = createClient(); Client client = init();
// 1.发送短信 // 1.发送短信
com.aliyun.dysmsapi20170525.models.SendSmsRequest sendSmsRequest = new com.aliyun.dysmsapi20170525.models.SendSmsRequest() com.aliyun.dysmsapi20170525.models.SendSmsRequest sendSmsRequest = new com.aliyun.dysmsapi20170525.models.SendSmsRequest()
.setSignName("陕西超掌柜科技") .setSignName("陕西超掌柜科技")
@@ -67,7 +56,7 @@ public class SmsServiceImpl implements SmsService {
if (sendSmsResponse.getStatusCode() != 200) { if (sendSmsResponse.getStatusCode() != 200) {
throw new CzgException("短信发送失败"); throw new CzgException("短信发送失败");
} }
}catch (Exception e) { } catch (Exception e) {
log.info("发送短信失败", e); log.info("发送短信失败", e);
} }
} }

View File

@@ -140,12 +140,12 @@ public class SysParamsServiceImpl extends ServiceImpl<SysParamsMapper, SysParams
@Cacheable(cacheNames = "params:entity", key = "#type") @Cacheable(cacheNames = "params:entity", key = "#type")
@Override @Override
public Map<String, String> getParamsByMap(String type, Set<String> keyList) throws CzgException{ public Map<String, String> getParamsByMap(String type, Set<String> keyList) throws CzgException {
Map<String, String> map = new HashMap<>(); Map<String, String> map = new HashMap<>();
for (String key : keyList) { for (String key : keyList) {
SysParams sysParam = getSysParam(key); SysParams sysParam = getSysParam(key);
if (sysParam == null || StrUtil.isBlank(sysParam.getParamValue())) { if (sysParam == null || StrUtil.isBlank(sysParam.getParamValue())) {
throw new CzgException(key + "参数不存在"); throw new CzgException("sysParam的类型" + type + "" + key + "参数不存在");
} }
map.put(key, sysParam.getParamValue()); map.put(key, sysParam.getParamValue());
} }