Compare commits

35 Commits

Author SHA1 Message Date
xm
49ce3c40e5 1 2026-06-10 15:07:57 +08:00
xm
97db34f141 1、拆分门店、服务商角色及调整对应订单计算算法
2、推荐人关系列表增加删除标记,方便后期数据硕源
2026-06-05 17:31:19 +08:00
xm
48ae0ddfe6 优化分红金额计算业务 2026-06-02 15:11:00 +08:00
xm
5b3506fa00 商品增加分享图业务 2026-06-01 17:05:28 +08:00
xm
471927ccfc 商品订单增加配送时间业务 2026-06-01 11:34:04 +08:00
xm
2f1c95401f 优化商品股东分红批量更新业务 2026-05-30 17:28:53 +08:00
xm
3a874e84f5 Merge branch 'glt_xm' into dev_xm
# Conflicts:
#	src/main/java/com/gxwebsoft/shop/service/impl/ShopFlashSaleActivityServiceImpl.java
#	src/main/java/com/gxwebsoft/shop/vo/ShopFlashSaleActivityVO.java
2026-05-30 15:46:26 +08:00
xm
c3a50306ba 优化秒杀活动用户下单能力业务 2026-05-30 15:26:39 +08:00
xm
8d1a91cee7 Merge remote-tracking branch 'origin/dev_xm' into glt_xm
# Conflicts:
#	src/main/resources/application-dev.yml
#	src/main/resources/application-local.yml
2026-05-30 14:50:16 +08:00
xm
e511df0f8b 优化秒杀活动用户下单能力业务 2026-05-30 14:46:44 +08:00
xm
dd889dd7a2 1、增加股东/合伙人分红功能
2、优化原有订单分销算法,去掉原有股东分红制
3、优化收益明细查询业务
4、优化订单分佣解冻业务
2026-05-30 10:55:32 +08:00
xm
61b1d16937 1、优化配送派单消息推送功能
2、优化送水订单配送状态、水票标识查询,回显品名、水票标识、订单状态业务
3、优化送水订单接单、送达业务
4、优化资金表、资金流水表资金变更同步业务
2026-05-28 17:01:35 +08:00
xm
30363735df 增加商品分润基础业务功能 2026-05-27 10:59:00 +08:00
xm
b9d0d6b036 1、增加配送师傅订单派送发送消息通知功能
2、增加普通商品配完成送结算步梯费用给到配送师傅业务功能
3、增加分销商查询个人资金流水功能
2026-05-27 10:56:55 +08:00
xm
ba3748d2f9 1、调整微信消息推送模板业务
2、增加普通商品配送自动发单功能
3、增加核销员管理功能
4、开发配送员转单功能
5、优化送水订单查询业务
6、优化配送订单自动分配配送师傅业务
7、增加普通商品下单配送支付步梯费功能
2026-05-25 18:08:47 +08:00
xm
18148ddb8d 1、优化配送费分佣计算方式,按百分比/固定金额计算
2、增加自提订单核销数据统计功能
3、增加现场核销推广指定人分佣业务
2026-05-21 18:14:35 +08:00
xm
4d455e2ba2 增加分销员推广核销能力业务 2026-05-20 16:54:57 +08:00
xm
74bf6dd8d2 1、推广码底图增加分享底图业务
2、优化订单核销码、核销人查询业务
2026-05-20 14:28:30 +08:00
xm
5b876d29eb 1、关闭原有定时结算、手动结算业务,因新业务已完成流程结算功能
2、优化秒杀订单查询活动名称、核销码业务
3、优化订单状态查询业务
2026-05-20 11:29:24 +08:00
xm
032c936f42 local启动配置修改 2026-05-19 17:52:19 +08:00
xm
bbb26b44a9 优化配送订单完成结算配送金业务 2026-05-19 17:40:08 +08:00
xm
52af00170a 1、优化送水订单同步记录水票订单号业务
2、分销用户分销明细增加结算标识业务
3、增加分销用户个人当日收益数据统计
2026-05-19 16:47:42 +08:00
xm
b5d4274d97 1、修改测试、本地环境证书加载路径业务
2、优化配送结算业务,配送完成即计算
3、优化门店、服务商结算任务
4、秒杀活动增加弹窗业务
2026-05-19 10:32:17 +08:00
xm
2fbcf16a48 增加门店、服务商佣金定时结算功能,默认每天凌晨一点执行 2026-05-16 15:10:14 +08:00
xm
7de53327d6 修改配置 2026-05-14 17:45:04 +08:00
xm
f86bf8df4b 修改配置了 2026-05-14 08:21:10 +08:00
xm
65f1fa861d 配置修改 2026-05-14 01:33:58 +08:00
xm
cdabd5d446 优化水票释放业务 2026-05-13 17:29:45 +08:00
xm
86d27db76d Merge branch 'dev' into dev_xm
# Conflicts:
#	src/test/java/com/gxwebsoft/generator/ShopGenerator.java
2026-05-13 16:33:42 +08:00
xm
c3fcb36f66 增加退款按订单号回退分销用户钱包流水及同步生产回退流水功能 2026-05-13 16:32:09 +08:00
a306f53336 feat(cms): 在CmsNavigation实体中添加文章列表关联
- 在CmsNavigation类中新增articles字段用于存储栏目文章列表
- 在CmsNavigationServiceImpl的pageRel方法中关联查询每个栏目对应的最多5篇文章
- 调用CmsArticleService获取文章列表并设置到CmsNavigation实体中
- 优化栏目分页查询,增加文章数据支持展示
2026-05-06 19:39:03 +08:00
8fca992e37 fix(shopOrder): 支持订单拒绝退款状态校验
- 修改退款操作接口,增加对拒绝退款状态(orderStatus=5)的支持
- 更新接口描述,明确支持申请、拒绝、同意及客户端申请退款四种状态
- 优化校验逻辑,确保orderStatus只能为4、5、6或7
- 完善参数非空判断并返回相应失败信息
2026-05-06 17:06:40 +08:00
026824d31d chore(config): remove obsolete test and environment configuration files
- 删除了 application-glt2.yml、application-glt3.yml 和 application-test.yml 配置文件
- 移除了所有与证书路径相关的测试类,包括 CertificatePathConcatenationTest、CertificatePathFixTest、CertificatePathTest、CertificateTest 和 EnvironmentBasedCertificateTest
- 删除了 CouponStatusServiceTest 测试类和 MultiSpecOrderTest 测试类
- 清理历史环境和测试遗留配置,简化项目结构,提高维护性
2026-04-29 10:28:08 +08:00
1350250847@qq.com
bc3842faee 变更数据库链接 2026-04-20 16:38:04 +08:00
1350250847@qq.com
8d2a0c46b7 常量注释 2026-04-14 16:57:34 +08:00
153 changed files with 4712 additions and 4143 deletions

View File

@@ -227,6 +227,10 @@ public class CmsNavigation implements Serializable {
@TableField(exist = false)
private String text;
@Schema(description = "栏目文章")
@TableField(exist = false)
private List<CmsArticle> articles;
public String getCategoryName() {
return this.title;
}

View File

@@ -4,9 +4,11 @@ import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gxwebsoft.cms.entity.CmsArticle;
import com.gxwebsoft.cms.entity.CmsDesign;
import com.gxwebsoft.cms.entity.CmsModel;
import com.gxwebsoft.cms.mapper.CmsNavigationMapper;
import com.gxwebsoft.cms.service.CmsArticleService;
import com.gxwebsoft.cms.service.CmsDesignService;
import com.gxwebsoft.cms.service.CmsModelService;
import com.gxwebsoft.cms.service.CmsNavigationService;
@@ -38,6 +40,8 @@ public class CmsNavigationServiceImpl extends ServiceImpl<CmsNavigationMapper, C
private CmsModelService cmsModelService;
@Resource
private UserService userService;
@Resource
private CmsArticleService cmsArticleService;
@Override
public PageResult<CmsNavigation> pageRel(CmsNavigationParam param) {
@@ -53,6 +57,11 @@ public class CmsNavigationServiceImpl extends ServiceImpl<CmsNavigationMapper, C
// 排序
PageParam<CmsNavigation, CmsNavigationParam> page = new PageParam<>();
page.setDefaultOrder("sort_number asc, position asc,navigation_id asc");
list.forEach(item -> {
// 关联信息
final List<CmsArticle> articleList = cmsArticleService.list(new LambdaQueryWrapper<CmsArticle>().eq(CmsArticle::getCategoryId, item.getNavigationId()).last("limit 5"));
item.setArticles(articleList);
});
return page.sortRecords(list);
}

View File

@@ -32,7 +32,7 @@ public class CertificateProperties {
/**
* 开发环境证书路径前缀
*/
private String devCertPath = "dev";
private String devCertPath = "local";
/**
* 微信支付证书配置

View File

@@ -60,7 +60,7 @@ public class ConfigProperties {
/**
* token过期时间, 单位秒
*/
private Long tokenExpireTime = 60 * 60 * 365 * 24L;
private Long tokenExpireTime = 60 * 60 * 30 * 24L;
/**
* token快要过期自动刷新时间, 单位分钟

View File

@@ -80,6 +80,7 @@ public class MybatisPlusConfig {
@Override
public boolean ignoreTable(String tableName) {
// TenantContext.setIgnoreTenant(Boolean.TRUE);
// 如果当前上下文设置了忽略租户隔离,则忽略所有表的租户隔离
if (TenantContext.isIgnoreTenant()) {
return true;
@@ -92,17 +93,8 @@ public class MybatisPlusConfig {
"sys_dictionary_data",
"apps_test_data",
"cms_lang",
// "hjm_car",
// "hjm_fence"
// "cms_website"
// "sys_user"
// "cms_domain"
// "shop_order_goods",
"shop_goods",
// "shop_users",
"shop_order" , // 移除shop_order改为通过注解控制
// "shop_order_info",
// "booking_user_invoice"
"shop_order" ,
"shop_order_goods",
"glt_ticket_template",
"glt_user_ticket",
@@ -110,7 +102,9 @@ public class MybatisPlusConfig {
"glt_user_ticket_log",
"shop_dealer_user",
"shop_dealer_order",
"shop_dealer_referee"
"shop_dealer_referee",
"shop_store_rider",
"shop_goods_profit"
).contains(tableName);
}
};

View File

@@ -30,7 +30,7 @@ import java.util.Map;
@Tag(name = "数据库修复工具")
@RestController
@RequestMapping("/api/database-fix")
// @ConditionalOnProperty(name = "spring.profiles.active", havingValue = "dev")
// @ConditionalOnProperty(name = "spring.profiles.active", havingValue = "local")
public class DatabaseFixController extends BaseController {
@Autowired

View File

@@ -28,7 +28,7 @@ import java.util.Map;
@Tag(name = "开发环境管理")
@RestController
@RequestMapping("/api/dev")
// @ConditionalOnProperty(name = "spring.profiles.active", havingValue = "dev")
// @ConditionalOnProperty(name = "spring.profiles.active", havingValue = "local")
public class DevEnvironmentController extends BaseController {
@Autowired

View File

@@ -15,11 +15,14 @@ public enum ShopDealerCapitalUpdateEnum {
MANAGEMENT_INCOME(11, "团队管理津贴收入", true),
DIVIDEND_INCOME(12, "分红收入", true),
PROMOTION_INCOME(13, "现场推广收入", true),
PROMOTION_PARENT_INCOME(14, "现场推广分佣", true),
WITHDRAW_PAYMENT(20, "提现支出", false),
TRANSFER_PAYMENT(30, "转账支出", false),
TRANSFER_INCOME(40, "转账收入", true),
FREEZE_MONEY_THAW(50, "佣金解冻", true),
DELIVERY_INCOME(60, "配送奖励", true),
DELIVERY_REWARD(60, "配送奖励", true),
DELIVERY_INCOME(61, "配送提成", true),
DELIVERY_FLOOR_FEE(62, "配送步梯费", true),
ORDER_REFUND(70, "佣金退回(退单)", false),
;

View File

@@ -13,7 +13,8 @@ public enum ShopDealerTypeEnum {
FREEZE_ACCOUNT(1, "操作冻结账户余额"),
WITHDRAW_ACCOUNT(2, "操作提现账户余额【直接结算】"),
DEFROST(3, "解冻");
DEFROST(3, "解冻"),
ORDER_REFUND(4, "退单");
private final Integer code;
private final String desc;

View File

@@ -70,7 +70,7 @@ public class EnvironmentAwarePaymentService {
* 根据当前环境获取回调地址
*/
private String getEnvironmentNotifyUrl() {
if ("dev".equals(activeProfile) || "test".equals(activeProfile)) {
if ("local".equals(activeProfile) || "test".equals(activeProfile)) {
// 开发/测试环境使用本地回调地址
return devNotifyUrl;
} else if ("prod".equals(activeProfile)) {
@@ -135,7 +135,7 @@ public class EnvironmentAwarePaymentService {
* 是否为开发环境
*/
public boolean isDevelopmentEnvironment() {
return "dev".equals(activeProfile) || "test".equals(activeProfile);
return "local".equals(activeProfile) || "test".equals(activeProfile);
}
/**

View File

@@ -84,7 +84,7 @@ public class WechatCertAutoConfig {
String apiV3Key = "0kF5OlPr482EZwtn9zGufUcqa7ovgxRL";
// 根据环境选择证书路径
if ("dev".equals(activeProfile)) {
if ("local".equals(activeProfile)) {
// 开发环境使用配置文件upload-path拼接证书路径
String uploadPath = configProperties.getUploadPath(); // 配置文件路径
String tenantId = "10550"; // 租户ID

View File

@@ -105,7 +105,7 @@ public class WechatPayCertificateDiagnostic {
* 检查证书文件
*/
private void checkCertificateFiles(Payment payment, Integer tenantId, String environment, DiagnosticResult result) {
if ("dev".equals(environment)) {
if ("local".equals(environment)) {
// 开发环境证书检查
String tenantCertPath = "dev/wechat/" + tenantId;
String privateKeyPath = tenantCertPath + "/" + certConfig.getWechatPay().getDev().getPrivateKeyFile();
@@ -152,7 +152,7 @@ public class WechatPayCertificateDiagnostic {
*/
private void validateCertificateContent(Payment payment, Integer tenantId, String environment, DiagnosticResult result) {
try {
if ("dev".equals(environment)) {
if ("local".equals(environment)) {
String tenantCertPath = "dev/wechat/" + tenantId;
String apiclientCertPath = tenantCertPath + "/" + certConfig.getWechatPay().getDev().getApiclientCertFile();

View File

@@ -103,7 +103,7 @@ public class WechatPayCertificateFixer {
* 修复证书文件问题
*/
private void fixCertificateFiles(Payment payment, Integer tenantId, String environment, FixResult result) {
if ("dev".equals(environment)) {
if ("local".equals(environment)) {
fixDevCertificateFiles(tenantId, result);
} else {
fixProdCertificateFiles(payment, result);
@@ -169,7 +169,7 @@ public class WechatPayCertificateFixer {
}
// 在开发环境中,尝试从证书文件中提取序列号进行验证
if ("dev".equals(environment)) {
if ("local".equals(environment)) {
try {
String tenantCertPath = "dev/wechat/" + tenantId;
String apiclientCertPath = tenantCertPath + "/" + certConfig.getWechatPay().getDev().getApiclientCertFile();

View File

@@ -115,7 +115,7 @@ public class WechatPayConfigValidator {
* 验证证书文件
*/
private void validateCertificateFiles(Integer tenantId, ValidationResult result) {
if ("dev".equals(activeProfile)) {
if ("local".equals(activeProfile)) {
// 开发环境证书验证
String tenantCertPath = "dev/wechat/" + tenantId;
String privateKeyPath = tenantCertPath + "/" + certConfig.getWechatPay().getDev().getPrivateKeyFile();
@@ -195,7 +195,7 @@ public class WechatPayConfigValidator {
// 证书文件检查
report.append("当前环境: ").append(activeProfile).append("\n");
if ("dev".equals(activeProfile)) {
if ("local".equals(activeProfile)) {
String tenantCertPath = "dev/wechat/" + tenantId;
String privateKeyPath = tenantCertPath + "/" + certConfig.getWechatPay().getDev().getPrivateKeyFile();
boolean certExists = certificateLoader.certificateExists(privateKeyPath);

View File

@@ -78,7 +78,7 @@ public class WechatPayDiagnostic {
}
// 生产环境检查证书文件
if (!"dev".equals(environment)) {
if (!"local".equals(environment)) {
if (payment.getApiclientCert() != null) {
log.info("商户证书文件配置: {}", payment.getApiclientCert());
}

View File

@@ -70,4 +70,11 @@ public interface UserMapper extends BaseMapper<User> {
@InterceptorIgnore(tenantLine = "true")
List<User> listByAlert();
/**
* 批量查询用户信息
* @param userIdList 用户ID集合
* @return
*/
List<User> selectByUserIdList(@Param("userIdList") List<Integer> userIdList);
}

View File

@@ -263,5 +263,22 @@
<select id="getById" resultType="com.gxwebsoft.common.system.entity.User">
SELECT * FROM gxwebsoft_core.sys_user WHERE user_id = #{userId} and deleted = 0
</select>
<select id="selectByUserIdList" resultType="com.gxwebsoft.common.system.entity.User">
SELECT
user_id,
username,
nickname,
phone,
real_name,
create_time
FROM
gxwebsoft_core.sys_user
WHERE
deleted = 0
AND user_id IN
<foreach collection="userIdList" item="item" index="index" open="(" close=")" separator=",">
#{item}
</foreach>
</select>
</mapper>

View File

@@ -143,7 +143,7 @@ public class SettingServiceImpl extends ServiceImpl<SettingMapper, Setting> impl
final String apiV3key = jsonObject.getString("wechatApiKey");
if(config == null){
// 根据环境选择不同的证书路径配置
if ("dev".equals(activeProfile)) {
if ("local".equals(activeProfile)) {
// 开发环境使用配置文件的upload-path拼接证书路径 - 租户ID 10550
System.out.println("=== 开发环境使用配置文件upload-path拼接证书路径 ===");
String uploadPath = pathConfig.getUploadPath(); // 获取配置的upload-path

View File

@@ -9,6 +9,8 @@ import com.gxwebsoft.common.core.web.BatchParam;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.common.system.mapper.UserMapper;
import com.gxwebsoft.glt.dto.GltTransferOrderDto;
import com.gxwebsoft.glt.dto.NoticeRiderNewOrderDto;
import com.gxwebsoft.glt.entity.GltTicketOrder;
import com.gxwebsoft.glt.param.GltTicketOrderDeliveredParam;
import com.gxwebsoft.glt.param.GltTicketOrderParam;
@@ -23,6 +25,7 @@ import cn.hutool.core.util.StrUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springdoc.api.annotations.ParameterObject;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
@@ -56,7 +59,7 @@ public class GltTicketOrderController extends BaseController {
@Operation(summary = "分页查询送水订单")
@GetMapping("/page")
public ApiResult<PageResult<GltTicketOrder>> page(GltTicketOrderParam param) {
public ApiResult<PageResult<GltTicketOrder>> page(@ParameterObject GltTicketOrderParam param) {
// 使用关联查询
return success(gltTicketOrderService.pageRel(param));
}
@@ -176,14 +179,6 @@ public class GltTicketOrderController extends BaseController {
}
gltTicketOrderService.createWithWriteOff(gltTicketOrder, loginUser.getUserId(), loginUser.getTenantId());
// 订单创建成功后,异步通知所有在线配送员有新订单
try {
notifyRidersOfNewOrder(gltTicketOrder, loginUser.getTenantId());
} catch (Exception e) {
log.warn("通知配送员失败(不影响下单): {}", e.getMessage());
}
return success("下单成功");
}
@@ -242,8 +237,14 @@ public class GltTicketOrderController extends BaseController {
}
}
}
}
log.info("已向 {} 位配送员发送新订单通知", riders.size());
@PreAuthorize("isAuthenticated()")
@Operation(summary = "配送员调度单通知")
@PostMapping("/sendRiderNewOrderNotice")
public ApiResult<?> sendRiderNewOrderNotice(@RequestBody NoticeRiderNewOrderDto noticeRiderNewOrderDto) {
gltSubscribeMessageService.sendRiderNewOrderNotice(noticeRiderNewOrderDto);
return success("发送消息成功!");
}
@PreAuthorize("isAuthenticated()")
@@ -260,6 +261,13 @@ public class GltTicketOrderController extends BaseController {
return success("接单成功");
}
@PreAuthorize("isAuthenticated()")
@Operation(summary = "配送员转单")
@PostMapping("/transferOrder")
public ApiResult<Boolean> transferOrder(@RequestBody GltTransferOrderDto orderDto) {
return success(gltTicketOrderService.transferOrder(orderDto));
}
@PreAuthorize("isAuthenticated()")
@Operation(summary = "配送员开始配送")
@PostMapping("/{id}/start")
@@ -291,6 +299,13 @@ public class GltTicketOrderController extends BaseController {
return success("确认送达");
}
@Operation(summary = "订单调度")
@PostMapping("/dispatchOrder")
public ApiResult<?> dispatchOrder(@RequestParam("orderNo") String orderNo, @RequestParam("tenantId") Integer tenantId) {
gltTicketOrderService.dispatchOrder(orderNo, tenantId);
return success("success!");
}
@PreAuthorize("isAuthenticated()")
@Operation(summary = "用户确认收货")
@PostMapping("/{id}/confirm-receive")
@@ -374,23 +389,14 @@ public class GltTicketOrderController extends BaseController {
}
if (gltTicketOrderService.updateById(gltTicketOrder)) {
// 后台指派配送员(直接改 riderId同步商城订单为“已发货”(deliveryStatus=20)
if (gltTicketOrder != null
&& gltTicketOrder.getId() != null
&& gltTicketOrder.getRiderId() != null
&& gltTicketOrder.getRiderId() > 0) {
gltTicketOrderService.markShopOrderShippedAfterRiderAssigned(
gltTicketOrder.getId(),
tenantId,
gltTicketOrder.getRiderId()
);
}
gltTicketOrderService.markShopOrderShippedAfterRiderAssigned(gltTicketOrder.getId(), tenantId, gltTicketOrder.getRiderId());
// 后台直接改“已完成”(deliveryStatus=40)时,同步商城订单为“已完成”(orderStatus=1)
if (gltTicketOrder != null
&& gltTicketOrder.getId() != null
&& gltTicketOrder.getDeliveryStatus() != null
&& gltTicketOrder.getDeliveryStatus() == GltTicketOrderService.DELIVERY_STATUS_FINISHED) {
gltTicketOrderService.markShopOrderCompletedAfterTicketFinished(gltTicketOrder.getId(), tenantId);
gltTicketOrderService.markShopOrderCompletedAfterTicketFinished(gltTicketOrder.getId());
}
return success("修改成功");
}

View File

@@ -79,6 +79,7 @@ public class GltTicketTemplateController extends BaseController {
User loginUser = getLoginUser();
if (loginUser != null) {
gltTicketTemplate.setUserId(loginUser.getUserId());
gltTicketTemplate.setTenantId(loginUser.getTenantId());
}
if (gltTicketTemplateService.save(gltTicketTemplate)) {
return success("添加成功");

View File

@@ -0,0 +1,25 @@
package com.gxwebsoft.glt.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
/**
* 转单请求类
*
*/
@Data
@Schema(name = "ShopOrderMyVerifyDto", description = "转单请求类")
public class GltTransferOrderDto {
@Schema(description = "订单ID")
@NotEmpty(message = "订单ID不能为空")
private Integer id;
@Schema(description = "转单用户ID")
@NotEmpty(message = "转单用户ID不能为空")
private Integer userId;
}

View File

@@ -0,0 +1,35 @@
package com.gxwebsoft.glt.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 配送员新订单配送通知
*
*/
@Data
@Schema(name = "ShopOrderMyVerifyDto", description = "配送员新订单配送通知")
public class NoticeRiderNewOrderDto {
@Schema(description = "订单号")
private String orderNo;
@Schema(description = "商品名称")
private String goodsName;
@Schema(description = "配送数量")
private Integer productCount;
@Schema(description = "期望送达时间")
private LocalDateTime createTime;
@Schema(description = "租户ID")
private Integer tenantId;
@Schema(description = "openID")
private String openId;
}

View File

@@ -33,7 +33,6 @@ public class GltTicketOrder implements Serializable {
private Integer userTicketId;
@Schema(description = "关联订单编号")
@TableField(exist = false)
private String orderNo;
@Schema(description = "订单状态")
@@ -47,6 +46,10 @@ public class GltTicketOrder implements Serializable {
@TableField(exist = false)
private String storeName;
@Schema(description = "品名")
@TableField(exist = false)
private String goodsName;
@Schema(description = "门店地址")
@TableField(exist = false)
private String storeAddress;
@@ -214,6 +217,9 @@ public class GltTicketOrder implements Serializable {
@Schema(description = "状态, 0正常, 1冻结")
private Integer status;
@Schema(description = "水票标识 0-非 1-是")
private Integer waterTicketFlag;
@Schema(description = "是否删除, 0否, 1是")
@TableLogic
private Integer deleted;

View File

@@ -11,7 +11,7 @@
d.name as receiverName, d.phone as receiverPhone,
d.province as receiverProvince, d.city as receiverCity, d.region as receiverRegion,
d.address as receiverAddress, d.full_address as receiverFullAddress, d.lat as receiverLat, d.lng as receiverLng,
COALESCE(o.order_no, f.order_no) as orderNo, o.order_status as orderStatus
COALESCE(o.order_no, a.order_no) as orderNo, o.order_status as orderStatus
FROM glt_ticket_order a
LEFT JOIN shop_store b ON a.store_id = b.id
LEFT JOIN shop_store_warehouse w ON a.warehouse_id = w.id
@@ -20,7 +20,6 @@
LEFT JOIN shop_user_address d ON a.address_id = d.id
LEFT JOIN glt_user_ticket f ON a.user_ticket_id = f.id
LEFT JOIN shop_order o ON f.order_id = o.order_id AND f.tenant_id = o.tenant_id AND o.deleted = 0
<where>
<if test="param.id != null">
AND a.id = #{param.id}
@@ -88,7 +87,7 @@
AND a.create_time &lt;= #{param.createTimeEnd}
</if>
<if test="param.orderNo != null">
AND (a.id = #{param.orderNo} OR COALESCE(o.order_no, f.order_no) = #{param.orderNo})
AND (a.id = #{param.orderNo} OR COALESCE(o.order_no, a.order_no) = #{param.orderNo})
</if>
<if test="param.phone != null">
AND u.phone = #{param.phone}
@@ -103,6 +102,12 @@
OR u.phone LIKE CONCAT('%', #{param.keywords}, '%')
)
</if>
<if test="param.waterTicketFlag != null">
AND a.water_ticket_flag = #{param.waterTicketFlag}
</if>
<if test="param.deliveryStatus != null and param.deliveryStatus == 10">
AND o.order_status in (0, 1, 5)
</if>
</where>
</sql>

View File

@@ -94,4 +94,7 @@ public class GltTicketOrderParam extends BaseParam {
@QueryField(type = QueryType.EQ)
private Integer orderStatus;
@Schema(description = "水票订单标识 0-否 1-是")
private Integer waterTicketFlag;
}

View File

@@ -1,5 +1,6 @@
package com.gxwebsoft.glt.service;
import com.gxwebsoft.glt.dto.NoticeRiderNewOrderDto;
import com.gxwebsoft.glt.entity.GltTicketOrder;
/**
@@ -25,4 +26,10 @@ public interface GltSubscribeMessageService {
* @return 是否发送成功
*/
boolean sendOrderStatusNotice(GltTicketOrder order, String riderOpenId, String statusText, Integer tenantId);
/**
* 推送配送师傅接单提醒
* @param noticeRiderNewOrderDto
*/
void sendRiderNewOrderNotice(NoticeRiderNewOrderDto noticeRiderNewOrderDto);
}

View File

@@ -1,10 +1,7 @@
package com.gxwebsoft.glt.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gxwebsoft.glt.entity.GltTicketTemplate;
import com.gxwebsoft.glt.entity.GltUserTicket;
import com.gxwebsoft.glt.entity.GltUserTicketLog;
import com.gxwebsoft.glt.entity.GltUserTicketRelease;
import com.gxwebsoft.glt.entity.*;
import com.gxwebsoft.glt.task.DealerOrderSettlement10584Task;
import com.gxwebsoft.shop.entity.ShopOrder;
import com.gxwebsoft.shop.entity.ShopOrderGoods;
@@ -18,6 +15,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;
import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
@@ -37,6 +35,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
@RequiredArgsConstructor
public class GltTicketIssueService {
@Resource
private GltTicketOrderService gltTicketOrderService;
public static final int CHANGE_TYPE_ISSUE = 10;
private enum IssueOutcome {
@@ -142,7 +143,11 @@ public class GltTicketIssueService {
//2.执行分销员分销、统计门店/服务商分销业务
dealerOrderSettlement.orderSettlement(orderNo);
//3.执行平台分红业务 TODO 待开发
//3.执行平台分红业务
dealerOrderSettlement.partnerProfit(orderNo, tenantId);
//4.普通商品【非水票订单】如果是需要自配送的,则会同步生成派单信息
gltTicketOrderService.dispatchOrder(orderNo, tenantId);
}
@@ -188,7 +193,6 @@ public class GltTicketIssueService {
//6.更新商品订单为已完成、已收到赠品状态
if (release.get()) {
shopOrder.setOrderStatus(1);
shopOrder.setHasTakeGift(true);
shopOrder.setUpdateTime(LocalDateTime.now());
shopOrderMapper.updateById(shopOrder);

View File

@@ -2,6 +2,7 @@ package com.gxwebsoft.glt.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.glt.dto.GltTransferOrderDto;
import com.gxwebsoft.glt.entity.GltTicketOrder;
import com.gxwebsoft.glt.param.GltTicketOrderParam;
@@ -16,10 +17,10 @@ import java.time.LocalDateTime;
*/
public interface GltTicketOrderService extends IService<GltTicketOrder> {
int DELIVERY_STATUS_WAITING = 10;
int DELIVERY_STATUS_DELIVERING = 20;
int DELIVERY_STATUS_WAIT_CONFIRM = 30;
int DELIVERY_STATUS_FINISHED = 40;
int DELIVERY_STATUS_WAITING = 10; //待配送
int DELIVERY_STATUS_DELIVERING = 20; //配送中
int DELIVERY_STATUS_WAIT_CONFIRM = 30; //等待收货
int DELIVERY_STATUS_FINISHED = 40; //收货完成
int RECEIVE_CONFIRM_TYPE_MANUAL = 10;
int RECEIVE_CONFIRM_TYPE_PHOTO = 20;
@@ -64,6 +65,13 @@ public interface GltTicketOrderService extends IService<GltTicketOrder> {
*/
void accept(Integer id, Integer riderId, Integer tenantId);
/**
* 配送员转单
* @param orderDto
* @return
*/
Boolean transferOrder(GltTransferOrderDto orderDto);
/**
* 指派/接单成功后,同步关联商城订单发货状态为“已发货”(deliveryStatus=20)。
*
@@ -76,7 +84,7 @@ public interface GltTicketOrderService extends IService<GltTicketOrder> {
*
* <p>用于后台直接改 deliveryStatus=40 等不经过 confirmReceive/autoConfirmTimeout 的兜底同步。</p>
*/
void markShopOrderCompletedAfterTicketFinished(Integer ticketOrderId, Integer tenantId);
void markShopOrderCompletedAfterTicketFinished(Integer id);
/**
* 配送员开始配送10 -> 20并写 sendStartTime。
@@ -106,4 +114,10 @@ public interface GltTicketOrderService extends IService<GltTicketOrder> {
*/
int autoConfirmTimeout(Integer tenantId, LocalDateTime now, int timeoutHours, int batchSize);
/**
* 派送订单调度
* @return
*/
Boolean dispatchOrder(String orderNo, Integer tenantId);
}

View File

@@ -1,14 +1,12 @@
package com.gxwebsoft.glt.service.impl;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
import cn.binarywang.wx.miniapp.config.WxMaConfig;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.common.core.exception.BusinessException;
import com.gxwebsoft.common.core.utils.RedisUtil;
import com.gxwebsoft.common.core.utils.DateTimeUtil;
import com.gxwebsoft.glt.dto.NoticeRiderNewOrderDto;
import com.gxwebsoft.glt.entity.GltTicketOrder;
import com.gxwebsoft.glt.service.GltSubscribeMessageService;
import lombok.extern.slf4j.Slf4j;
@@ -19,7 +17,8 @@ import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import static com.gxwebsoft.common.core.constants.RedisConstants.*;
import static com.gxwebsoft.common.core.constants.RedisConstants.ACCESS_TOKEN_KEY;
import static com.gxwebsoft.common.core.constants.RedisConstants.MP_WX_KEY;
/**
* 微信订阅消息服务实现
@@ -43,7 +42,34 @@ public class GltSubscribeMessageServiceImpl implements GltSubscribeMessageServic
* 模板名称:订单配送通知
* 关键词:订单编号、订单内容、配送地址、订单金额
*/
private static final String SUBSCRIBE_TEMPLATE_ID = "YOUR_TEMPLATE_ID"; // TODO: 替换为实际模板ID
private static final String ORDER_DELIVERY_ID = "vSMSqGVy3aG1RuzQUZlk282p5hCvuMBcHvix1AFhN90";
public void sendRiderNewOrderNotice(NoticeRiderNewOrderDto entity){
//1.获取微信accessToken
String accessToken = getAccessToken(entity.getTenantId());
if(accessToken == null){
log.error("配送发单消息发生失败获取accessToken失败");
return;
}
//2.品名字段最大能发送20个长度字符大于15的长度需做处理
String goodsName = entity.getGoodsName();
int keepLength = 15;
if (goodsName.length() > keepLength) {
entity.setGoodsName(goodsName.substring(0, keepLength) + "...");
}
//3.组装入参
Map<String, Object> data = new HashMap<>();
data.put("character_string1", Map.of("value", String.valueOf(entity.getOrderNo())));
data.put("thing22", Map.of("value", String.valueOf(entity.getGoodsName())));
data.put("number20", Map.of("value", String.valueOf(entity.getProductCount())));
data.put("time24", Map.of("value", DateTimeUtil.formatDateTime(entity.getCreateTime(), "yyyy-MM-dd HH:mm:ss")));
//推送订阅消息
sendSubscribeMessage(accessToken, entity.getOpenId(), data);
}
/**
* 发送新订单通知给配送员
@@ -65,7 +91,7 @@ public class GltSubscribeMessageServiceImpl implements GltSubscribeMessageServic
// 构建消息内容
Map<String, Object> data = new HashMap<>();
data.put("phrase1", Map.of("value", "待配送")); // 订单状态
data.put("character_string2", Map.of("value", String.valueOf(order.getId()))); // 订单编号
data.put("character_string2", Map.of("value", String.valueOf(order.getOrderNo()))); // 订单编号
data.put("thing3", Map.of("value", truncateStr(order.getAddress(), 20))); // 配送地址
data.put("number4", Map.of("value", String.valueOf(order.getTotalNum()))); // 商品数量
data.put("time5", Map.of("value", formatTime(order.getSendTime()))); // 期望送达时间
@@ -196,8 +222,8 @@ public class GltSubscribeMessageServiceImpl implements GltSubscribeMessageServic
Map<String, Object> params = new HashMap<>();
params.put("touser", openId); // 用户 openid
params.put("template_id", SUBSCRIBE_TEMPLATE_ID); // 模板ID
params.put("page", "pages/rider/orders/index"); // 点击后跳转的页面
params.put("template_id", ORDER_DELIVERY_ID); // 模板ID
// params.put("page", "pages/rider/orders/index"); // 点击后跳转的页面
params.put("data", data);
String response = HttpUtil.createPost(url)
@@ -208,14 +234,14 @@ public class GltSubscribeMessageServiceImpl implements GltSubscribeMessageServic
.body();
JSONObject result = JSON.parseObject(response);
int errcode = result.getIntValue("errcode");
int errCode = result.getIntValue("errcode");
if (errcode == 0) {
if (errCode == 0) {
log.info("订阅消息发送成功 - openId={}", openId);
return true;
} else {
log.warn("订阅消息发送失败 - openId={}, errcode={}, errmsg={}",
openId, errcode, result.getString("errmsg"));
openId, errCode, result.getString("errmsg"));
return false;
}
}

View File

@@ -1,5 +1,6 @@
package com.gxwebsoft.glt.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
@@ -7,41 +8,52 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gxwebsoft.common.core.enums.ShopDealerCapitalUpdateEnum;
import com.gxwebsoft.common.core.enums.ShopDealerTypeEnum;
import com.gxwebsoft.common.core.exception.BusinessException;
import com.gxwebsoft.common.core.exception.enums.GlobalErrorCodeConstants;
import com.gxwebsoft.common.core.utils.LoginUserUtil;
import com.gxwebsoft.common.core.web.PageParam;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.common.system.mapper.UserMapper;
import com.gxwebsoft.common.system.redis.OrderNoUtils;
import com.gxwebsoft.glt.dto.GltTransferOrderDto;
import com.gxwebsoft.glt.dto.NoticeRiderNewOrderDto;
import com.gxwebsoft.glt.entity.GltTicketOrder;
import com.gxwebsoft.glt.entity.GltUserTicket;
import com.gxwebsoft.glt.entity.GltUserTicketLog;
import com.gxwebsoft.glt.mapper.GltTicketOrderMapper;
import com.gxwebsoft.glt.mapper.GltUserTicketMapper;
import com.gxwebsoft.glt.param.GltTicketOrderParam;
import com.gxwebsoft.glt.service.GltSubscribeMessageService;
import com.gxwebsoft.glt.service.GltTicketOrderService;
import com.gxwebsoft.glt.service.GltUserTicketLogService;
import com.gxwebsoft.glt.service.GltUserTicketService;
import com.gxwebsoft.shop.dto.ShopDealerUserReduceDto;
import com.gxwebsoft.shop.entity.*;
import com.gxwebsoft.shop.mapper.ShopGoodsMapper;
import com.gxwebsoft.shop.mapper.ShopStoreRiderMapper;
import com.gxwebsoft.shop.mapper.ShopUserAddressMapper;
import com.gxwebsoft.shop.service.ShopDealerCapitalService;
import com.gxwebsoft.shop.service.ShopDealerUserService;
import com.gxwebsoft.shop.service.ShopOrderGoodsService;
import com.gxwebsoft.shop.service.ShopOrderService;
import com.gxwebsoft.shop.vo.ShopOrderGoodsInfoVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
/**
@@ -93,23 +105,48 @@ public class GltTicketOrderServiceImpl extends ServiceImpl<GltTicketOrderMapper,
@Resource
private OrderNoUtils orderNoUtils;
@Resource
private ShopGoodsMapper shopGoodsMapper;
@Resource
private ShopStoreRiderMapper shopStoreRiderMapper;
@Resource
private GltSubscribeMessageService gltSubscribeMessageService;
// 轮询指针(高并发安全)
private final AtomicInteger index = new AtomicInteger(0);
@Override
public PageResult<GltTicketOrder> pageRel(GltTicketOrderParam param) {
PageParam<GltTicketOrder, GltTicketOrderParam> page = new PageParam<>(param);
page.setDefaultOrder("sort_number asc, create_time desc");
page.setDefaultOrder("create_time desc");
List<GltTicketOrder> list = baseMapper.selectPageRel(page, param);
if(CollectionUtils.isNotEmpty(list)){
List<Integer> addressIdList = list.stream().map(GltTicketOrder::getAddressId).distinct().collect(Collectors.toList());
List<String> orderNoList = list.stream().filter(gltTicketOrder -> StrUtil.isNotBlank(gltTicketOrder.getOrderNo())).map(GltTicketOrder::getOrderNo).distinct().collect(Collectors.toList());
List<ShopOrderGoodsInfoVO> orderGoodsInfoVOList = new ArrayList<>();
if(CollectionUtils.isNotEmpty(orderNoList)){
orderGoodsInfoVOList = shopOrderService.getOrderGoodsInfoByOrderNos(orderNoList);
}
List<ShopUserAddress> userAddressList = shopUserAddressMapper.selectBatchIds(addressIdList);
if(CollectionUtils.isNotEmpty(userAddressList)){
List<ShopOrderGoodsInfoVO> finalOrderGoodsInfoVOList = orderGoodsInfoVOList;
list.forEach(ticketOrder ->{
ShopUserAddress shopUserAddress = userAddressList.stream().filter(address -> ticketOrder.getAddressId().equals(address.getId())).findFirst().orElse(null);
if(shopUserAddress != null){
ticketOrder.setFullAddress(shopUserAddress.getFullAddress());
}
});
if(StrUtil.isNotBlank(ticketOrder.getOrderNo())){
ShopOrderGoodsInfoVO shopOrderGoodsInfoVO = finalOrderGoodsInfoVOList.stream().filter(orderGoodsInfoVO -> ticketOrder.getOrderNo().equals(orderGoodsInfoVO.getOrderNo())).findFirst().orElse(null);
if(shopOrderGoodsInfoVO != null){
ticketOrder.setGoodsName(shopOrderGoodsInfoVO.getGoodsName());
ticketOrder.setOrderStatus(shopOrderGoodsInfoVO.getOrderStatus());
}
}
});
}
return new PageResult<>(list, page.getTotal());
}
@@ -177,6 +214,7 @@ public class GltTicketOrderServiceImpl extends ServiceImpl<GltTicketOrderMapper,
}
// 4) 插入 glt_ticket_orderstoreId/addressId/totalNum/buyerRemarks…
gltTicketOrder.setOrderNo(userTicket.getOrderNo());
gltTicketOrder.setUserId(userId);
// 订单基础字段由后端兜底,避免前端误传/恶意传参
gltTicketOrder.setStatus(0);
@@ -194,10 +232,13 @@ public class GltTicketOrderServiceImpl extends ServiceImpl<GltTicketOrderMapper,
gltTicketOrder.setCreateTime(now);
}
// “立刻送水”下单场景不再需要前端选择配送时间;若未传则默认当前时间,便于排序与派单。
if (!StringUtils.hasText(gltTicketOrder.getSendTime())) {
if(gltTicketOrder.getSendEndTime() == null){
gltTicketOrder.setSendTime(now.format(SEND_TIME_FMT));
}
gltTicketOrder.setUpdateTime(now);
//每个骑手平等获取派单
gltTicketOrder.setRiderId(getRiderUserId());
if (!this.save(gltTicketOrder)) {
throw new BusinessException("创建订单失败");
}
@@ -233,6 +274,29 @@ public class GltTicketOrderServiceImpl extends ServiceImpl<GltTicketOrderMapper,
throw new BusinessException("写入核销记录失败");
}
//发送配送师傅派单配送消息
if(gltTicketOrder.getRiderId() != null){
User user = userMapper.getById(gltTicketOrder.getRiderId());
if(user != null){
NoticeRiderNewOrderDto noticeDto = new NoticeRiderNewOrderDto();
noticeDto.setOrderNo(gltTicketOrder.getOrderNo());
noticeDto.setGoodsName("商品信息见订单详情");
noticeDto.setProductCount(gltTicketOrder.getTotalNum());
noticeDto.setCreateTime(gltTicketOrder.getCreateTime());
noticeDto.setTenantId(tenantId);
noticeDto.setOpenId(user.getOpenid());
ShopOrder shopOrder = shopOrderService.getByOrderNo(gltTicketOrder.getOrderNo(), tenantId);
if(shopOrder != null){
Integer formId = shopOrder.getFormId();
ShopGoods shopGoods = shopGoodsMapper.selectById(formId);
if(shopGoods != null){
noticeDto.setGoodsName(shopGoods.getName());
}
}
gltSubscribeMessageService.sendRiderNewOrderNotice(noticeDto);
}
}
return gltTicketOrder;
}
@@ -300,7 +364,7 @@ public class GltTicketOrderServiceImpl extends ServiceImpl<GltTicketOrderMapper,
.update();
if (ok) {
// 接单成功后同步商城订单发货状态10未发货 -> 20已发货
updateShopOrderDeliveryStatusAfterAccept(id, tenantId, riderId, now);
updateShopOrderDeliveryStatusAfterAcceptV2(id, tenantId, riderId, now);
return;
}
@@ -320,13 +384,34 @@ public class GltTicketOrderServiceImpl extends ServiceImpl<GltTicketOrderMapper,
}
@Override
public void markShopOrderShippedAfterRiderAssigned(Integer ticketOrderId, Integer tenantId, Integer riderId) {
updateShopOrderDeliveryStatusAfterAccept(ticketOrderId, tenantId, riderId, LocalDateTime.now());
public Boolean transferOrder(GltTransferOrderDto orderDto) {
User loginUser = LoginUserUtil.getLoginUser();
if(loginUser == null){
throw new BusinessException(GlobalErrorCodeConstants.UNAUTHORIZED.getMsg());
}
GltTicketOrder gltTicketOrder = baseMapper.selectById(orderDto.getId());
if(gltTicketOrder != null){
if(!gltTicketOrder.getRiderId().equals(loginUser.getUserId())){
throw new BusinessException("该订单归属非本人,转单操作失败!");
}
gltTicketOrder.setRiderId(orderDto.getUserId());
gltTicketOrder.setUpdateTime(LocalDateTime.now());
return baseMapper.updateById(gltTicketOrder) > 0;
}else {
throw new BusinessException(GlobalErrorCodeConstants.NOT_FOUND.getMsg());
}
}
@Override
public void markShopOrderCompletedAfterTicketFinished(Integer ticketOrderId, Integer tenantId) {
updateShopOrderOrderStatusAfterTicketFinished(ticketOrderId, tenantId, LocalDateTime.now());
public void markShopOrderShippedAfterRiderAssigned(Integer ticketOrderId, Integer tenantId, Integer riderId) {
updateShopOrderDeliveryStatusAfterAcceptV2(ticketOrderId, tenantId, riderId, LocalDateTime.now());
}
@Override
public void markShopOrderCompletedAfterTicketFinished(Integer id) {
updateShopOrderOrderStatusAfterTicketFinishedV2(id);
}
private void updateShopOrderDeliveryStatusAfterAccept(Integer ticketOrderId, Integer tenantId, Integer riderId, LocalDateTime now) {
@@ -396,22 +481,6 @@ public class GltTicketOrderServiceImpl extends ServiceImpl<GltTicketOrderMapper,
shopOrderNo = order.getOrderNo();
}
}
LambdaUpdateWrapper<GltUserTicket> backfill = new LambdaUpdateWrapper<GltUserTicket>()
.eq(GltUserTicket::getTenantId, tenantId)
.eq(GltUserTicket::getDeleted, 0)
.eq(GltUserTicket::getId, userTicket.getId());
backfill.set(GltUserTicket::getOrderId, shopOrderId);
if (!StringUtils.hasText(userTicket.getOrderNo()) && StringUtils.hasText(shopOrderNo)) {
backfill.set(GltUserTicket::getOrderNo, shopOrderNo);
}
backfill.set(GltUserTicket::getUpdateTime, now);
try {
gltUserTicketService.update(backfill);
} catch (Exception e) {
log.debug("回填水票关联商城订单信息失败(不影响主流程) - tenantId={}, userTicketId={}, orderId={}, orderNo={}",
tenantId, userTicket.getId(), shopOrderId, shopOrderNo, e);
}
}
LambdaUpdateWrapper<ShopOrder> uw = new LambdaUpdateWrapper<ShopOrder>()
@@ -459,6 +528,20 @@ public class GltTicketOrderServiceImpl extends ServiceImpl<GltTicketOrderMapper,
}
}
private void updateShopOrderDeliveryStatusAfterAcceptV2(Integer ticketOrderId, Integer tenantId, Integer riderId, LocalDateTime now) {
GltTicketOrder gltTicketOrder = baseMapper.selectById(ticketOrderId);
if(gltTicketOrder != null && StrUtil.isNotBlank(gltTicketOrder.getOrderNo())){
String orderNo = gltTicketOrder.getOrderNo();
ShopOrder shopOrder = shopOrderService.getByOrderNo(orderNo, tenantId);
if(shopOrder != null && shopOrder.getOrderStatus() == 0){
shopOrder.setDeliveryStatus(20);
shopOrder.setUpdateTime(now);
shopOrderService.updateById(shopOrder);
}
}
}
@Override
public void start(Integer id, Integer riderId, Integer tenantId) {
if (id == null) {
@@ -682,7 +765,80 @@ public class GltTicketOrderServiceImpl extends ServiceImpl<GltTicketOrderMapper,
return confirmed;
}
private void updateShopOrderOrderStatusAfterTicketFinished(Integer ticketOrderId, Integer tenantId, LocalDateTime now) {
@Override
public Boolean dispatchOrder(String orderNo, Integer tenantId) {
ShopOrder shopOrder = shopOrderService.getByOrderNo(orderNo, tenantId);
if(shopOrder != null){
LocalDateTime now = LocalDateTime.now();
//只有:1-及时自配送、3-预约自配送 方式会生成调度单
if(Arrays.asList(1, 3).contains(shopOrder.getOrderType())){
GltTicketOrder dispatchOrder = BeanUtil.toBean(shopOrder, GltTicketOrder.class);
String no = orderNoUtils.generate("S");
dispatchOrder.setNo(no);
dispatchOrder.setRiderId(getRiderUserId());
dispatchOrder.setSendTime(now.format(SEND_TIME_FMT));
Integer deliveryMethod = shopOrder.getDeliveryMethod();
if(deliveryMethod != null && deliveryMethod == 1){
dispatchOrder.setDeliveryMethod("stairs");
}else {
dispatchOrder.setDeliveryMethod("elevator");
}
dispatchOrder.setComments("系统自动派单");
dispatchOrder.setCreateTime(now);
dispatchOrder.setUpdateTime(now);
baseMapper.insert(dispatchOrder);
//推送配送师傅接单提醒
if(dispatchOrder.getRiderId() != null){
User user = userMapper.getById(dispatchOrder.getRiderId());
if(user != null){
NoticeRiderNewOrderDto noticeDto = new NoticeRiderNewOrderDto();
noticeDto.setOrderNo(dispatchOrder.getOrderNo());
noticeDto.setGoodsName("商品信息见订单详情");
noticeDto.setProductCount(dispatchOrder.getTotalNum());
noticeDto.setCreateTime(dispatchOrder.getCreateTime());
noticeDto.setTenantId(tenantId);
noticeDto.setOpenId(user.getOpenid());
if(shopOrder != null){
Integer formId = shopOrder.getFormId();
ShopGoods shopGoods = shopGoodsMapper.selectById(formId);
if(shopGoods != null){
noticeDto.setGoodsName(shopGoods.getName());
}
}
gltSubscribeMessageService.sendRiderNewOrderNotice(noticeDto);
}
}
}
}
return Boolean.TRUE;
}
/**
* 每个骑手平等获取派单
* @return
*/
private Integer getRiderUserId(){
List<ShopStoreRider> shopStoreRiders = shopStoreRiderMapper.selectList(new LambdaQueryWrapper<ShopStoreRider>().select(ShopStoreRider::getUserId).in(ShopStoreRider::getWorkStatus, Arrays.asList(1, 2)));
if(CollectionUtils.isNotEmpty(shopStoreRiders)){
List<Integer> riderIdList = shopStoreRiders.stream().map(ShopStoreRider::getUserId).distinct().collect(Collectors.toList());
int i = index.getAndIncrement() % riderIdList.size();
return riderIdList.get(i);
}
return null;
}
/**
* 更新送水订单为已完成状态
* @param ticketOrderId
* @param tenantId
* @param now
*/
@Transactional
public void updateShopOrderOrderStatusAfterTicketFinished(Integer ticketOrderId, Integer tenantId, LocalDateTime now) {
if (ticketOrderId == null || tenantId == null) {
return;
}
@@ -692,7 +848,8 @@ public class GltTicketOrderServiceImpl extends ServiceImpl<GltTicketOrderMapper,
// 找到关联水票的商城订单glt_user_ticket.orderId / orderNo
GltTicketOrder ticketOrder = this.lambdaQuery()
.select(GltTicketOrder::getId, GltTicketOrder::getUserTicketId)
.select(GltTicketOrder::getId, GltTicketOrder::getUserTicketId, GltTicketOrder::getTotalNum, GltTicketOrder::getRiderId,
GltTicketOrder::getUserId, GltTicketOrder::getNo)
.eq(GltTicketOrder::getId, ticketOrderId)
.eq(GltTicketOrder::getTenantId, tenantId)
.eq(GltTicketOrder::getDeleted, 0)
@@ -768,15 +925,70 @@ public class GltTicketOrderServiceImpl extends ServiceImpl<GltTicketOrderMapper,
}
}
//查询未完成订单,完成资金解冻
LambdaQueryWrapper<ShopOrder> orderLambdaQueryWrapper;
if(shopOrderId != null){
orderLambdaQueryWrapper = new LambdaQueryWrapper<ShopOrder>().eq(ShopOrder::getOrderId, shopOrderId).eq(ShopOrder::getOrderStatus, 0);
ShopOrder order = shopOrderService.getByOrderNo(userTicket.getOrderNo(), userTicket.getTenantId());
//生成配送师傅可提现账户分佣金额数据【配送奖励(按商品设置)、配送提成(每桶0.1)】
int qty = ticketOrder.getTotalNum() == null ? 0 : ticketOrder.getTotalNum();
if (qty > 0) { //配送提成(每桶0.1)
BigDecimal money = RIDER_UNIT_COMMISSION
.multiply(BigDecimal.valueOf(qty))
.setScale(RIDER_COMMISSION_SCALE, RoundingMode.HALF_UP);
if (money.signum() > 0) {
ShopDealerUserReduceDto reduceDto = new ShopDealerUserReduceDto();
reduceDto.setTypeEnum(ShopDealerTypeEnum.WITHDRAW_ACCOUNT);
reduceDto.setUserId(ticketOrder.getRiderId());
reduceDto.setOrderUserId(ticketOrder.getUserId());
if(Arrays.asList(1, 3).contains(order.getOrderType())){
reduceDto.setOrderNo(order.getOrderNo());
}else {
orderLambdaQueryWrapper = new LambdaQueryWrapper<ShopOrder>().eq(ShopOrder::getOrderId, shopOrderNo).eq(ShopOrder::getOrderStatus, 0);
reduceDto.setOrderNo(ticketOrder.getNo());
}
ShopOrder order = shopOrderService.getOne(orderLambdaQueryWrapper);
if(order != null){
reduceDto.setPrice(money);
reduceDto.setUpdateEnum(ShopDealerCapitalUpdateEnum.DELIVERY_INCOME);
shopDealerUserService.reduceBalance(reduceDto);
}
}
//配送奖励(按商品设置)
Integer goodsId = userTicket.getGoodsId();
ShopGoods shopGood = shopGoodsMapper.selectById(goodsId);
if(shopGood != null && order != null){
Integer commissionType = shopGood.getCommissionType();
BigDecimal money = BigDecimal.ZERO;
if(commissionType == 10){ //按金额
money = shopGood.getDeliveryMoney();
}else { //按比率
money = order.getPayPrice().multiply(shopGood.getDeliveryMoney()).divide(BigDecimal.valueOf(100), 3, RoundingMode.HALF_UP);
}
if(money.compareTo(BigDecimal.ZERO) > 0){
ShopDealerUserReduceDto reduceDto = new ShopDealerUserReduceDto();
reduceDto.setTypeEnum(ShopDealerTypeEnum.WITHDRAW_ACCOUNT);
reduceDto.setUserId(ticketOrder.getRiderId());
reduceDto.setOrderUserId(ticketOrder.getUserId());
if(Arrays.asList(1, 3).contains(order.getOrderType())){
reduceDto.setOrderNo(order.getOrderNo());
}else {
reduceDto.setOrderNo(ticketOrder.getNo());
}
reduceDto.setPrice(money);
reduceDto.setUpdateEnum(ShopDealerCapitalUpdateEnum.DELIVERY_REWARD);
shopDealerUserService.reduceBalance(reduceDto);
}
}
//配送费结算
if(Arrays.asList(1, 3).contains(order.getOrderType()) && order.getDeliveryFee().compareTo(BigDecimal.ZERO) > 0){
ShopDealerUserReduceDto reduceDto = new ShopDealerUserReduceDto();
reduceDto.setTypeEnum(ShopDealerTypeEnum.WITHDRAW_ACCOUNT);
reduceDto.setUserId(ticketOrder.getRiderId());
reduceDto.setOrderUserId(ticketOrder.getUserId());
reduceDto.setOrderNo(order.getOrderNo());
reduceDto.setPrice(order.getDeliveryFee());
reduceDto.setUpdateEnum(ShopDealerCapitalUpdateEnum.DELIVERY_FLOOR_FEE);
shopDealerUserService.reduceBalance(reduceDto);
}
//查询未完成订单,完成资金解冻
if(order != null && order.getOrderStatus() == 0){
ShopDealerUserReduceDto reduceDto = new ShopDealerUserReduceDto();
reduceDto.setTypeEnum(ShopDealerTypeEnum.DEFROST);
reduceDto.setOrderUserId(order.getUserId());
@@ -819,6 +1031,104 @@ public class GltTicketOrderServiceImpl extends ServiceImpl<GltTicketOrderMapper,
}
}
/**
* 更新送水订单为已完成状态
* @param id 送水订单ID
*/
@Transactional
public void updateShopOrderOrderStatusAfterTicketFinishedV2(Integer id) {
LocalDateTime now = LocalDateTime.now();
if(id == null){
return;
}
//1.找到关联水票的商城订单
GltTicketOrder ticketOrder = baseMapper.selectById(id);
if (ticketOrder == null) {
return;
}
ShopOrder order = shopOrderService.getByOrderNo(ticketOrder.getOrderNo(), ticketOrder.getTenantId());
//2.配送提成(每桶0.1)
int qty = ticketOrder.getTotalNum() == null ? 0 : ticketOrder.getTotalNum();
if (qty > 0) {
BigDecimal money = RIDER_UNIT_COMMISSION
.multiply(BigDecimal.valueOf(qty))
.setScale(RIDER_COMMISSION_SCALE, RoundingMode.HALF_UP);
if (money.signum() > 0) {
ShopDealerUserReduceDto reduceDto = new ShopDealerUserReduceDto();
reduceDto.setTypeEnum(ShopDealerTypeEnum.WITHDRAW_ACCOUNT);
reduceDto.setUserId(ticketOrder.getRiderId());
reduceDto.setOrderUserId(ticketOrder.getUserId());
if(Arrays.asList(1, 3).contains(order.getOrderType())){
reduceDto.setOrderNo(order.getOrderNo());
}else {
reduceDto.setOrderNo(ticketOrder.getNo());
}
reduceDto.setPrice(money);
reduceDto.setUpdateEnum(ShopDealerCapitalUpdateEnum.DELIVERY_INCOME);
shopDealerUserService.reduceBalance(reduceDto);
}
}
//3.配送奖励(按商品设置)
Integer goodsId = order.getFormId();
ShopGoods shopGood = shopGoodsMapper.selectById(goodsId);
if(shopGood != null && order != null){
Integer commissionType = shopGood.getCommissionType();
BigDecimal money = BigDecimal.ZERO;
if(commissionType == 10){ //按金额
money = shopGood.getDeliveryMoney();
}else { //按比率
money = order.getPayPrice().multiply(shopGood.getDeliveryMoney()).divide(BigDecimal.valueOf(100), 3, RoundingMode.HALF_UP);
}
if(money.compareTo(BigDecimal.ZERO) > 0){
ShopDealerUserReduceDto reduceDto = new ShopDealerUserReduceDto();
reduceDto.setTypeEnum(ShopDealerTypeEnum.WITHDRAW_ACCOUNT);
reduceDto.setUserId(ticketOrder.getRiderId());
reduceDto.setOrderUserId(ticketOrder.getUserId());
if(Arrays.asList(1, 3).contains(order.getOrderType())){
reduceDto.setOrderNo(order.getOrderNo());
}else {
reduceDto.setOrderNo(ticketOrder.getNo());
}
reduceDto.setPrice(money);
reduceDto.setUpdateEnum(ShopDealerCapitalUpdateEnum.DELIVERY_REWARD);
shopDealerUserService.reduceBalance(reduceDto);
}
}
//4.配送费结算
if(Arrays.asList(1, 3).contains(order.getOrderType()) && order.getDeliveryFee().compareTo(BigDecimal.ZERO) > 0){
ShopDealerUserReduceDto reduceDto = new ShopDealerUserReduceDto();
reduceDto.setTypeEnum(ShopDealerTypeEnum.WITHDRAW_ACCOUNT);
reduceDto.setUserId(ticketOrder.getRiderId());
reduceDto.setOrderUserId(ticketOrder.getUserId());
reduceDto.setOrderNo(order.getOrderNo());
reduceDto.setPrice(order.getDeliveryFee());
reduceDto.setUpdateEnum(ShopDealerCapitalUpdateEnum.DELIVERY_FLOOR_FEE);
shopDealerUserService.reduceBalance(reduceDto);
}
//5.查询未完成订单,完成资金解冻
if(order != null && order.getOrderStatus() == 0){
ShopDealerUserReduceDto reduceDto = new ShopDealerUserReduceDto();
reduceDto.setTypeEnum(ShopDealerTypeEnum.DEFROST);
reduceDto.setOrderUserId(order.getUserId());
reduceDto.setOrderNo(order.getOrderNo());
reduceDto.setUpdateEnum(ShopDealerCapitalUpdateEnum.FREEZE_MONEY_THAW);
//按订单号资金解冻
shopDealerUserService.reduceBalance(reduceDto);
}
//5.调整订单为已完成、配送完成状态
order.setOrderStatus(1);
order.setDeliveryStatus(40);
order.setUpdateTime(now);
shopOrderService.updateById(order);
}
private void settleRiderCommissionIfEligible(Integer ticketOrderId, Integer tenantId, boolean requirePhoto) {
if (ticketOrderId == null || tenantId == null) {
return;

View File

@@ -116,7 +116,7 @@ public class DealerCommissionUnfreeze10584Task {
private final AtomicBoolean running = new AtomicBoolean(false);
@Scheduled(cron = "${dealer.commission.unfreeze10584.cron:0/50 * * * * ?}")
// @Scheduled(cron = "${dealer.commission.unfreeze10584.cron:0/50 * * * * ?}")
@IgnoreTenant("定时任务无登录态,需忽略租户隔离;内部使用 tenantId=10584 精确过滤")
public void run() {
if (!running.compareAndSet(false, true)) {

View File

@@ -8,8 +8,12 @@ import com.gxwebsoft.common.core.enums.ShopDealerCapitalUpdateEnum;
import com.gxwebsoft.common.core.enums.ShopDealerTypeEnum;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.common.system.mapper.UserMapper;
import com.gxwebsoft.common.system.redis.OrderNoUtils;
import com.gxwebsoft.glt.entity.GltTicketTemplate;
import com.gxwebsoft.glt.service.GltTicketTemplateService;
import com.gxwebsoft.glt.vo.UserRelationVO;
import com.gxwebsoft.shop.dto.ShopDealerSettlementDto;
import com.gxwebsoft.shop.dto.ShopDealerSettlementItemDto;
import com.gxwebsoft.shop.dto.ShopDealerUserReduceDto;
import com.gxwebsoft.shop.entity.*;
import com.gxwebsoft.shop.mapper.ShopDealerRefereeMapper;
@@ -17,6 +21,7 @@ import com.gxwebsoft.shop.mapper.ShopOrderMapper;
import com.gxwebsoft.shop.service.*;
import com.gxwebsoft.shop.util.UpstreamUserFinder;
import com.gxwebsoft.shop.vo.ShopDealerRefereeVO;
import com.gxwebsoft.shop.vo.ShopGoodsProfitVO;
import com.gxwebsoft.shop.vo.ShopOrderGoodsVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
@@ -33,6 +38,7 @@ import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
/**
* 租户10584分销订单结算任务
@@ -94,6 +100,12 @@ public class DealerOrderSettlement10584Task {
@Resource
private ShopDealerRefereeMapper shopDealerRefereeMapper;
@Resource
private ShopGoodsProfitService shopGoodsProfitService;
@Resource
private OrderNoUtils orderNoUtils;
/**
* 每10秒执行一次。
*/
@@ -191,7 +203,7 @@ public class DealerOrderSettlement10584Task {
if (!claimOrderToSettle(order.getOrderId(), waterFormIds)) {
return;
}
settleOneOrderV2(order, level1ParentCache, shopRoleCache, totalDealerUser, dealerBasicSetting.level);
settleOneOrderV2(order, dealerBasicSetting.level);
});
} catch (Exception e) {
log.error("订单结算失败,将回滚本订单并在下次任务重试 - orderId={}, orderNo={}", order.getOrderId(), order.getOrderNo(), e);
@@ -225,11 +237,73 @@ public class DealerOrderSettlement10584Task {
if (!claimOrderToSettleV2(order.getOrderId())) {
return;
}
settleOneOrderV2(order, level1ParentCache, shopRoleCache, totalDealerUser, dealerBasicSetting.level);
settleOneOrderV2(order, dealerBasicSetting.level);
});
}
}
/**
* 股东/合伙人分红
* @param orderNo 订单号
* @return
*/
@Transactional
public Boolean partnerProfit(String orderNo, Integer tenantId){
//1.查询订单信息
ShopOrder shopOrder = shopOrderService.getByOrderNo(orderNo, tenantId);
if(shopOrder != null){
//2.查询订单号订单所有已开启分销的商品分润信息
List<ShopOrderGoodsVO> orderGoodsVOList = shopOrderMapper.getOrderGoodsInfo(orderNo);
if(CollectionUtils.isNotEmpty(orderGoodsVOList)){
//3.计算商品实付比例
BigDecimal rate = shopOrder.getPayPrice().divide(shopOrder.getTotalPrice(), 2, RoundingMode.HALF_UP);
//4.查询商品分红设定比例数据
List<Integer> goodsIdList = orderGoodsVOList.stream().map(ShopOrderGoodsVO::getGoodsId).distinct().collect(Collectors.toList());
List<ShopGoodsProfitVO> goodsProfitVOList = shopGoodsProfitService.getGoodsProfit(goodsIdList, 1);
if(CollectionUtils.isNotEmpty(goodsProfitVOList)){
List<ShopDealerSettlementItemDto> itemList = new ArrayList<>();
//5.按照商品分组分润信息
Map<Integer, List<ShopGoodsProfitVO>> goodsProfitMap = goodsProfitVOList.stream().collect(Collectors.groupingBy(ShopGoodsProfitVO::getGoodsId));
//6.遍历商品获取分红子项数据
orderGoodsVOList.forEach(orderGoodsVO ->{
List<ShopGoodsProfitVO> profitVOS = goodsProfitMap.get(orderGoodsVO.getGoodsId());
if(CollectionUtils.isNotEmpty(profitVOS)){
BigDecimal itemPrice = orderGoodsVO.getPrice().multiply(BigDecimal.valueOf(orderGoodsVO.getTotalNum()));
BigDecimal itemProfitPrice = itemPrice.multiply(rate).setScale(3, RoundingMode.HALF_UP);
profitVOS.forEach(profitVO ->{
ShopDealerSettlementItemDto itemDto = new ShopDealerSettlementItemDto();
String no = orderNoUtils.generate("C");
BigDecimal money = profitVO.getProfit().divide(BigDecimal.valueOf(100)).multiply(itemProfitPrice).setScale(3, RoundingMode.HALF_UP);
itemDto.setNo(no);
itemDto.setUserId(profitVO.getUserId());
itemDto.setMoney(money);
itemList.add(itemDto);
});
}
});
//7.存在分红子项数据,则批量结算
if(CollectionUtils.isNotEmpty(itemList)){
ShopDealerSettlementDto settlementDto = new ShopDealerSettlementDto();
settlementDto.setOrderNo(orderNo);
settlementDto.setToUserId(shopOrder.getUserId());
settlementDto.setTenantId(tenantId);
settlementDto.setItemList(itemList);
shopDealerUserService.orderProfit(settlementDto);
}
}
}
}
return Boolean.TRUE;
}
private List<ShopOrder> findUnsettledPaidOrders(Set<Integer> waterFormIds) {
// 租户10584约定
// - 普通订单以发货为准deliveryStatus=20才结算
@@ -355,8 +429,7 @@ public class DealerOrderSettlement10584Task {
log.info("订单结算完成 - orderId={}, orderNo={}, baseAmount={}", order.getOrderId(), order.getOrderNo(), baseAmount);
}
private void settleOneOrderV2(ShopOrder order, Map<Integer, Integer> level1ParentCache, Map<Integer, Boolean> shopRoleCache,
ShopDealerUser totalDealerUser, int dealerLevel) {
private void settleOneOrderV2(ShopOrder order, int dealerLevel) {
if (order.getUserId() == null || order.getOrderNo() == null) {
throw new IllegalStateException("订单关键信息缺失,无法结算 - orderId=" + order.getOrderId());
}
@@ -378,14 +451,10 @@ public class DealerOrderSettlement10584Task {
// 2) 门店分润上级:从下单用户开始逐级向上找,命中 ShopDealerUser.type=1 的最近两级(直推门店/间推门店)【只统计数据,不对分销账户进行处理,
// 已日结形式统计分销记录表shop_dealer_order 做对应一级二级管理津贴结算】
ShopRoleCommission shopRoleCommission = settleShopRoleRefereeCommissionV2(order, rate, orderGoodsVOList, level1ParentCache, shopRoleCache);
ShopRoleCommission shopRoleCommission = settleShopRoleRefereeCommissionV2(order, rate, orderGoodsVOList);
// 3) 分红:固定比率,每个订单都分 TODO 总分红未开发,还按原逻辑走
int goodsQty = orderGoodsVOList.stream().mapToInt(ShopOrderGoodsVO::getTotalNum).sum();
TotalDealerCommission totalDealerCommission = settleTotalDealerCommissionV2(order, goodsQty, totalDealerUser);
// 4) 写入分销订单记录(用于排查/统计;详细分佣以 ShopDealerCapital 为准)
createDealerOrderRecordV2(order, dealerRefereeCommission, shopRoleCommission, totalDealerCommission);
// 3) 写入分销订单记录(用于排查/统计;详细分佣以 ShopDealerCapital 为准)
createDealerOrderRecordV2(order, dealerRefereeCommission, shopRoleCommission);
log.info("订单结算完成 - orderId={}, orderNo={}, baseAmount={}", order.getOrderId(), order.getOrderNo(), payPrice);
}else {
@@ -486,6 +555,9 @@ public class DealerOrderSettlement10584Task {
ShopDealerRefereeVO dealerRefereeVO = shopDealerRefereeMapper.getDealerIdByUserId(order.getUserId());
if(dealerRefereeVO == null){
return null;
}
if (dealerLevel == 1) {
Integer directUserId = dealerRefereeVO.getDirectUserId();
Integer directUserType = dealerRefereeVO.getDirectUserType();
@@ -518,13 +590,13 @@ public class DealerOrderSettlement10584Task {
//一级分销员存在(type = 0)且单项实付金额大于0及商品设置了一级分销比例/金额
if(finalDirectDealerId != null && itemRatePrice.compareTo(BigDecimal.ZERO) > 0 && firstMoney.compareTo(BigDecimal.ZERO) > 0){
BigDecimal one = calcMoneyByCommissionType(itemRatePrice, firstMoney, orderGoodsVO.getTotalNum(), 2, orderGoodsVO.getCommissionType());
BigDecimal one = calcMoneyByCommissionType(itemRatePrice, firstMoney, orderGoodsVO.getTotalNum(), 3, orderGoodsVO.getCommissionType());
directMoney.accumulateAndGet(one, BigDecimal::add);
}
//一级分销员存在(type = 0)且单项实付金额大于0及商品设置了一级分销比例/金额
if(finalSimpleDealerId != null && itemRatePrice.compareTo(BigDecimal.ZERO) > 0 && secondMoney.compareTo(BigDecimal.ZERO) > 0 ){
BigDecimal two = calcMoneyByCommissionType(itemRatePrice, secondMoney, orderGoodsVO.getTotalNum(), 2, orderGoodsVO.getCommissionType());
BigDecimal two = calcMoneyByCommissionType(itemRatePrice, secondMoney, orderGoodsVO.getTotalNum(), 3, orderGoodsVO.getCommissionType());
simpleMoney.accumulateAndGet(two, BigDecimal::add);
}
});
@@ -640,28 +712,18 @@ public class DealerOrderSettlement10584Task {
return new ShopRoleCommission(shopRoleReferees.get(0), storeDirectMoney, shopRoleReferees.get(1), storeSimpleMoney);
}
private ShopRoleCommission settleShopRoleRefereeCommissionV2(ShopOrder order, BigDecimal rate, List<ShopOrderGoodsVO> orderGoodsVOList, Map<Integer, Integer> level1ParentCache, Map<Integer, Boolean> shopRoleCache) {
List<Integer> shopRoleReferees = findFirstTwoShopRoleReferees(order.getUserId(), level1ParentCache, shopRoleCache);
log.info("门店分润命中结果(type=1门店角色取前两级) - orderNo={}, buyerUserId={}, shopRoleReferees={}",
order.getOrderNo(), order.getUserId(), shopRoleReferees);
if (shopRoleReferees.isEmpty()) {
private ShopRoleCommission settleShopRoleRefereeCommissionV2(ShopOrder order, BigDecimal rate, List<ShopOrderGoodsVO> orderGoodsVOList) {
UserRelationVO userSuperior = shopDealerUserService.getUserSuperior(order.getUserId());
Integer storeDirectUserId = userSuperior.getStoreUserId();
Integer storeSimpleUserId = userSuperior.getServiceUserId();
if(storeDirectUserId == null && storeSimpleUserId == null){
return ShopRoleCommission.empty();
}
if(CollectionUtils.isNotEmpty(shopRoleReferees)){
Integer storeDirectUserId;
Integer storeSimpleUserId = null;
AtomicReference<BigDecimal> storeDirectMoney = new AtomicReference<>(BigDecimal.ZERO);
AtomicReference<BigDecimal> storeSimpleMoney = new AtomicReference<>(BigDecimal.ZERO);
if(shopRoleReferees.size() == 1){
storeDirectUserId = shopRoleReferees.get(0);
}else {
storeDirectUserId = shopRoleReferees.get(0);
storeSimpleUserId = shopRoleReferees.get(1);
}
Integer finalStoreDirectUserId = storeDirectUserId;
Integer finalStoreSimpleUserId = storeSimpleUserId;
orderGoodsVOList.forEach(orderGoodsVO ->{
@@ -673,19 +735,16 @@ public class DealerOrderSettlement10584Task {
BigDecimal itemRatePrice = orderGoodsVO.getPrice().multiply(BigDecimal.valueOf(orderGoodsVO.getTotalNum())).multiply(rate);
if(finalStoreDirectUserId != null && itemRatePrice.compareTo(BigDecimal.ZERO) > 0){
BigDecimal one = calcMoneyByCommissionType(itemRatePrice, firstMoney, orderGoodsVO.getTotalNum(), 2, orderGoodsVO.getCommissionType());
BigDecimal one = calcMoneyByCommissionType(itemRatePrice, firstMoney, orderGoodsVO.getTotalNum(), 3, orderGoodsVO.getCommissionType());
storeDirectMoney.accumulateAndGet(one, BigDecimal::add);
}
if(finalStoreSimpleUserId != null && itemRatePrice.compareTo(BigDecimal.ZERO) > 0){
BigDecimal two = calcMoneyByCommissionType(itemRatePrice, secondMoney, orderGoodsVO.getTotalNum(), 2, orderGoodsVO.getCommissionType());
BigDecimal two = calcMoneyByCommissionType(itemRatePrice, secondMoney, orderGoodsVO.getTotalNum(), 3, orderGoodsVO.getCommissionType());
storeSimpleMoney.accumulateAndGet(two, BigDecimal::add);
}
});
return new ShopRoleCommission(storeDirectUserId, storeDirectMoney.get(), storeSimpleUserId, storeSimpleMoney.get());
}else {
return null;
}
}
private TotalDealerCommission settleTotalDealerCommission(
@@ -1064,7 +1123,7 @@ public class DealerOrderSettlement10584Task {
* @param dealerRefereeCommission 一级、二级分销员分销数据
* @param shopRoleCommission 门店/服务商一级、二级管理津贴数据
*/
private void createDealerOrderRecordV2(ShopOrder order, DealerRefereeCommissionV2 dealerRefereeCommission, ShopRoleCommission shopRoleCommission, TotalDealerCommission totalDealerCommission) {
private void createDealerOrderRecordV2(ShopOrder order, DealerRefereeCommissionV2 dealerRefereeCommission, ShopRoleCommission shopRoleCommission) {
// 幂等:同一订单只写一条(依赖 order_no + tenant_id 作为业务唯一)
ShopDealerOrder existed = shopDealerOrderService.getOne(
new LambdaQueryWrapper<ShopDealerOrder>()
@@ -1138,7 +1197,7 @@ public class DealerOrderSettlement10584Task {
dealerOrder.setSettleTime(LocalDateTime.now());
dealerOrder.setMonth(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM")));
dealerOrder.setTenantId(TENANT_ID);
dealerOrder.setComments(buildCommissionTraceCommentV2(dealerRefereeCommission, shopRoleCommission, totalDealerCommission));
dealerOrder.setComments(buildCommissionTraceCommentV2(dealerRefereeCommission, shopRoleCommission));
shopDealerOrderService.save(dealerOrder);
}
@@ -1160,8 +1219,7 @@ public class DealerOrderSettlement10584Task {
private String buildCommissionTraceCommentV2(
DealerRefereeCommissionV2 dealerRefereeCommission,
ShopRoleCommission shopRoleCommission,
TotalDealerCommission totalDealerCommission
ShopRoleCommission shopRoleCommission
) {
// 轻量“过程”留痕,方便排查;详细分佣以 ShopDealerCapital 为准。
Integer direct = dealerRefereeCommission != null ? dealerRefereeCommission.directDealerId : null;
@@ -1172,14 +1230,11 @@ public class DealerOrderSettlement10584Task {
BigDecimal storeDirectMoney = shopRoleCommission != null ? shopRoleCommission.storeDirectMoney : BigDecimal.ZERO;
Integer storeSimpleUserId = shopRoleCommission != null ? shopRoleCommission.storeSimpleUserId : null;
BigDecimal storeSimpleMoney = shopRoleCommission != null ? shopRoleCommission.storeSimpleMoney : BigDecimal.ZERO;
Integer userId = totalDealerCommission != null ? totalDealerCommission.userId : null;
BigDecimal money = totalDealerCommission != null ? totalDealerCommission.money : BigDecimal.ZERO;
return "direct=" + direct + ":" + directMoney
+ ",simple=" + simpleDealerId + ":" + simpleMoney
+ ",dividend1=" + storeDirectUserId + ":" + storeDirectMoney
+ ",dividend2=" + storeSimpleUserId + ":" + storeSimpleMoney
+ ",totalDealer=" + userId + ":" + money;
+ ",dividend2=" + storeSimpleUserId + ":" + storeSimpleMoney;
}
private BigDecimal getOrderBaseAmount(ShopOrder order) {

View File

@@ -34,7 +34,7 @@ public class GltTicketOrderAutoConfirm10584Task {
private final AtomicBoolean running = new AtomicBoolean(false);
@Scheduled(cron = "${glt.ticket-order.auto-confirm10584.cron:0/33 * * * * ?}")
// @Scheduled(cron = "${glt.ticket-order.auto-confirm10584.cron:0/33 * * * * ?}")
@IgnoreTenant("定时任务无登录态,需忽略租户隔离;内部使用 tenantId=10584 精确过滤")
public void run() {
if (!running.compareAndSet(false, true)) {

View File

@@ -35,7 +35,7 @@ public class GltTicketOrderAutoDispatch10584Task {
@Value("${glt.ticket.dispatch10584.batchSize:50}")
private int batchSize;
@Scheduled(cron = "${glt.ticket.dispatch10584.cron:0/20 * * * * ?}")
// @Scheduled(cron = "${glt.ticket.dispatch10584.cron:0/20 * * * * ?}")
@IgnoreTenant("定时任务无登录态,需忽略租户隔离;内部使用 tenantId=10584 精确过滤")
public void run() {
if (!running.compareAndSet(false, true)) {

View File

@@ -0,0 +1,16 @@
package com.gxwebsoft.glt.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
public class UserRelationVO {
@Schema(description = "当前用户ID")
private Integer userId;
@Schema(description = "上级门店ID")
private Integer storeUserId;
@Schema(description = "上级服务商ID")
private Integer serviceUserId;
}

View File

@@ -230,7 +230,7 @@ public class PaymentConstants {
*/
public static class Environment {
/** 开发环境 */
public static final String DEV = "dev";
public static final String DEV = "local";
/** 测试环境 */
public static final String TEST = "test";
/** 生产环境 */

View File

@@ -148,7 +148,7 @@ public class WxPayConfigService {
log.info("从数据库获取支付配置成功租户ID: {},将缓存配置", tenantId);
// 开发环境下如果apiclientKey为空设置默认值
if ("dev".equals(activeProfile) &&
if ("local".equals(activeProfile) &&
(payment.getApiclientKey() == null || payment.getApiclientKey().trim().isEmpty())) {
log.warn("开发环境数据库配置中apiclientKey为空使用默认值租户ID: {}", tenantId);
payment.setApiclientKey("apiclient_key.pem");
@@ -167,7 +167,7 @@ public class WxPayConfigService {
}
// 数据库也没有配置
if (!"dev".equals(activeProfile)) {
if (!"local".equals(activeProfile)) {
throw PaymentException.systemError("微信支付配置未找到租户ID: " + tenantId + ",请检查数据库配置", null);
}
@@ -180,7 +180,7 @@ public class WxPayConfigService {
* 获取证书文件路径
*/
private String getCertificatePath(Integer tenantId, Payment payment) throws PaymentException {
if ("dev".equals(activeProfile)) {
if ("local".equals(activeProfile)) {
return getDevCertificatePath(tenantId);
} else {
return getProdCertificatePath(payment);
@@ -237,7 +237,7 @@ public class WxPayConfigService {
*/
private Config createWxPayConfig(Payment payment, String certificatePath) throws PaymentException {
try {
if ("dev".equals(activeProfile) && payment == null) {
if ("local".equals(activeProfile) && payment == null) {
// 开发环境测试配置
return createDevTestConfig(certificatePath);
} else if (payment != null) {
@@ -343,7 +343,7 @@ public class WxPayConfigService {
// 开发环境下如果apiclientKey为空给一个警告但不抛异常
// 生产环境必须有apiclientKey
if (payment.getApiclientKey() == null || payment.getApiclientKey().trim().isEmpty()) {
if ("dev".equals(activeProfile)) {
if ("local".equals(activeProfile)) {
log.warn("开发环境:证书文件名(apiclientKey)未配置,将使用默认值");
} else {
throw PaymentException.systemError("证书文件名(apiclientKey)未配置", null);

View File

@@ -78,7 +78,7 @@ public class WxPayConstants {
public static final int AMOUNT_MULTIPLIER = 100;
/** 开发环境标识 */
public static final String PROFILE_DEV = "dev";
public static final String PROFILE_DEV = "local";
/** 生产环境标识 */
public static final String PROFILE_PROD = "prod";
}

View File

@@ -6,9 +6,11 @@ import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.common.core.web.BatchParam;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.shop.dto.ShopDealerCapitalWaterDto;
import com.gxwebsoft.shop.entity.ShopDealerCapital;
import com.gxwebsoft.shop.param.ShopDealerCapitalParam;
import com.gxwebsoft.shop.service.ShopDealerCapitalService;
import com.gxwebsoft.shop.vo.ShopDealerCapitalWaterVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springdoc.api.annotations.ParameterObject;
@@ -39,6 +41,14 @@ public class ShopDealerCapitalController extends BaseController {
return success(shopDealerCapitalService.pageRel(param));
}
@PreAuthorize("hasAuthority('shop:shopDealerCapital:list')")
@Operation(summary = "分页查询分销商个人流水")
@GetMapping("/myCapitalWater")
public ApiResult<PageResult<ShopDealerCapitalWaterVO>> myCapitalWater(ShopDealerCapitalWaterDto waterDto) {
// 使用关联查询
return success(shopDealerCapitalService.myCapitalWater(waterDto));
}
@PreAuthorize("hasAuthority('shop:shopDealerCapital:list')")
@Operation(summary = "查询全部分销商资金明细表")
@GetMapping()

View File

@@ -3,19 +3,18 @@ package com.gxwebsoft.shop.controller;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.shop.service.ShopDealerOrderService;
import com.gxwebsoft.shop.entity.ShopDealerOrder;
import com.gxwebsoft.shop.param.ShopDealerOrderParam;
import com.gxwebsoft.shop.param.ShopDealerOrderImportParam;
import com.gxwebsoft.common.core.annotation.OperationLog;
import com.gxwebsoft.common.core.utils.JSONUtil;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.common.core.web.BatchParam;
import com.gxwebsoft.common.core.annotation.OperationLog;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.shop.entity.ShopDealerOrder;
import com.gxwebsoft.shop.param.ShopDealerOrderImportParam;
import com.gxwebsoft.shop.param.ShopDealerOrderParam;
import com.gxwebsoft.shop.service.ShopDealerOrderService;
import com.gxwebsoft.shop.task.OrderSettlementTask;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.security.access.prepost.PreAuthorize;
@@ -24,6 +23,7 @@ import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
@@ -40,6 +40,9 @@ public class ShopDealerOrderController extends BaseController {
@Resource
private ShopDealerOrderService shopDealerOrderService;
@Resource
private OrderSettlementTask orderSettlementTask;
@PreAuthorize("hasAuthority('shop:shopDealerOrder:list')")
@Operation(summary = "分页查询分销商订单记录表")
@GetMapping("/page")
@@ -64,6 +67,13 @@ public class ShopDealerOrderController extends BaseController {
return success(shopDealerOrderService.getByIdRel(id));
}
@PreAuthorize("hasAuthority('shop:shopDealerOrder:list')")
@Operation(summary = "查询个人今日收益")
@GetMapping("/todayRevenue")
public ApiResult<BigDecimal> todayRevenue() {
return success(shopDealerOrderService.todayRevenue());
}
@PreAuthorize("hasAuthority('shop:shopDealerOrder:save')")
@OperationLog
@Operation(summary = "添加分销商订单记录表")
@@ -173,7 +183,7 @@ public class ShopDealerOrderController extends BaseController {
@PreAuthorize("hasAuthority('shop:shopDealerOrder:update')")
@OperationLog
@Operation(summary = "手动触发单条订单佣金解冻")
@PostMapping("/unfreeze")
// @PostMapping("/unfreeze")
public ApiResult<String> manualUnfreeze(@RequestBody Map<String, Object> body) {
String orderNo = (String) body.get("orderNo");
if (orderNo == null || orderNo.isBlank()) {
@@ -187,4 +197,11 @@ public class ShopDealerOrderController extends BaseController {
return fail(e.getMessage(),null);
}
}
@Operation(summary = "店、服务商结算任务每天一点每10分钟执行一次结算任务")
@PutMapping("/teamSettlement")
public ApiResult<?> teamSettlement() {
orderSettlementTask.teamSettlement();
return success("success");
}
}

View File

@@ -11,6 +11,7 @@ import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.common.core.web.BatchParam;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.shop.dto.ShopDealerRefundDto;
import com.gxwebsoft.shop.dto.ShopDealerUserReduceDto;
import com.gxwebsoft.shop.entity.ShopDealerUser;
import com.gxwebsoft.shop.param.ShopDealerUserImportParam;
@@ -78,11 +79,18 @@ public class ShopDealerUserController extends BaseController {
return fail("添加失败");
}
@PreAuthorize("hasAuthority('shop:shopDealerUser:update')")
@Operation(summary = "开启/关闭分销商用户核销权限")
@PutMapping("/verifyEnable")
public ApiResult<Boolean> verifyEnable(@RequestParam("id") Integer id) {
return success(shopDealerUserService.verifyEnable(id));
}
@PreAuthorize("hasAuthority('shop:shopDealerUser:update')")
@Operation(summary = "修改分销商用户记录表")
@PutMapping()
public ApiResult<?> update(@RequestBody ShopDealerUser shopDealerUser) {
if (shopDealerUserService.updateById(shopDealerUser)) {
if (shopDealerUserService.updateInfo(shopDealerUser)) {
return success("修改成功");
}
return fail("修改失败");
@@ -185,4 +193,11 @@ public class ShopDealerUserController extends BaseController {
return success(shopDealerUserService.reduceBalance(reduceDto));
}
@Operation(summary = "分销退单")
@PostMapping("/refundOrder")
@Deprecated
public ApiResult<?> refundOrder(@RequestBody ShopDealerRefundDto refundDto) {
return success(shopDealerUserService.refundOrder(refundDto));
}
}

View File

@@ -256,7 +256,8 @@ public class ShopDealerWithdrawController extends BaseController {
}
// 使用提现记录ID构造单号保持幂等微信要求 5-32 且仅字母/数字
String outBillNo = String.format("WD%03d", db.getId());
String outBillNo = db.getOrderNo();
String remark = "分销商提现";
String userName = db.getRealName();

View File

@@ -43,9 +43,9 @@ public class ShopFlashSaleActivityController extends BaseController {
@Operation(summary = "个人获取秒杀活动数据")
@GetMapping("/getMyActive")
public ApiResult<List<ShopFlashSaleActivityVO>> getMyActive(@RequestParam("tenantId") Integer tenantId) {
public ApiResult<List<ShopFlashSaleActivityVO>> getMyActive(@RequestParam("tenantId") Integer tenantId, Integer popFlag) {
// 使用关联查询
return success(shopFlashSaleActivityService.getMyActive(tenantId));
return success(shopFlashSaleActivityService.getMyActive(tenantId, popFlag));
}
// @PreAuthorize("hasAuthority('shop:shopFlashSaleActivity:list')")
@@ -59,9 +59,9 @@ public class ShopFlashSaleActivityController extends BaseController {
// @PreAuthorize("hasAuthority('shop:shopFlashSaleActivity:list')")
@Operation(summary = "根据id查询秒杀活动")
@GetMapping("/{id}")
public ApiResult<ShopFlashSaleActivity> get(@PathVariable("id") Integer id) {
public ApiResult<ShopFlashSaleActivityVO> get(@PathVariable("id") Integer id) {
// 使用关联查询
return success(shopFlashSaleActivityService.getByIdRel(id));
return success(shopFlashSaleActivityService.getInfoById(id));
}
// @PreAuthorize("hasAuthority('shop:shopFlashSaleActivity:save')")

View File

@@ -6,7 +6,6 @@ import com.gxwebsoft.shop.entity.ShopGoodsCategory;
import com.gxwebsoft.shop.param.ShopGoodsCategoryParam;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.core.web.PageParam;
import com.gxwebsoft.common.core.web.BatchParam;
import com.gxwebsoft.common.core.annotation.OperationLog;
import com.gxwebsoft.common.system.entity.User;

View File

@@ -0,0 +1,51 @@
package com.gxwebsoft.shop.controller;
import com.gxwebsoft.common.core.annotation.OperationLog;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.shop.dto.ShopGoodsProfitUpdateDto;
import com.gxwebsoft.shop.service.ShopGoodsProfitService;
import com.gxwebsoft.shop.vo.ShopGoodsProfitVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.ibatis.annotations.Param;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
/**
* 商品分润设定控制器
*
* @author xm
* @since 2026-05-20 14:33:00
*/
@Tag(name = "商品分润设定管理")
@RestController
@RequestMapping("/api/shop/shop-goods-profit")
public class ShopGoodsProfitController extends BaseController {
@Resource
private ShopGoodsProfitService shopGoodsProfitService;
// @PreAuthorize("hasAuthority('shop:shopGoodsProfit:list')")
@Operation(summary = "通过商品、类型查询分润信息")
@GetMapping("/getByGoodsId")
@Parameters({
@Parameter(name = "goodsId", description = "商品ID", required = true, example = "10086"),
@Parameter(name = "type", description = "类型 1-分红 2-其他", required = true, example = "1")
})
public ApiResult<List<ShopGoodsProfitVO>> getByGoodsId(@RequestParam("goodsId") Integer goodsId, @Param("type") Integer type) {
return success(shopGoodsProfitService.getByGoodsId(goodsId, type));
}
// @PreAuthorize("hasAuthority('shop:shopGoodsProfit:update')")
@OperationLog
@Operation(summary = "根据商品ID修改商品分润设定")
@PutMapping("/updateByGoodsId")
public ApiResult<Boolean> update(@RequestBody ShopGoodsProfitUpdateDto updateDto) {
return success(shopGoodsProfitService.updateByGoodsId(updateDto));
}
}

View File

@@ -17,8 +17,10 @@ import com.gxwebsoft.common.core.web.BatchParam;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.system.entity.Payment;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.common.system.redis.OrderNoUtils;
import com.gxwebsoft.glt.service.GltTicketIssueService;
import com.gxwebsoft.glt.service.GltTicketRevokeService;
import com.gxwebsoft.glt.task.DealerOrderSettlement10584Task;
import com.gxwebsoft.payment.dto.PaymentResponse;
import com.gxwebsoft.payment.enums.PaymentType;
import com.gxwebsoft.payment.service.PaymentService;
@@ -30,6 +32,7 @@ import com.gxwebsoft.shop.param.ShopOrderParam;
import com.gxwebsoft.shop.service.*;
import com.gxwebsoft.shop.service.impl.KuaiDi100Impl;
import com.gxwebsoft.shop.task.OrderAutoCancelTask;
import com.gxwebsoft.shop.vo.ShopOrderMyVerifyVO;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
@@ -40,6 +43,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springdoc.api.annotations.ParameterObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
@@ -111,6 +115,10 @@ public class ShopOrderController extends BaseController {
private ShopDealerCommissionRollbackService shopDealerCommissionRollbackService;
@Resource
private GltTicketIssueService gltTicketIssueService;
@Resource
private OrderNoUtils orderNoUtils;
@Resource
private DealerOrderSettlement10584Task dealerOrderSettlement;
@Operation(summary = "分页查询订单")
@GetMapping("/page")
@@ -134,6 +142,13 @@ public class ShopOrderController extends BaseController {
return success(shopOrderService.getByIdRel(id));
}
// @PreAuthorize("hasAuthority('shop:shopOrder:list')")
@Operation(summary = "我已核销订单")
@GetMapping("/myVerifyOrder")
public ApiResult<ShopOrderMyVerifyVO> myVerifyOrder(@ParameterObject ShopOrderMyVerifyDto myVerifyDto) {
return success(shopOrderService.myVerifyOrder(myVerifyDto));
}
@Operation(summary = "添加订单【单商品添加】")
@PostMapping()
public ApiResult<?> save(@RequestBody OrderCreateRequest request) {
@@ -441,14 +456,15 @@ public class ShopOrderController extends BaseController {
}
@PreAuthorize("hasAuthority('shop:shopOrder:refund')")
@Operation(summary = "订单退款操作(申请退款/同意退款)", description = "orderStatus=4 申请退款orderStatus=6 同意退款并发起原路退款")
@Operation(summary = "订单退款操作(申请退款/同意退款/拒绝退款)", description = "orderStatus=4 申请退款orderStatus=5 拒绝退款orderStatus=6 同意退款并发起原路退款orderStatus=7 客户端申请退款")
@PutMapping("/refund")
public ApiResult<?> refund(@RequestBody ShopOrder req) {
if (req == null || req.getOrderId() == null || req.getOrderStatus() == null) {
return fail("orderId 和 orderStatus 不能为空");
}
if (!Objects.equals(req.getOrderStatus(), 4) && !Objects.equals(req.getOrderStatus(), 6) && !Objects.equals(req.getOrderStatus(), 7)) {
return fail("orderStatus 仅支持 4(申请退款) 或 6(同意退款) 或 7(客户端申请退款)");
if (!Objects.equals(req.getOrderStatus(), 4) && !Objects.equals(req.getOrderStatus(), 5)
&& !Objects.equals(req.getOrderStatus(), 6) && !Objects.equals(req.getOrderStatus(), 7)) {
return fail("orderStatus 仅支持 4(申请退款)、5(拒绝退款)、6(同意退款)、7(客户端申请退款)");
}
ShopOrder current = shopOrderService.getById(req.getOrderId());
@@ -493,12 +509,12 @@ public class ShopOrderController extends BaseController {
if (!Boolean.TRUE.equals(current.getPayStatus())) {
return fail("订单未支付,无法退款");
}
if (StrUtil.isNotBlank(current.getRefundOrder())) {
logger.warn("订单已经退款过,订单号: {}, 退款单号: {}", current.getOrderNo(), current.getRefundOrder());
if (StrUtil.isNotBlank(current.getRefundOrder()) || current.getOrderStatus() == 6) {
logger.warn("订单已经退款过,订单号: {}, 退款单号: {}", current.getOrderNo(), current.getRefundOrder() != null ? current.getRefundOrder() : "");
return fail("订单已退款,请勿重复操作");
}
String refundNo = "RF" + IdUtil.getSnowflakeNextId();
String refundNo = orderNoUtils.generate("RF");
BigDecimal refundAmount = req.getRefundMoney();
if (refundAmount == null || refundAmount.compareTo(BigDecimal.ZERO) <= 0) {
@@ -572,7 +588,7 @@ public class ShopOrderController extends BaseController {
rollbackOrder.setOrderNo(current.getOrderNo());
rollbackOrder.setPayPrice(current.getPayPrice());
rollbackOrder.setTotalPrice(current.getTotalPrice());
boolean rollbackOk = shopDealerCommissionRollbackService.rollbackOnOrderRefund(rollbackOrder, refundAmount);
boolean rollbackOk = shopDealerCommissionRollbackService.rollbackOnOrderRefundV2(rollbackOrder, refundAmount);
if (!rollbackOk) {
logger.error("退款成功但回退分红/分润/佣金失败 - tenantId={}, orderId={}, orderNo={}",
tenantId, current.getOrderId(), current.getOrderNo());
@@ -801,7 +817,7 @@ public class ShopOrderController extends BaseController {
if (config == null) {
try {
NotificationConfig newConfig;
if (active.equals("dev")) {
if (active.equals("local")) {
// 开发环境 - 构建包含租户号的私钥路径
String tenantCertPath = "dev/wechat/" + tenantId;
String privateKeyPath = tenantCertPath + "/" + certConfig.getWechatPay().getDev().getPrivateKeyFile();
@@ -971,6 +987,27 @@ public class ShopOrderController extends BaseController {
return success(Boolean.TRUE);
}
@Operation(summary = "支付成功发送水票", description = "支付成功发送水票")
@PutMapping("/suerTicketRelease")
public ApiResult<Boolean> suerTicketRelease(@RequestBody PaySuccessTaskDto taskDto){
gltTicketIssueService.suerTicketRelease(taskDto.getOrderNo(), taskDto.getTenantId());
return success(Boolean.TRUE);
}
@Operation(summary = "支付成功结算", description = "支付成功结算")
@PutMapping("/orderSettlement")
public ApiResult<Boolean> orderSettlement(@RequestBody PaySuccessTaskDto taskDto){
dealerOrderSettlement.orderSettlement(taskDto.getOrderNo());
return success(Boolean.TRUE);
}
@Operation(summary = "分红结算", description = "分红结算")
@PutMapping("/partnerProfit")
public ApiResult<Boolean> partnerProfit(@RequestBody PaySuccessTaskDto taskDto){
dealerOrderSettlement.partnerProfit(taskDto.getOrderNo(), taskDto.getTenantId());
return success(Boolean.TRUE);
}
@Operation(summary = "更新订单支付状态", description = "用户支付成功后主动同步订单状态")
@PutMapping("/payment-status")
public ApiResult<?> updateOrderPaymentStatus(@RequestBody UpdatePaymentStatusRequest request) {

View File

@@ -31,7 +31,7 @@
@Resource
private ShopUserAddressService shopUserAddressService;
@PreAuthorize("hasAuthority('shop:shopUserAddress:list')")
// @PreAuthorize("hasAuthority('shop:shopUserAddress:list')")
@Operation(summary = "分页查询收货地址")
@GetMapping("/page")
public ApiResult<PageResult<ShopUserAddress>> page(ShopUserAddressParam param) {
@@ -39,7 +39,7 @@
return success(shopUserAddressService.pageRel(param));
}
@PreAuthorize("hasAuthority('shop:shopUserAddress:list')")
// @PreAuthorize("hasAuthority('shop:shopUserAddress:list')")
@Operation(summary = "查询全部收货地址")
@GetMapping()
public ApiResult<List<ShopUserAddress>> list(ShopUserAddressParam param) {
@@ -48,7 +48,7 @@
return success(shopUserAddressService.listRel(param));
}
@PreAuthorize("hasAuthority('shop:shopUserAddress:list')")
// @PreAuthorize("hasAuthority('shop:shopUserAddress:list')")
@Operation(summary = "根据id查询收货地址")
@GetMapping("/{id}")
public ApiResult<ShopUserAddress> get(@PathVariable("id") Integer id) {
@@ -56,7 +56,7 @@
return success(shopUserAddressService.getByIdRel(id));
}
@PreAuthorize("hasAuthority('shop:shopUserAddress:save')")
// @PreAuthorize("hasAuthority('shop:shopUserAddress:save')")
@OperationLog
@Operation(summary = "添加收货地址")
@PostMapping()
@@ -75,7 +75,7 @@
return fail("添加失败");
}
@PreAuthorize("hasAuthority('shop:shopUserAddress:update')")
// @PreAuthorize("hasAuthority('shop:shopUserAddress:update')")
@OperationLog
@Operation(summary = "修改收货地址")
@PutMapping()
@@ -83,7 +83,7 @@
return success(shopUserAddressService.updateInfo(shopUserAddress));
}
@PreAuthorize("hasAuthority('shop:shopUserAddress:remove')")
// @PreAuthorize("hasAuthority('shop:shopUserAddress:remove')")
@OperationLog
@Operation(summary = "删除收货地址")
@DeleteMapping("/{id}")

View File

@@ -0,0 +1,103 @@
package com.gxwebsoft.shop.controller;
import com.gxwebsoft.common.core.annotation.OperationLog;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.shop.entity.ShopVerifyUser;
import com.gxwebsoft.shop.param.ShopVerifyUserParam;
import com.gxwebsoft.shop.service.ShopVerifyUserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
/**
* 订单核销人管理控制器
*
* @author xm
* @since 2026-05-25 17:13:01
*/
@Tag(name = "订单核销人管理管理")
@RestController
@RequestMapping("/api/shop/shop-verify-user")
public class ShopVerifyUserController extends BaseController {
@Resource
private ShopVerifyUserService shopVerifyUserService;
// @PreAuthorize("hasAuthority('shop:shopVerifyUser:list')")
@Operation(summary = "分页查询订单核销人管理")
@GetMapping("/page")
public ApiResult<PageResult<ShopVerifyUser>> page(ShopVerifyUserParam param) {
// 使用关联查询
return success(shopVerifyUserService.pageRel(param));
}
// @PreAuthorize("hasAuthority('shop:shopVerifyUser:list')")
@Operation(summary = "查询全部订单核销人管理")
@GetMapping()
public ApiResult<List<ShopVerifyUser>> list(ShopVerifyUserParam param) {
// 使用关联查询
return success(shopVerifyUserService.listRel(param));
}
// @PreAuthorize("hasAuthority('shop:shopVerifyUser:list')")
@Operation(summary = "根据id查询订单核销人管理")
@GetMapping("/{id}")
public ApiResult<ShopVerifyUser> get(@PathVariable("id") Integer id) {
// 使用关联查询
return success(shopVerifyUserService.getByIdRel(id));
}
// @PreAuthorize("hasAuthority('shop:shopVerifyUser:list')")
@Operation(summary = "根据用户ID查询订单核销人管理")
@GetMapping("/getByUserId")
public ApiResult<ShopVerifyUser> getByUserId(@RequestParam("userId") Integer userId) {
return success(shopVerifyUserService.getInfo(userId));
}
// @PreAuthorize("hasAuthority('shop:shopVerifyUser:save')")
@OperationLog
@Operation(summary = "添加订单核销人管理")
@PostMapping()
public ApiResult<Boolean> save(@RequestBody ShopVerifyUser shopVerifyUser) {
return success(shopVerifyUserService.saveInfo(shopVerifyUser));
}
// @PreAuthorize("hasAuthority('shop:shopVerifyUser:update')")
@Operation(summary = "修改订单核销人管理")
@PutMapping()
public ApiResult<?> update(@RequestBody ShopVerifyUser shopVerifyUser) {
if (shopVerifyUserService.updateById(shopVerifyUser)) {
return success("修改成功");
}
return fail("修改失败");
}
@Operation(summary = "修改订单核销人开启状态")
@PutMapping("/updateStatus")
public ApiResult<Boolean> updateStatus(@RequestParam("id") Integer id) {
return success(shopVerifyUserService.updateStatus(id));
}
@Operation(summary = "修改订单核销人核销权限")
@PutMapping("/updateVerifyFlag")
public ApiResult<Boolean> updateVerifyFlag(@RequestParam("id") Integer id) {
return success(shopVerifyUserService.updateVerifyFlag(id));
}
// @PreAuthorize("hasAuthority('shop:shopVerifyUser:remove')")
@OperationLog
@Operation(summary = "删除订单核销人管理")
@DeleteMapping("/{id}")
public ApiResult<?> remove(@PathVariable("id") Integer id) {
if (shopVerifyUserService.removeById(id)) {
return success("删除成功");
}
return fail("删除失败");
}
}

View File

@@ -6,6 +6,7 @@ import lombok.Data;
import javax.validation.Valid;
import javax.validation.constraints.*;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
/**
@@ -91,6 +92,12 @@ public class OrderCreateRequest {
@Schema(description = "发货店铺")
private String expressMerchantName;
@Schema(description = "配送方式 0-电梯 1-步梯")
private Integer deliveryMethod;
@Schema(description = "楼层")
private Integer deliveryFloor;
@Schema(description = "订单总额")
@NotNull(message = "订单总额不能为空")
@DecimalMin(value = "0.01", message = "订单总额必须大于0")
@@ -153,6 +160,9 @@ public class OrderCreateRequest {
@Schema(description = "秒杀活动ID")
private Integer activityId;
@Schema(description = "配送时间")
private LocalDateTime sendTime;
@Schema(description = "订单商品列表")
@Valid
@NotEmpty(message = "订单商品列表不能为空")
@@ -167,14 +177,14 @@ public class OrderCreateRequest {
@Schema(description = "秒杀活动ID")
private Integer activityId;
@Schema(description = "商品ID", required = true)
@Schema(description = "商品ID")
@NotNull(message = "商品ID不能为空")
private Integer goodsId;
@Schema(description = "商品SKU ID")
private Integer skuId;
@Schema(description = "商品数量", required = true)
@Schema(description = "商品数量")
@NotNull(message = "商品数量不能为空")
@Min(value = 1, message = "商品数量必须大于0")
private Integer quantity;

View File

@@ -0,0 +1,28 @@
package com.gxwebsoft.shop.dto;
import com.gxwebsoft.common.core.web.BaseParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
/**
* 查询个人流水
*
*/
@Data
@Schema(name = "ShopDealerCapitalWaterDto", description = "查询个人流水")
public class ShopDealerCapitalWaterDto extends BaseParam {
@Schema(description = "用户ID")
@NotEmpty(message = "用户ID不能为空")
private Integer userId;
@Schema(description = "起始时间", example = "2026-05-01")
private String dateStart;
@Schema(description = "结束时间", example = "2026-05-31")
private String dateEnd;
}

View File

@@ -0,0 +1,28 @@
package com.gxwebsoft.shop.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
/**
* 分销订单退款
* @author xm
* @since 2026-05-13
*/
@Data
@Schema(name = "ShopDealerUserReduceDto", description = "分销订单退款")
public class ShopDealerRefundDto {
@Schema(description = "订单号")
@NotNull(message = "变订单号不可为空!")
private String orderNo;
@Schema(description = "租户ID")
private Integer tenantId;
@Schema(description = "退款金额")
private BigDecimal refundAmount;
}

View File

@@ -0,0 +1,37 @@
package com.gxwebsoft.shop.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
/**
* 分销订单结算
* @author xm
* @since 2026-05-13
*/
@Data
@Schema(name = "ShopDealerSettlementDto", description = "分销订单结算")
public class ShopDealerSettlementDto {
@Schema(description = "变动类型 1-操作冻结账户余额 2-操作提现账户余额【直接结算】 3-解冻 4-退款")
private Integer type;
@Schema(description = "资金流动类型 (10分销收入 11团队管理津贴收入 12分红收入 13现场推广收入 20提现支出 30转账支出 40转账收入 50佣金解冻 60配送奖励 70佣金退回【退单】)")
private Integer flowType;
@Schema(description = "订单号")
private String orderNo;
@Schema(description = "描述")
private String comments;
@Schema(description = "分销来源")
private Integer toUserId;
@Schema(description = "商城ID")
private Integer tenantId;
@Schema(description = "明细列表")
private List<ShopDealerSettlementItemDto> itemList;
}

View File

@@ -0,0 +1,26 @@
package com.gxwebsoft.shop.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
/**
* 分销订单退款
* @author xm
* @since 2026-05-13
*/
@Data
@Schema(name = "ShopDealerSettlementItemDto", description = "分销订单退款")
public class ShopDealerSettlementItemDto {
@Schema(description = "订单号")
private String no;
@Schema(description = "分销商用户ID")
private Integer userId;
@Schema(description = "变更金额")
private BigDecimal money;
}

View File

@@ -0,0 +1,29 @@
package com.gxwebsoft.shop.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import java.util.List;
/**
* 商品分润设定更新
*
* @author xm
* @since 2026-05-20 14:33:00
*/
@Data
public class ShopGoodsProfitUpdateDto {
@Schema(description = "商品ID")
@NotEmpty(message = "商品ID不能为空")
private Integer goodsId;
@Schema(description = "分润类型 1-股东分红 2-其他")
@NotEmpty(message = "分润类型不能为空!")
private Integer type;
@Schema(description = "变更明细")
private List<ShopGoodsProfitUpdateItemDto> itemList;
}

View File

@@ -0,0 +1,26 @@
package com.gxwebsoft.shop.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
/**
* 商品分润设定更新
*
* @author xm
* @since 2026-05-20 14:33:00
*/
@Data
public class ShopGoodsProfitUpdateItemDto {
@Schema(description = "用户ID")
private Integer userId;
@Schema(description = "分佣比例 百分比")
private BigDecimal profit;
@Schema(description = "开启状态 0-未开启 1-开启")
private Integer status;
}

View File

@@ -0,0 +1,27 @@
package com.gxwebsoft.shop.dto;
import com.gxwebsoft.common.core.web.BaseParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 查询个人核销记录
*
*/
@Data
@Schema(name = "ShopOrderMyVerifyDto", description = "查询个人核销记录")
public class ShopOrderMyVerifyDto extends BaseParam {
@Schema(description = "用户ID")
private Integer userId;
@Schema(description = "订单号")
private String orderNo;
@Schema(description = "开始时间【核销时间】", example = "2026-05-20")
private String dateStart;
@Schema(description = "结束时间【核销时间】", example = "2026-05-25")
private String dateEnd;
}

View File

@@ -26,7 +26,7 @@ public class UserOrderStats implements Serializable {
@Schema(description = "待核销statusFilter=2")
private Long waitVerify;
@Schema(description = "待收货statusFilter=3")
@Schema(description = "待收货/使用statusFilter=3")
private Long waitReceive;
@Schema(description = "待评价statusFilter=4")

View File

@@ -38,6 +38,9 @@ public class ShopActiveImage implements Serializable {
@Schema(description = "图片地址,多个以‘,’隔开")
private String imgUrl;
@Schema(description = "分享底图")
private String shareImg;
@Schema(description = "图片地址集合")
@TableField(exist = false)
private List<String> imgUrlList;
@@ -48,6 +51,13 @@ public class ShopActiveImage implements Serializable {
@Schema(description = "排序")
private Integer sortNumber;
@Schema(description = "跳转商品ID")
private Integer goodsId;
@Schema(description = "跳转商品名称")
@TableField(exist = false)
private String goodsName;
@Schema(description = "租户ID")
@NotNull(message = "租户ID不能为空")
private Integer tenantId;

View File

@@ -35,7 +35,7 @@ public class ShopDealerCapital implements Serializable {
@Schema(description = "分销商用户ID")
private Integer userId;
@Schema(description = "变动类型 1-操作冻结账户余额 2-操作提现账户余额【直接结算】 3-解冻")
@Schema(description = "变动类型 1-操作冻结账户余额 2-操作提现账户余额【直接结算】 3-解冻 4-退款")
private Integer type;
@Schema(description = "分销商昵称")
@@ -49,7 +49,7 @@ public class ShopDealerCapital implements Serializable {
@TableField(exist = false)
private Integer orderStatus;
@Schema(description = "资金流动类型 (10佣金收入 20提现支出 30转账支出 40转账收入 50佣金解冻 60配送奖励 70佣金退回【退单】)")
@Schema(description = "资金流动类型 (10分销收入 11团队管理津贴收入 12分红收入 13现场推广收入 14现场推广分佣 20提现支出 30转账支出 40转账收入 50佣金解冻 60配送奖励 61配送提成 62配送步梯费 70佣金退回【退单】)")
private Integer flowType;
@Schema(description = "变更金额")
@@ -77,6 +77,9 @@ public class ShopDealerCapital implements Serializable {
@Schema(description = "结算月份")
private String month;
@Schema(description = "结算标识 0-未结算 1-已结算")
private Integer paymentFlag;
@Schema(description = "商城ID")
private Integer tenantId;

View File

@@ -1,11 +1,10 @@
package com.gxwebsoft.shop.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.*;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.io.Serializable;
import io.swagger.v3.oas.annotations.media.Schema;
@@ -21,6 +20,7 @@ import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
@Schema(name = "ShopDealerReferee对象", description = "分销商推荐关系表")
@TableName("shop_dealer_referee")
public class ShopDealerReferee implements Serializable {
private static final long serialVersionUID = 1L;
@@ -69,6 +69,10 @@ public class ShopDealerReferee implements Serializable {
@Schema(description = "推荐关系层级(弃用)")
private Integer level;
@Schema(description = "是否删除 0-未删 1-已删")
@TableLogic
private Integer deleted;
@Schema(description = "来源(如 goods_share)")
// NOTE: 表 shop_dealer_referee 若未新增该字段,需要 exist=false避免 MyBatis-Plus 自动生成SQL时报 Unknown column。
@TableField(exist = false)

View File

@@ -1,12 +1,11 @@
package com.gxwebsoft.shop.entity;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.*;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.io.Serializable;
import io.swagger.v3.oas.annotations.media.Schema;
@@ -30,7 +29,7 @@ public class ShopDealerUser implements Serializable {
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
@Schema(description = "0经销商,1企业也,2集团)")
@Schema(description = "0-分销员 1-门店 2-服务商 3-合伙人")
private Integer type;
@Schema(description = "自增ID")
@@ -105,6 +104,9 @@ public class ShopDealerUser implements Serializable {
@Schema(description = "排序号")
private Integer sortNumber;
@Schema(description = "核销权限是否开启 0-未开启 1-已开启")
private Boolean verifyFlag;
@Schema(description = "是否删除")
private Integer isDelete;
@@ -115,6 +117,9 @@ public class ShopDealerUser implements Serializable {
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
@Schema(description = "更新人")
private Integer updater;
@Schema(description = "修改时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime updateTime;
@@ -122,4 +127,8 @@ public class ShopDealerUser implements Serializable {
@Schema(description = "分销商等级0-普通用户 1-超级管理员 2-合伙人(总店) 3-合伙人(分店)")
private Integer dealerLevel;
@Schema(description = "删除 0-未删 1-已删")
@TableLogic
private Integer deleted;
}

View File

@@ -69,7 +69,7 @@ public class ShopFlashSaleActivity implements Serializable {
@Schema(description = "库存")
private Integer stock;
@Schema(description = "展示类型0普通用户1新用户")
@Schema(description = "展示类型0普通用户1新用户 2老用户")
private Integer displayType;
@Schema(description = "备注")
@@ -78,6 +78,9 @@ public class ShopFlashSaleActivity implements Serializable {
@Schema(description = "排序")
private Integer sortNumber;
@Schema(description = "是否弹窗 0-否 1-是")
private Integer popFlag;
@Schema(description = "租户id")
private Integer tenantId;

View File

@@ -1,15 +1,16 @@
package com.gxwebsoft.shop.entity;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.*;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonAlias;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.io.Serializable;
import java.util.List;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
@@ -110,6 +111,12 @@ public class ShopGoods implements Serializable {
@Schema(description = "推广核验佣金比率")
private BigDecimal verifyRate;
@Schema(description = "推广核验上级/指定人")
private Integer verifyParentUserId;
@Schema(description = "推广核验上级佣金比率/指定分佣")
private BigDecimal verifyParentRate;
@Schema(description = "库存计算方式(10下单减库存 20付款减库存)")
@JsonAlias({"cdeductStockType"})
private Integer deductStockType;
@@ -174,24 +181,47 @@ public class ShopGoods implements Serializable {
@Schema(description = "用户ID")
private Integer userId;
@Schema(description = "租户id")
private Integer tenantId;
@Schema(description = "配送方式:1-自配送 2-自提 4-发快递 多属性用','隔开")
@Schema(description = "配送方式:1-自配送 2-自提 4-发快递 5-水票 多属性用','隔开")
private String deliveryType;
@Schema(description = "配送方式:1-自配送 2-自提 4-发快递 5-水票 多属性用','隔开")
@TableField(exist = false)
private List<Integer> deliveryTypeList;
@Schema(description = "水票标识 0-否 1-是")
private Integer waterTicketFlag;
@Schema(description = "水票ID")
private Integer waterTickerId;
@Schema(description = "0-按每桶楼层计算 1-固定金额")
private Integer deliveryFeeType;
@Schema(description = "配送楼层步梯费(元)")
private BigDecimal deliveryFee;
@Schema(description = "分享图")
private String shareImg;
@Schema(description = "租户id")
private Integer tenantId;
@Schema(description = "创建人")
private Integer creator;
@Schema(description = "创建时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
@Schema(description = "修改人")
private Integer updater;
@Schema(description = "修改时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime updateTime;
@Schema(description = "是否删除 0-未删 1-已删")
@TableLogic
private Integer deleted;
}

View File

@@ -2,15 +2,16 @@ package com.gxwebsoft.shop.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.time.LocalDateTime;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.baomidou.mybatisplus.annotation.TableLogic;
import java.io.Serializable;
import io.swagger.v3.oas.annotations.media.Schema;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* 商品分类
*
@@ -20,6 +21,7 @@ import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
@Schema(name = "ShopGoodsCategory对象", description = "商品分类")
@TableName("shop_goods_category")
public class ShopGoodsCategory implements Serializable {
private static final long serialVersionUID = 1L;

View File

@@ -0,0 +1,65 @@
package com.gxwebsoft.shop.entity;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.IdType;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import java.io.Serializable;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 商品分润设定
*
* @author xm
* @since 2026-05-20 14:33:00
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Schema(name = "ShopGoodsProfit对象", description = "商品分润设定")
@TableName("shop_goods_profit")
public class ShopGoodsProfit implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "主键ID")
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
@Schema(description = "类型 1-股东分红 2-其他")
private Integer type;
@Schema(description = "商品ID")
private Integer goodsId;
@Schema(description = "用户ID")
private Integer userId;
@Schema(description = "分佣比例 百分比")
private BigDecimal profit;
@Schema(description = "开启状态 0-未开启 1-开启")
private Integer status;
@Schema(description = "租户ID")
private Integer tenantId;
@Schema(description = "创建人")
private Integer creator;
@Schema(description = "创建时间")
private LocalDateTime createTime;
@Schema(description = "更新人")
private Integer updater;
@Schema(description = "更新人")
private LocalDateTime updateTime;
@Schema(description = "删除 0-未删 1-已删")
@TableLogic
private Integer deleted;
}

View File

@@ -33,7 +33,7 @@ public class ShopOrder implements Serializable {
@TableId(value = "order_id", type = IdType.AUTO)
private Integer orderId;
@Schema(description = "订单类型 1-及时自配送 2-自提 3-预约自配送 4-发快递")
@Schema(description = "订单类型 1-及时自配送 2-自提 3-预约自配送 4-发快递 5-水票 6-(配送:自配送/快递)")
private Integer orderType;
@Schema(description = "订单编号")
@@ -190,7 +190,7 @@ public class ShopOrder implements Serializable {
@Schema(description = "0未使用1已完成2已取消3取消中4退款申请中5退款被拒绝6退款成功7客户端申请退款")
private Integer orderStatus;
@Schema(description = "发货状态(10未发货 20已发货 30部分发货)")
@Schema(description = "发货状态(10未发货 20已发货 30部分发货 40已送达)")
private Integer deliveryStatus;
@Schema(description = "发货备注")
@@ -313,6 +313,10 @@ public class ShopOrder implements Serializable {
@Schema(description = "秒杀活动ID")
private Integer activityId;
@Schema(description = "秒杀活动ID")
@TableField(exist = false)
private String activityName;
@Schema(description = "水票订单标识 0-否 1-是")
private Integer waterTicketFlag;
@@ -331,9 +335,37 @@ public class ShopOrder implements Serializable {
@Schema(description = "核销人")
private Integer verifyUser;
@Schema(description = "核销人")
@TableField(exist = false)
private String verifyUserName;
@Schema(description = "推广核销佣金")
private BigDecimal verifyMoney;
@Schema(description = "推广核验上级/指定人")
private Integer verifyParentUser;
@Schema(description = "推广核验上级/指定人佣金")
private BigDecimal verifyParentMoney;
@Schema(description = "门店、服务商结算标识 0-未结算 1-已结算")
private Integer teamSettlementFlag;
@Schema(description = "分红结算标识 0-未结算 1-已结算")
private Integer dividendSettlementFlag;
@Schema(description = "配送方式 0-电梯 1-步梯")
private Integer deliveryMethod;
@Schema(description = "楼层")
private Integer deliveryFloor;
@Schema(description = "配送费(步梯配送特有)")
private BigDecimal deliveryFee;
@Schema(description = "配送时间")
private LocalDateTime sendTime;
@Schema(description = "修改时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime updateTime;

View File

@@ -54,6 +54,14 @@ public class ShopOrderGoods implements Serializable {
@Schema(description = "商品名称")
private String goodsName;
@Schema(description = "商品名称")
@TableField(exist = false)
private String activeNam;
@Schema(description = "核销码")
@TableField(exist = false)
private String verifyCode;
@Schema(description = "商品规格")
private String spec;

View File

@@ -32,6 +32,9 @@ public class ShopSurchargeConfig implements Serializable {
@Schema(description = "名称")
private String name;
@Schema(description = "商品ID")
private Integer goodsId;
@Schema(description = "价格(元)")
private BigDecimal price;

View File

@@ -0,0 +1,61 @@
package com.gxwebsoft.shop.entity;
import com.baomidou.mybatisplus.annotation.*;
import java.time.LocalDateTime;
import java.io.Serializable;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 订单核销人管理
*
* @author xm
* @since 2026-05-25 17:13:00
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Schema(name = "ShopVerifyUser对象", description = "订单核销人管理")
@TableName("shop_verify_user")
public class ShopVerifyUser implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "主键ID")
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
@Schema(description = "用户ID")
private Integer userId;
@Schema(description = "用户名称")
@TableField(exist = false)
private String userName;
@Schema(description = "核销权限是否开启 0-未开启 1-已开启")
private Integer verifyFlag;
@Schema(description = "是否开启 0-未开始 1-已开启")
private Integer status;
@Schema(description = "排序号")
private Integer sortNumber;
@Schema(description = "创建人")
private Integer creator;
@Schema(description = "创建时间")
private LocalDateTime createTime;
@Schema(description = "更新人")
private Integer updater;
@Schema(description = "更新时间")
private LocalDateTime updateTime;
@Schema(description = "是否删除 0-未删 1-已删")
@TableLogic
private Integer deleted;
}

View File

@@ -2,8 +2,11 @@ package com.gxwebsoft.shop.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gxwebsoft.shop.dto.ShopDealerCapitalWaterDto;
import com.gxwebsoft.shop.entity.ShopDealerCapital;
import com.gxwebsoft.shop.param.ShopDealerCapitalParam;
import com.gxwebsoft.shop.vo.ShopDealerCapitalWaterVO;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@@ -34,4 +37,12 @@ public interface ShopDealerCapitalMapper extends BaseMapper<ShopDealerCapital> {
*/
List<ShopDealerCapital> selectListRel(@Param("param") ShopDealerCapitalParam param);
/**
* 查询个人资金流水
* @param page
* @param entity
* @return
*/
IPage<ShopDealerCapitalWaterVO> getPageInfo(@Param("page") Page page, @Param("entity") ShopDealerCapitalWaterDto entity);
}

View File

@@ -4,6 +4,8 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.gxwebsoft.shop.entity.ShopDealerOrder;
import com.gxwebsoft.shop.param.ShopDealerOrderParam;
import com.gxwebsoft.shop.vo.ShopDealerOrderTaskVO;
import com.gxwebsoft.shop.vo.ShopDealerOrderTodayRevenueVO;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@@ -34,4 +36,18 @@ public interface ShopDealerOrderMapper extends BaseMapper<ShopDealerOrder> {
*/
List<ShopDealerOrder> selectListRel(@Param("param") ShopDealerOrderParam param);
/**
* 获取订单门店/分销商待结算数据
* @param tenantId 租户ID
* @return
*/
List<ShopDealerOrderTaskVO> getDealerOrderList(@Param("tenantId") Integer tenantId);
/**
* 获取用户当日分佣数据
* @param userId
* @return
*/
List<ShopDealerOrderTodayRevenueVO> getTodayRevenue(@Param("userId") Integer userId);
}

View File

@@ -0,0 +1,14 @@
package com.gxwebsoft.shop.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.gxwebsoft.shop.entity.ShopGoodsProfit;
/**
* 商品分润设定Mapper
*
* @author xm
* @since 2026-05-20 14:33:00
*/
public interface ShopGoodsProfitMapper extends BaseMapper<ShopGoodsProfit> {
}

View File

@@ -3,9 +3,13 @@ package com.gxwebsoft.shop.mapper;
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gxwebsoft.shop.dto.ShopOrderMyVerifyDto;
import com.gxwebsoft.shop.entity.ShopOrder;
import com.gxwebsoft.shop.param.ShopOrderParam;
import com.gxwebsoft.shop.vo.ShopOrderGoodsInfoVO;
import com.gxwebsoft.shop.vo.ShopOrderGoodsVO;
import com.gxwebsoft.shop.vo.ShopOrderMyVerifyItemVO;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
@@ -67,4 +71,20 @@ public interface ShopOrderMapper extends BaseMapper<ShopOrder> {
* @return
*/
List<ShopOrderGoodsVO> getOrderGoodsInfo(@Param("orderNo") String orderNo);
/**
* 查询我的核销订单数据
* @param page
* @param entity
* @return
*/
IPage<ShopOrderMyVerifyItemVO> getMyVerifyPageInfo(@Param("page") Page page, @Param("entity") ShopOrderMyVerifyDto entity);
/**
* 通过订单号查询订单商品名称
* @param orderNoList
* @return
*/
List<ShopOrderGoodsInfoVO> getOrderGoodsInfoByOrderNos(@Param("orderNoList") List<String> orderNoList);
}

View File

@@ -0,0 +1,37 @@
package com.gxwebsoft.shop.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.gxwebsoft.shop.entity.ShopVerifyUser;
import com.gxwebsoft.shop.param.ShopVerifyUserParam;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 订单核销人管理Mapper
*
* @author xm
* @since 2026-05-25 17:13:00
*/
public interface ShopVerifyUserMapper extends BaseMapper<ShopVerifyUser> {
/**
* 分页查询
*
* @param page 分页对象
* @param param 查询参数
* @return List<ShopVerifyUser>
*/
List<ShopVerifyUser> selectPageRel(@Param("page") IPage<ShopVerifyUser> page,
@Param("param") ShopVerifyUserParam param);
/**
* 查询全部
*
* @param param 查询参数
* @return List<User>
*/
List<ShopVerifyUser> selectListRel(@Param("param") ShopVerifyUserParam param);
}

View File

@@ -11,6 +11,7 @@
LEFT JOIN gxwebsoft_core.sys_user d ON a.to_user_id = d.user_id and d.deleted = 0
LEFT JOIN shop_order e ON a.order_no = e.order_no
<where>
a.deleted = 0
<if test="param.id != null">
AND a.id = #{param.id}
</if>
@@ -55,5 +56,23 @@
<select id="selectListRel" resultType="com.gxwebsoft.shop.entity.ShopDealerCapital">
<include refid="selectSql"></include>
</select>
<select id="getPageInfo" resultType="com.gxwebsoft.shop.vo.ShopDealerCapitalWaterVO">
SELECT
no,
order_no,
flow_type,
money,
freeze_money,
comments,
create_time
FROM
shop_dealer_capital
WHERE
user_id = #{entity.userId}
<if test="entity.dateStart != null and entity.dateEnd != null">
AND DATE(create_time) BETWEEN #{entity.dateStart} AND #{entity.dateEnd}
</if>
ORDER BY create_time DESC
</select>
</mapper>

View File

@@ -89,5 +89,46 @@
<select id="selectListRel" resultType="com.gxwebsoft.shop.entity.ShopDealerOrder">
<include refid="selectSql"></include>
</select>
<select id="getDealerOrderList" resultType="com.gxwebsoft.shop.vo.ShopDealerOrderTaskVO">
SELECT
a.order_id,
b.id as shopDealerOrderId,
b.order_no,
first_dividend_user,
b.first_dividend,
b.first_dividend_flag,
second_dividend_user,
b.second_dividend,
b.second_dividend_flag
FROM
shop_order a
LEFT JOIN shop_dealer_order b ON a.order_no = b.order_no
WHERE
DATE(a.create_time) >= '2026-05-14'
AND a.team_settlement_flag = 0
AND a.pay_status = 1
AND a.order_status = 1
AND a.deleted = 0
AND ((b.first_dividend > 0 AND first_dividend_flag = 0) OR (b.second_dividend > 0 AND second_dividend_flag = 0))
</select>
<select id="getTodayRevenue" resultType="com.gxwebsoft.shop.vo.ShopDealerOrderTodayRevenueVO">
SELECT
a.order_no,
b.order_status,
a.first_user_id,
a.first_money,
a.second_user_id,
a.second_money,
a.first_dividend_user,
a.first_dividend,
a.second_dividend_user,
a.second_dividend
FROM
shop_dealer_order a
LEFT JOIN shop_order b ON a.order_no = b.order_no
WHERE
DATE(a.create_time) = CURRENT_DATE
AND (a.first_user_id = #{userId} OR a.second_user_id = #{userId} OR a.first_dividend_user = #{userId} OR a.second_dividend_user = #{userId})
</select>
</mapper>

View File

@@ -17,6 +17,7 @@
INNER JOIN gxwebsoft_core.sys_user d ON a.dealer_id = d.user_id AND d.deleted = 0
INNER JOIN gxwebsoft_core.sys_user u ON a.user_id = u.user_id AND u.deleted = 0
<where>
a.deleted = 0
<if test="param.tenantId != null">
AND a.tenant_id = #{param.tenantId}
</if>
@@ -65,12 +66,11 @@
d.type simpleUserType
FROM
shop_dealer_referee a
LEFT JOIN shop_dealer_user b ON a.dealer_id = b.user_id
LEFT JOIN shop_dealer_referee c ON b.user_id = c.user_id
LEFT JOIN shop_dealer_user d ON d.user_id = c.dealer_id
LEFT JOIN shop_dealer_user b ON a.dealer_id = b.user_id AND b.deleted = 0
LEFT JOIN shop_dealer_referee c ON b.user_id = c.user_id AND c.deleted = 0
LEFT JOIN shop_dealer_user d ON c.dealer_id = d.user_id and d.deleted = 0
WHERE
b.is_delete = 0
and d.is_delete = 0
a.deleted = 0
AND a.user_id = #{userId}
</select>

View File

@@ -110,6 +110,9 @@
<if test="param.deleted != null">
AND a.deleted = #{param.deleted}
</if>
<if test="param.waterTicketFlag != null">
AND a.water_ticket_flag = #{param.waterTicketFlag}
</if>
<if test="param.deleted == null">
AND a.deleted = 0
</if>

View File

@@ -0,0 +1,5 @@
<?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.gxwebsoft.shop.mapper.ShopGoodsProfitMapper">
</mapper>

View File

@@ -241,15 +241,15 @@
</if>
<if test="param.statusFilter == 1">
<!-- 1待发货已付款但未发货 -->
AND a.pay_status = 1 AND a.delivery_status = 10 AND a.order_status = 0 AND a.order_type in(1, 3, 4)
AND a.pay_status = 1 AND a.delivery_status = 10 AND a.order_status = 0 AND a.order_type in(1, 3, 4, 5)
</if>
<if test="param.statusFilter == 2">
<!-- 2待核销已付款但订单状态为未使用 -->
AND a.pay_status = 1 AND a.order_status = 0 and order_type = 2
</if>
<if test="param.statusFilter == 3">
<!-- 3待收货已发货但订单状态不是已完成 -->
AND a.pay_status = 1 AND a.delivery_status = 20 AND a.order_status = 0
<!-- 3待收货/使用:已发货但订单状态不是已完成 -->
AND a.pay_status = 1 AND a.order_status = 0 AND (a.delivery_status = 20 or (a.order_type = 2 and a.delivery_status = 10))
</if>
<if test="param.statusFilter == 4">
<!-- 4待评价订单已完成但可能需要评价 -->
@@ -298,12 +298,12 @@
-- “全部”默认也会过滤已关闭(取消)订单statusFilter != 8 时会加 a.order_status != 2
COALESCE(SUM(CASE WHEN a.deleted = 0 AND a.order_status != 2 THEN 1 ELSE 0 END), 0) AS total,
COALESCE(SUM(CASE WHEN a.deleted = 0 AND a.pay_status = 0 AND a.order_status = 0 THEN 1 ELSE 0 END), 0) AS waitPay,
COALESCE(SUM(CASE WHEN a.deleted = 0 AND a.pay_status = 1 AND a.order_status = 0 AND a.order_type in(1, 3, 4) AND a.delivery_status = 10 THEN 1 ELSE 0 END), 0) AS waitDeliver,
COALESCE(SUM(CASE WHEN a.deleted = 0 AND a.pay_status = 1 AND a.order_status = 0 AND a.order_type in(1, 3, 4, 5) AND a.delivery_status = 10 THEN 1 ELSE 0 END), 0) AS waitDeliver,
COALESCE(SUM(CASE WHEN a.deleted = 0 AND a.pay_status = 1 AND a.order_status = 0 AND a.order_type = 2 THEN 1 ELSE 0 END), 0) AS waitVerify,
COALESCE(SUM(CASE WHEN a.deleted = 0 AND a.pay_status = 1 AND a.order_status = 0 AND a.delivery_status = 20 THEN 1 ELSE 0 END), 0) AS waitReceive,
COALESCE(SUM(CASE WHEN a.deleted = 0 AND a.pay_status = 1 AND a.order_status = 0 AND (a.delivery_status = 20 or (a.order_type = 2 and a.delivery_status = 10)) THEN 1 ELSE 0 END), 0) AS waitReceive,
COALESCE(SUM(CASE WHEN a.deleted = 0 AND a.pay_status = 1 AND a.order_status = 1 AND a.evaluate_status = 0 THEN 1 ELSE 0 END), 0) AS waitComment,
COALESCE(SUM(CASE WHEN a.deleted = 0 AND a.pay_status = 1 AND a.order_status = 1 THEN 1 ELSE 0 END), 0) AS completed,
COALESCE(SUM(CASE WHEN a.deleted = 0 AND a.pay_status = 1 AND a.order_status in(4, 5, 6, 7) THEN 1 ELSE 0 END), 0) AS refund,
-- COALESCE(SUM(CASE WHEN a.deleted = 0 AND a.pay_status = 1 AND a.order_status = 1 THEN 1 ELSE 0 END), 0) AS completed,
-- COALESCE(SUM(CASE WHEN a.deleted = 0 AND a.pay_status = 1 AND a.order_status in(4, 5, 6, 7) THEN 1 ELSE 0 END), 0) AS refund,
COALESCE(SUM(CASE WHEN a.deleted = 1 THEN 1 ELSE 0 END), 0) AS deleted,
COALESCE(SUM(CASE WHEN a.deleted = 0 AND a.order_status = 2 THEN 1 ELSE 0 END), 0) AS canceled
FROM shop_order a
@@ -342,7 +342,56 @@
AND c.is_open_commission = 1
AND a.order_no = #{orderNo}
</select>
<select id="getMyVerifyPageInfo" resultType="com.gxwebsoft.shop.vo.ShopOrderMyVerifyItemVO">
SELECT
a.order_id,
a.order_type,
a.order_no,
a.total_price,
a.pay_price,
a.total_num,
b.goods_name,
c.NAME as activeName,
a.pay_type,
a.pay_status,
a.order_status,
a.user_id,
a.verify_time,
a.verify_user,
a.verify_money,
a.create_time
FROM
shop_order a
LEFT JOIN shop_order_goods b ON a.order_id = b.order_id
LEFT JOIN shop_flash_sale_activity c ON a.activity_id = c.id
WHERE
a.verify_user = #{entity.userId}
AND a.deleted = 0
<if test="entity.orderNo != null and entity.order != ''">
AND a.order_no LIKE CONCAT('%', #{entity.orderNo}, '%')
</if>
<if test="entity.dateStart != null and entity.dateStart != '' and entity.dateEnd != null and entity.dateEnd !=''">
AND DATE(a.verify_time) BETWEEN #{entity.dateStart} AND #{entity.dateEnd}
</if>
ORDER BY a.create_time desc
</select>
<select id="getOrderGoodsInfoByOrderNos" resultType="com.gxwebsoft.shop.vo.ShopOrderGoodsInfoVO">
SELECT
a.order_no,
b.order_status,
c.goods_name
FROM
glt_ticket_order a
LEFT JOIN shop_order b ON a.order_no = b.order_no
LEFT JOIN shop_order_goods c ON b.order_id = c.order_id
WHERE
a.deleted = 0
AND b.deleted = 0
AND a.order_no in
<foreach collection="orderNoList" index="index" item="item" open="(" close=")" separator=",">
#{item}
</foreach>
</select>
<!-- 根据订单号修改订单 -->
<update id="updateByOutTradeNo" parameterType="com.gxwebsoft.cms.entity.CmsWebsite">
UPDATE shop_order

View File

@@ -0,0 +1,57 @@
<?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.gxwebsoft.shop.mapper.ShopVerifyUserMapper">
<!-- 关联查询sql -->
<sql id="selectSql">
SELECT a.*
FROM shop_verify_user a
<where>
<if test="param.id != null">
AND a.id = #{param.id}
</if>
<if test="param.userId != null">
AND a.user_id = #{param.userId}
</if>
<if test="param.verifyFlag != null">
AND a.verify_flag = #{param.verifyFlag}
</if>
<if test="param.status != null">
AND a.status = #{param.status}
</if>
<if test="param.creator != null">
AND a.creator = #{param.creator}
</if>
<if test="param.createTimeStart != null">
AND a.create_time &gt;= #{param.createTimeStart}
</if>
<if test="param.createTimeEnd != null">
AND a.create_time &lt;= #{param.createTimeEnd}
</if>
<if test="param.updater != null">
AND a.updater = #{param.updater}
</if>
<if test="param.deleted != null">
AND a.deleted = #{param.deleted}
</if>
<if test="param.deleted == null">
AND a.deleted = 0
</if>
<if test="param.keywords != null">
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
)
</if>
</where>
</sql>
<!-- 分页查询 -->
<select id="selectPageRel" resultType="com.gxwebsoft.shop.entity.ShopVerifyUser">
<include refid="selectSql"></include>
</select>
<!-- 查询全部 -->
<select id="selectListRel" resultType="com.gxwebsoft.shop.entity.ShopVerifyUser">
<include refid="selectSql"></include>
</select>
</mapper>

View File

@@ -35,6 +35,9 @@ public class ShopActiveImageParam extends BaseParam {
@Schema(description = "图片地址")
private String imgUrl;
@Schema(description = "分享底图")
private String shareImg;
@Schema(description = "启用状态 0-启用 1-禁用")
@QueryField(type = QueryType.EQ)
private Integer status;

View File

@@ -69,6 +69,9 @@ public class ShopFlashSaleActivityParam extends BaseParam {
@QueryField(type = QueryType.EQ)
private Integer sortNumber;
@Schema(description = "是否弹窗 0-否 1-是")
private Integer popFlag;
@Schema(description = "创建者")
private String creator;

View File

@@ -1,15 +1,17 @@
package com.gxwebsoft.shop.param;
import java.math.BigDecimal;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.gxwebsoft.common.core.annotation.QueryField;
import com.gxwebsoft.common.core.annotation.QueryType;
import com.gxwebsoft.common.core.web.BaseParam;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* 商品查询参数
*
@@ -158,4 +160,33 @@ public class ShopGoodsParam extends BaseParam {
@QueryField(type = QueryType.EQ)
private Integer deliveryMode;
@Schema(description = "配送方式:1-自配送 2-自提 4-发快递 多属性用','隔开")
private String deliveryType;
@Schema(description = "水票标识 0-否 1-是")
private Integer waterTicketFlag;
@Schema(description = "水票ID")
private Integer waterTickerId;
@Schema(description = "0-按每桶楼层计算 1-固定金额")
private Integer deliveryFeeType;
@Schema(description = "租户id")
private Integer tenantId;
@Schema(description = "创建人")
private Integer creator;
@Schema(description = "创建时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
@Schema(description = "修改人")
private Integer updater;
@Schema(description = "修改时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime updateTime;
}

View File

@@ -0,0 +1,21 @@
package com.gxwebsoft.shop.param;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 商品分润设定查询参数
*
* @author xm
* @since 2026-05-20 14:33:00
*/
@Data
public class ShopGoodsProfitParam {
@Schema(description = "类型 1-股东分红 2-其他")
private Integer type;
@Schema(description = "商品ID")
private Integer goodsId;
}

View File

@@ -0,0 +1,52 @@
package com.gxwebsoft.shop.param;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.gxwebsoft.common.core.annotation.QueryField;
import com.gxwebsoft.common.core.annotation.QueryType;
import com.gxwebsoft.common.core.web.BaseParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 订单核销人管理查询参数
*
* @author xm
* @since 2026-05-25 17:13:00
*/
@Data
@EqualsAndHashCode(callSuper = false)
@JsonInclude(JsonInclude.Include.NON_NULL)
@Schema(name = "ShopVerifyUserParam对象", description = "订单核销人管理查询参数")
public class ShopVerifyUserParam extends BaseParam {
private static final long serialVersionUID = 1L;
@Schema(description = "主键ID")
@QueryField(type = QueryType.EQ)
private Integer id;
@Schema(description = "用户ID")
@QueryField(type = QueryType.EQ)
private Integer userId;
@Schema(description = "核销权限是否开启 0-未开启 1-已开启")
@QueryField(type = QueryType.EQ)
private Integer verifyFlag;
@Schema(description = "是否开启 0-未开始 1-已开启")
@QueryField(type = QueryType.EQ)
private Integer status;
@Schema(description = "创建人")
@QueryField(type = QueryType.EQ)
private Integer creator;
@Schema(description = "更新人")
@QueryField(type = QueryType.EQ)
private Integer updater;
@Schema(description = "是否删除 0-未删 1-已删")
@QueryField(type = QueryType.EQ)
private Integer deleted;
}

View File

@@ -23,6 +23,7 @@ import java.math.RoundingMode;
import java.security.SecureRandom;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@@ -93,7 +94,9 @@ public class OrderBusinessService {
ShopOrder shopOrder = buildShopOrder(request, loginUser);
//3. 处理收货地址信息
if(!(shopOrder.getOrderType() != null && shopOrder.getOrderType() == 2)){
processDeliveryAddress(shopOrder, request, loginUser);
}
//4. 下单时校验配送范围(电子围栏)
validateDeliveryFenceIfNeeded(shopOrder, loginUser);
@@ -134,18 +137,6 @@ public class OrderBusinessService {
throw new BusinessException("用户未登录");
}
// 检查是否为测试账号
boolean isTestAccount = orderConfig.isTestAccount(loginUser.getPhone());
if (isTestAccount) {
// 测试账号:直接使用测试金额,跳过金额验证
BigDecimal testAmount = orderConfig.getTestAccount().getTestPayAmount();
request.setTotalPrice(testAmount);
log.info("测试账号订单,用户:{},使用测试金额:{}", loginUser.getPhone(), testAmount);
return; // 测试账号跳过后续验证
}
// 非测试账号:正常验证流程
// 验证商品信息并计算总金额
BigDecimal calculatedTotal = validateAndCalculateTotal(request);
@@ -157,7 +148,6 @@ public class OrderBusinessService {
if (request.getTotalPrice() != null &&
request.getTotalPrice().subtract(calculatedTotal).abs().compareTo(new BigDecimal("0.01")) > 0) {
log.warn("订单金额计算不一致,前端传入:{},后台计算:{}", request.getTotalPrice(), calculatedTotal);
// throw new BusinessException("订单金额计算错误,请刷新重试");
}
// 使用后台计算的金额
@@ -328,23 +318,6 @@ public class OrderBusinessService {
shopOrder.setComments(orderConfig.getDefaultConfig().getDefaultComments());
}
// 设置价格相关字段(解决数据库字段没有默认值的问题)
if (shopOrder.getPayPrice() == null) {
shopOrder.setPayPrice(shopOrder.getTotalPrice()); // 实际付款默认等于订单总额
}
if (shopOrder.getPrice() == null) {
shopOrder.setPrice(shopOrder.getTotalPrice()); // 用于统计的价格默认等于订单总额
}
if (shopOrder.getReducePrice() == null) {
shopOrder.setReducePrice(BigDecimal.ZERO); // 减少金额默认为0
}
if (shopOrder.getMoney() == null) {
shopOrder.setMoney(shopOrder.getTotalPrice()); // 用于积分赠送的价格默认等于订单总额
}
// 设置默认状态
shopOrder.setPayStatus(false); // 未付款
shopOrder.setOrderStatus(0); // 未使用
@@ -378,6 +351,21 @@ public class OrderBusinessService {
shopOrder.setWaterTicketFlag(0);
}
//自配送才计算步梯费用业务【选择步梯配送方式、配送楼层大于1楼、商品已设置配送费】
if(Arrays.asList(1, 3).contains(shopOrder.getOrderType()) && shopOrder.getDeliveryMethod() == 1 && shopOrder.getDeliveryFloor() > 1
&& shopGoods.getDeliveryFee().compareTo(BigDecimal.ZERO) > 0){
BigDecimal deliveryFee = BigDecimal.ZERO;
if(shopGoods.getDeliveryFeeType() == 0 ){
deliveryFee = BigDecimal.valueOf(shopOrder.getDeliveryFloor() - 1).multiply(shopGoods.getDeliveryFee()).multiply(BigDecimal.valueOf(goodsItem.getQuantity()));
}else if(shopOrder.getDeliveryFloor() > 1){
deliveryFee = shopGoods.getDeliveryFee();
}
if(deliveryFee.compareTo(BigDecimal.ZERO) > 0){
shopOrder.setDeliveryFee(deliveryFee);
shopOrder.setTotalPrice(shopOrder.getTotalPrice().add(deliveryFee));
}
}
//单一配送方式商品如用户没选择配送方式按商品默认配送属性设定订单类型
String deliveryType = shopGoods.getDeliveryType();
if(orderType == null && StrUtil.isNotBlank(deliveryType) && !deliveryType.contains(",")){
@@ -396,14 +384,31 @@ public class OrderBusinessService {
break;
}
default:{
orderType = 1;
orderType = 5;
}
}
}
}
}
shopOrder.setOrderType(orderType);
// 设置价格相关字段(解决数据库字段没有默认值的问题)
if (shopOrder.getPayPrice() == null) {
shopOrder.setPayPrice(shopOrder.getTotalPrice()); // 实际付款默认等于订单总额
}
if (shopOrder.getPrice() == null) {
shopOrder.setPrice(shopOrder.getTotalPrice()); // 用于统计的价格默认等于订单总额
}
if (shopOrder.getReducePrice() == null) {
shopOrder.setReducePrice(BigDecimal.ZERO); // 减少金额默认为0
}
if (shopOrder.getMoney() == null) {
shopOrder.setMoney(shopOrder.getTotalPrice()); // 用于积分赠送的价格默认等于订单总额
}
shopOrder.setOrderType(orderType);
return shopOrder;
}
@@ -551,7 +556,9 @@ public class OrderBusinessService {
return;
}
// 5. 如果用户没有任何收货地址,抛出异常
if(Arrays.asList(1, 3, 4).contains(shopOrder.getOrderType())){
throw new BusinessException("请先添加收货地址");
}
} catch (BusinessException e) {
throw e;
@@ -667,8 +674,8 @@ public class OrderBusinessService {
throw new BusinessException("收货地址坐标异常,请重新选择收货地址");
}
//订单类型:5-配送【系统自动识别电子围栏内转及时配送,电子围栏外发快递】
if(orderType != null && orderType == 5){
//订单类型:6-配送【系统自动识别电子围栏内转及时配送,电子围栏外发快递】
if(orderType != null && orderType == 6){
Boolean exit = shopStoreFenceService.validatePointInEnabled(shopOrder.getTenantId(), lng, lat);
if(exit){
shopOrder.setOrderType(1);

View File

@@ -2,8 +2,10 @@ package com.gxwebsoft.shop.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.shop.dto.ShopDealerCapitalWaterDto;
import com.gxwebsoft.shop.entity.ShopDealerCapital;
import com.gxwebsoft.shop.param.ShopDealerCapitalParam;
import com.gxwebsoft.shop.vo.ShopDealerCapitalWaterVO;
import java.util.List;
@@ -23,6 +25,13 @@ public interface ShopDealerCapitalService extends IService<ShopDealerCapital> {
*/
PageResult<ShopDealerCapital> pageRel(ShopDealerCapitalParam param);
/**
* 分页查询分销商个人流水
* @param waterDto
* @return
*/
PageResult<ShopDealerCapitalWaterVO> myCapitalWater(ShopDealerCapitalWaterDto waterDto);
/**
* 关联查询全部
*

View File

@@ -17,5 +17,7 @@ public interface ShopDealerCommissionRollbackService {
* @return true=执行成功或无可回退数据false=执行失败
*/
boolean rollbackOnOrderRefund(ShopOrder order, BigDecimal refundAmount);
boolean rollbackOnOrderRefundV2(ShopOrder order, BigDecimal refundAmount);
}

View File

@@ -5,6 +5,7 @@ import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.shop.entity.ShopDealerOrder;
import com.gxwebsoft.shop.param.ShopDealerOrderParam;
import java.math.BigDecimal;
import java.util.List;
/**
@@ -39,6 +40,12 @@ public interface ShopDealerOrderService extends IService<ShopDealerOrder> {
*/
ShopDealerOrder getByIdRel(Integer id);
/**
* 查询门店/服务商本人今日收益
* @return
*/
BigDecimal todayRevenue();
/**
* 手动触发单条订单的佣金解冻(保留与定时任务相同的前置条件检查)
*

View File

@@ -2,6 +2,9 @@ package com.gxwebsoft.shop.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.glt.vo.UserRelationVO;
import com.gxwebsoft.shop.dto.ShopDealerRefundDto;
import com.gxwebsoft.shop.dto.ShopDealerSettlementDto;
import com.gxwebsoft.shop.dto.ShopDealerUserReduceDto;
import com.gxwebsoft.shop.entity.ShopDealerUser;
import com.gxwebsoft.shop.param.ShopDealerUserParam;
@@ -50,4 +53,43 @@ public interface ShopDealerUserService extends IService<ShopDealerUser> {
* @return
*/
Boolean reduceBalance(ShopDealerUserReduceDto reduceDto);
/**
* 分销订单退款
* @param refundDto
* @return
*/
Boolean refundOrder(ShopDealerRefundDto refundDto);
/**
* 用户资金结算
* @param dto
* @return
*/
Boolean settlementBatch(ShopDealerSettlementDto dto);
/**
* 订单分红变更冻结账户
* @param dto
* @return
*/
Boolean orderProfit(ShopDealerSettlementDto dto);
Boolean updateInfo(ShopDealerUser shopDealerUser);
/**
* 开启/关闭分销商用户核销权限
* @param id
* @return
*/
Boolean verifyEnable(Integer id);
/**
* 查询用户上级门店、上级服务商
* @param userId
* @return
*/
UserRelationVO getUserSuperior(Integer userId);
}

View File

@@ -24,6 +24,13 @@ public interface ShopFlashSaleActivityService extends IService<ShopFlashSaleActi
*/
PageResult<ShopFlashSaleActivityVO> pageRel(ShopFlashSaleActivityParam param);
/**
* 查询详情
* @param id
* @return
*/
ShopFlashSaleActivityVO getInfoById(Integer id);
/**
* 关联查询全部
*
@@ -45,7 +52,7 @@ public interface ShopFlashSaleActivityService extends IService<ShopFlashSaleActi
* @param tenantId 租户ID
* @return
*/
List<ShopFlashSaleActivityVO> getMyActive(Integer tenantId);
List<ShopFlashSaleActivityVO> getMyActive(Integer tenantId, Integer popFlag);
/**
* 修改秒杀活动状态

View File

@@ -0,0 +1,41 @@
package com.gxwebsoft.shop.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.gxwebsoft.shop.dto.ShopGoodsProfitUpdateDto;
import com.gxwebsoft.shop.entity.ShopGoodsProfit;
import com.gxwebsoft.shop.vo.ShopGoodsProfitVO;
import java.util.List;
/**
* 商品分润设定Service
*
* @author xm
* @since 2026-05-20 14:33:00
*/
public interface ShopGoodsProfitService extends IService<ShopGoodsProfit> {
/**
* 通过商品、类型查询分润信息
* @param goodsId
* @param type
* @return
*/
List<ShopGoodsProfitVO> getByGoodsId(Integer goodsId, Integer type);
/**
* 查询启用状态的商品分润信息
* @param goodsIdList 商品ID集合
* @param type 分润类型
* @return
*/
List<ShopGoodsProfitVO> getGoodsProfit(List<Integer> goodsIdList, Integer type);
/**
* 根据商品ID修改商品分润设定
* @param updateDto
* @return
*/
Boolean updateByGoodsId(ShopGoodsProfitUpdateDto updateDto);
}

View File

@@ -47,4 +47,5 @@ public interface ShopOrderGoodsService extends IService<ShopOrderGoods> {
* @return List<ShopOrderGoods>
*/
List<ShopOrderGoods> getListByOrderIdIgnoreTenant(Integer orderId);
}

View File

@@ -2,10 +2,13 @@ package com.gxwebsoft.shop.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.shop.dto.ShopOrderMyVerifyDto;
import com.gxwebsoft.shop.dto.UserOrderStats;
import com.gxwebsoft.shop.dto.VerifyShopOrderDto;
import com.gxwebsoft.shop.entity.ShopOrder;
import com.gxwebsoft.shop.param.ShopOrderParam;
import com.gxwebsoft.shop.vo.ShopOrderGoodsInfoVO;
import com.gxwebsoft.shop.vo.ShopOrderMyVerifyVO;
import java.math.BigDecimal;
import java.util.HashMap;
@@ -43,6 +46,12 @@ public interface ShopOrderService extends IService<ShopOrder> {
*/
ShopOrder getByIdRel(Integer orderId);
/**
* 我已核销订单
* @return
*/
ShopOrderMyVerifyVO myVerifyOrder(ShopOrderMyVerifyDto myVerifyDto);
HashMap<String, String> createWxOrder(ShopOrder shopOrder);
ShopOrder getByOutTradeNo(String outTradeNo);
@@ -94,4 +103,11 @@ public interface ShopOrderService extends IService<ShopOrder> {
* @return
*/
Boolean verifyOrder(VerifyShopOrderDto verifyDto);
/**
* 通过订单号查询订单商品名称
* @param orderNoList
* @return
*/
List<ShopOrderGoodsInfoVO> getOrderGoodsInfoByOrderNos(List<String> orderNoList);
}

View File

@@ -0,0 +1,70 @@
package com.gxwebsoft.shop.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.shop.entity.ShopVerifyUser;
import com.gxwebsoft.shop.param.ShopVerifyUserParam;
import java.util.List;
/**
* 订单核销人管理Service
*
* @author xm
* @since 2026-05-25 17:13:00
*/
public interface ShopVerifyUserService extends IService<ShopVerifyUser> {
/**
* 分页关联查询
*
* @param param 查询参数
* @return PageResult<ShopVerifyUser>
*/
PageResult<ShopVerifyUser> pageRel(ShopVerifyUserParam param);
/**
* 关联查询全部
*
* @param param 查询参数
* @return List<ShopVerifyUser>
*/
List<ShopVerifyUser> listRel(ShopVerifyUserParam param);
/**
* 根据id查询
*
* @param id 主键ID
* @return ShopVerifyUser
*/
ShopVerifyUser getByIdRel(Integer id);
/**
* 通过用户ID查询
* @param userId
* @return
*/
ShopVerifyUser getInfo(Integer userId);
/**
* 修改订单核销人开启状态
* @param id 主键ID
* @return
*/
Boolean updateStatus(Integer id);
/**
* 修改订单核销人核销权限
* @param id 主键ID
* @return
*/
Boolean updateVerifyFlag(Integer id);
/**
* 保存数据
* @param shopVerifyUser
* @return
*/
Boolean saveInfo(ShopVerifyUser shopVerifyUser);
}

View File

@@ -5,15 +5,19 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gxwebsoft.common.core.web.PageParam;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.shop.entity.ShopActiveImage;
import com.gxwebsoft.shop.entity.ShopGoods;
import com.gxwebsoft.shop.mapper.ShopActiveImageMapper;
import com.gxwebsoft.shop.mapper.ShopGoodsMapper;
import com.gxwebsoft.shop.param.ShopActiveImageParam;
import com.gxwebsoft.shop.service.ShopActiveImageService;
import lombok.AllArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* 推广码底图Service实现
@@ -25,16 +29,34 @@ import java.util.List;
@AllArgsConstructor
public class ShopActiveImageServiceImpl extends ServiceImpl<ShopActiveImageMapper, ShopActiveImage> implements ShopActiveImageService {
private ShopGoodsMapper shopGoodsMapper;
@Override
public PageResult<ShopActiveImage> pageRel(ShopActiveImageParam param) {
PageParam<ShopActiveImage, ShopActiveImageParam> page = new PageParam<>(param);
page.setDefaultOrder("sort_number asc, create_time desc");
List<ShopActiveImage> list = baseMapper.selectPageRel(page, param);
if(CollectionUtils.isNotEmpty(list)){
List<Integer> goodsIdList = list.stream().filter(shopActiveImage -> shopActiveImage.getGoodsId() != null).map(ShopActiveImage::getGoodsId)
.distinct().collect(Collectors.toList());
List<ShopGoods> shopGoodsList = new ArrayList<>();
if(CollectionUtils.isNotEmpty(goodsIdList)){
shopGoodsList = shopGoodsMapper.selectBatchIds(goodsIdList);
}
List<ShopGoods> finalShopGoodsList = shopGoodsList;
list.forEach(shopActiveImage -> {
if(!StringUtils.isEmpty(shopActiveImage.getImgUrl())){
shopActiveImage.setImgUrlList(Arrays.asList(shopActiveImage.getImgUrl().split(",")));
}
//回显商品名称
if(shopActiveImage.getGoodsId() != null){
ShopGoods shopGoods = finalShopGoodsList.stream().filter(goods -> shopActiveImage.getGoodsId().equals(goods.getGoodsId())).findFirst().orElse(null);
if(shopGoods != null){
shopActiveImage.setGoodsName(shopGoods.getName());
}
}
});
}
return new PageResult<>(list, page.getTotal());

View File

@@ -1,14 +1,24 @@
package com.gxwebsoft.shop.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gxwebsoft.common.core.exception.BusinessException;
import com.gxwebsoft.common.core.exception.enums.GlobalErrorCodeConstants;
import com.gxwebsoft.common.core.utils.LoginUserUtil;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.shop.dto.ShopDealerCapitalWaterDto;
import com.gxwebsoft.shop.mapper.ShopDealerCapitalMapper;
import com.gxwebsoft.shop.service.ShopDealerCapitalService;
import com.gxwebsoft.shop.entity.ShopDealerCapital;
import com.gxwebsoft.shop.param.ShopDealerCapitalParam;
import com.gxwebsoft.common.core.web.PageParam;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.shop.vo.ShopDealerCapitalWaterVO;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
@@ -28,6 +38,27 @@ public class ShopDealerCapitalServiceImpl extends ServiceImpl<ShopDealerCapitalM
return new PageResult<>(list, page.getTotal());
}
@Override
public PageResult<ShopDealerCapitalWaterVO> myCapitalWater(ShopDealerCapitalWaterDto entity) {
PageResult<ShopDealerCapitalWaterVO> pageResult = new PageResult<>();
User loginUser = LoginUserUtil.getLoginUser();
if(loginUser == null){
throw new BusinessException(GlobalErrorCodeConstants.UNAUTHORIZED.getMsg());
}
entity.setUserId(loginUser.getUserId());
IPage<ShopDealerCapitalWaterVO> pageInfo = baseMapper.getPageInfo(new Page<>(entity.getPage(), entity.getLimit()), entity);
if(CollectionUtils.isNotEmpty(pageInfo.getRecords())){
List<ShopDealerCapitalWaterVO> records = pageInfo.getRecords();
pageResult.setList(records);
pageResult.setCount(pageInfo.getTotal());
}else {
pageResult.setCount(0l);
pageResult.setList(new ArrayList<>());
}
return pageResult;
}
@Override
public List<ShopDealerCapital> listRel(ShopDealerCapitalParam param) {
List<ShopDealerCapital> list = baseMapper.selectListRel(param);

View File

@@ -1,8 +1,10 @@
package com.gxwebsoft.shop.service.impl;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.gxwebsoft.shop.dto.ShopDealerRefundDto;
import com.gxwebsoft.shop.entity.ShopDealerCapital;
import com.gxwebsoft.shop.entity.ShopDealerOrder;
import com.gxwebsoft.shop.entity.ShopDealerUser;
@@ -137,6 +139,59 @@ public class ShopDealerCommissionRollbackServiceImpl implements ShopDealerCommis
return true;
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean rollbackOnOrderRefundV2(ShopOrder order, BigDecimal refundAmount) {
if (order == null || order.getTenantId() == null || StrUtil.isEmpty(order.getOrderNo())) {
return true;
}
Integer tenantId = order.getTenantId();
String orderNo = order.getOrderNo();
//判断退款金额不能大于实付金额
if(refundAmount.compareTo(order.getPayPrice()) > 0){
throw new RuntimeException("退款金额不能大于订单实付金额!");
}
//执行分销订单退款业务
ShopDealerRefundDto refundDto = new ShopDealerRefundDto();
refundDto.setOrderNo(orderNo);
refundDto.setTenantId(tenantId);
refundDto.setRefundAmount(refundAmount);
Boolean refundResult = shopDealerUserService.refundOrder(refundDto);
if(refundResult){
//退款金额与实付金额一致,标记分销订单失效
if (order.getPayPrice().compareTo(refundAmount) == 0) {
markDealerOrderInvalid(tenantId, orderNo);
}else {
BigDecimal rate = refundAmount.divide(order.getPayPrice(), 3, RoundingMode.HALF_UP);
BigDecimal remainRate = BigDecimal.ONE.subtract(rate);
LambdaQueryWrapper<ShopDealerOrder> orderLambdaQueryWrapper = new LambdaQueryWrapper<ShopDealerOrder>().eq(ShopDealerOrder::getOrderNo, orderNo);
ShopDealerOrder shopDealerOrder = shopDealerOrderService.getOne(orderLambdaQueryWrapper);
if(shopDealerOrder != null){
if(shopDealerOrder.getFirstMoney().compareTo(BigDecimal.ZERO) > 0){
shopDealerOrder.setFirstMoney(shopDealerOrder.getFirstMoney().multiply(remainRate));
}
if(shopDealerOrder.getSecondMoney().compareTo(BigDecimal.ZERO) > 0){
shopDealerOrder.setSecondMoney(shopDealerOrder.getSecondMoney().multiply(remainRate));
}
if(shopDealerOrder.getFirstDividend().compareTo(BigDecimal.ZERO) > 0){
shopDealerOrder.setFirstDividend(shopDealerOrder.getFirstDividend().multiply(remainRate));
}
if(shopDealerOrder.getSecondDividend().compareTo(BigDecimal.ZERO) > 0){
shopDealerOrder.setSecondDividend(shopDealerOrder.getSecondDividend().multiply(remainRate));
}
shopDealerOrder.setUpdateTime(LocalDateTime.now());
shopDealerOrderService.updateById(shopDealerOrder);
}
}
return Boolean.TRUE;
}else {
return Boolean.FALSE;
}
}
private boolean hasUnfreezeMarker(Integer tenantId, ShopDealerCapital cap) {
if (tenantId == null || cap == null || cap.getId() == null || cap.getUserId() == null || cap.getOrderNo() == null) {
return false;

Some files were not shown because too many files have changed in this diff Show More