feat(glt): 添加送水订单模块并优化经销商结算功能
- 新增送水订单实体类 GltTicketOrder 及其相关控制器、服务、映射器 - 添加送水订单参数类 GltTicketOrderParam 和 XML 映射配置 - 实现送水订单的增删改查、分页查询等完整 CRUD 功能 - 在经销商结算任务中引入分销设置功能,支持按级别控制分佣 - 更新总经销商分润计算逻辑,使用动态费率替代固定值 - 删除不再使用的中文字体修复脚本文件 - 重构经销商推荐佣金结算逻辑,支持最多三级分佣 - 优化订单状态检查逻辑,在退款流程中排除已完成订单
This commit is contained in:
@@ -1,125 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# 捐款证书中文乱码修复脚本
|
|
||||||
# 用途:在运行中的Docker容器内安装中文字体
|
|
||||||
# 适用于:无法重新构建镜像的紧急情况
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
set -e # 遇到错误立即退出
|
|
||||||
|
|
||||||
# 颜色输出
|
|
||||||
RED='\033[0;31m'
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
YELLOW='\033[1;33m'
|
|
||||||
NC='\033[0m' # No Color
|
|
||||||
|
|
||||||
# 容器名称(可根据实际情况修改)
|
|
||||||
CONTAINER_NAME="websoft-api-container"
|
|
||||||
|
|
||||||
echo -e "${GREEN}================================${NC}"
|
|
||||||
echo -e "${GREEN}中文字体修复脚本${NC}"
|
|
||||||
echo -e "${GREEN}================================${NC}"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 检查容器是否存在
|
|
||||||
echo -e "${YELLOW}步骤 1/6: 检查容器状态...${NC}"
|
|
||||||
if ! docker ps | grep -q "$CONTAINER_NAME"; then
|
|
||||||
echo -e "${RED}错误:容器 $CONTAINER_NAME 未运行!${NC}"
|
|
||||||
echo "当前运行的容器:"
|
|
||||||
docker ps --format "table {{.Names}}\t{{.Status}}"
|
|
||||||
echo ""
|
|
||||||
read -p "请输入正确的容器名称: " CONTAINER_NAME
|
|
||||||
if [ -z "$CONTAINER_NAME" ]; then
|
|
||||||
echo -e "${RED}容器名称不能为空,退出。${NC}"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
echo -e "${GREEN}✓ 容器正在运行${NC}"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 检查是否已安装字体
|
|
||||||
echo -e "${YELLOW}步骤 2/6: 检查是否已安装中文字体...${NC}"
|
|
||||||
if docker exec "$CONTAINER_NAME" fc-list :lang=zh 2>/dev/null | grep -q "WenQuanYi"; then
|
|
||||||
echo -e "${GREEN}✓ 中文字体已安装${NC}"
|
|
||||||
docker exec "$CONTAINER_NAME" fc-list :lang=zh
|
|
||||||
echo ""
|
|
||||||
read -p "是否重新安装?(y/N): " REINSTALL
|
|
||||||
if [[ ! "$REINSTALL" =~ ^[Yy]$ ]]; then
|
|
||||||
echo "跳过安装,退出。"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo -e "${YELLOW}未检测到中文字体,开始安装...${NC}"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 安装字体工具
|
|
||||||
echo -e "${YELLOW}步骤 3/6: 安装字体工具...${NC}"
|
|
||||||
docker exec -u root "$CONTAINER_NAME" sh -c "apk add --no-cache fontconfig ttf-dejavu wget" || {
|
|
||||||
echo -e "${RED}✗ 字体工具安装失败${NC}"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
echo -e "${GREEN}✓ 字体工具安装成功${NC}"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 下载中文字体
|
|
||||||
echo -e "${YELLOW}步骤 4/6: 下载文泉驿微米黑字体...${NC}"
|
|
||||||
echo "正在从GitHub下载(约10MB),请稍候..."
|
|
||||||
docker exec -u root "$CONTAINER_NAME" sh -c "
|
|
||||||
wget -O /tmp/wqy-microhei.ttc https://github.com/anthonyfok/fonts-wqy-microhei/raw/master/wqy-microhei.ttc 2>&1 | grep -E 'Connecting|Length|saved' || true
|
|
||||||
" || {
|
|
||||||
echo -e "${YELLOW}GitHub下载失败,尝试使用代理...${NC}"
|
|
||||||
docker exec -u root "$CONTAINER_NAME" sh -c "
|
|
||||||
wget -O /tmp/wqy-microhei.ttc https://ghproxy.com/https://github.com/anthonyfok/fonts-wqy-microhei/raw/master/wqy-microhei.ttc
|
|
||||||
" || {
|
|
||||||
echo -e "${RED}✗ 字体下载失败${NC}"
|
|
||||||
echo "请检查网络连接或手动下载字体文件。"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
echo -e "${GREEN}✓ 字体下载成功${NC}"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 安装字体
|
|
||||||
echo -e "${YELLOW}步骤 5/6: 安装字体文件...${NC}"
|
|
||||||
docker exec -u root "$CONTAINER_NAME" sh -c "
|
|
||||||
mkdir -p /usr/share/fonts/truetype/wqy && \
|
|
||||||
mv /tmp/wqy-microhei.ttc /usr/share/fonts/truetype/wqy/ && \
|
|
||||||
fc-cache -fv
|
|
||||||
" || {
|
|
||||||
echo -e "${RED}✗ 字体安装失败${NC}"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
echo -e "${GREEN}✓ 字体安装成功${NC}"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 验证安装
|
|
||||||
echo -e "${YELLOW}步骤 6/6: 验证字体安装...${NC}"
|
|
||||||
FONT_COUNT=$(docker exec "$CONTAINER_NAME" fc-list :lang=zh | wc -l)
|
|
||||||
if [ "$FONT_COUNT" -gt 0 ]; then
|
|
||||||
echo -e "${GREEN}✓ 中文字体验证成功!${NC}"
|
|
||||||
echo "已安装的中文字体:"
|
|
||||||
docker exec "$CONTAINER_NAME" fc-list :lang=zh
|
|
||||||
else
|
|
||||||
echo -e "${RED}✗ 字体验证失败${NC}"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 完成提示
|
|
||||||
echo -e "${GREEN}================================${NC}"
|
|
||||||
echo -e "${GREEN}修复完成!${NC}"
|
|
||||||
echo -e "${GREEN}================================${NC}"
|
|
||||||
echo ""
|
|
||||||
echo "后续步骤:"
|
|
||||||
echo "1. 不需要重启容器,字体已生效"
|
|
||||||
echo "2. 重新生成捐款证书即可看到效果"
|
|
||||||
echo "3. 如果仍有问题,请查看容器日志:"
|
|
||||||
echo " docker logs -f $CONTAINER_NAME"
|
|
||||||
echo ""
|
|
||||||
echo -e "${YELLOW}注意:${NC}"
|
|
||||||
echo "- 此修复方法在容器重启后会失效"
|
|
||||||
echo "- 建议后续使用更新后的Dockerfile重新构建镜像"
|
|
||||||
echo "- 详细文档请参考:docs/chinese-font-fix-guide.md"
|
|
||||||
echo ""
|
|
||||||
@@ -13,8 +13,9 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package cn.afterturn.easypoi.excel.entity;
|
package com.gxwebsoft.common.core.web;
|
||||||
|
|
||||||
|
import cn.afterturn.easypoi.excel.entity.ExcelBaseParams;
|
||||||
import cn.afterturn.easypoi.handler.inter.IExcelVerifyHandler;
|
import cn.afterturn.easypoi.handler.inter.IExcelVerifyHandler;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@@ -0,0 +1,127 @@
|
|||||||
|
package com.gxwebsoft.glt.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.BatchParam;
|
||||||
|
import com.gxwebsoft.common.core.web.PageResult;
|
||||||
|
import com.gxwebsoft.glt.entity.GltTicketOrder;
|
||||||
|
import com.gxwebsoft.glt.param.GltTicketOrderParam;
|
||||||
|
import com.gxwebsoft.glt.service.GltTicketOrderService;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 送水订单控制器
|
||||||
|
*
|
||||||
|
* @author 科技小王子
|
||||||
|
* @since 2026-02-05 18:50:21
|
||||||
|
*/
|
||||||
|
@Tag(name = "送水订单管理")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/glt/glt-ticket-order")
|
||||||
|
public class GltTicketOrderController extends BaseController {
|
||||||
|
@Resource
|
||||||
|
private GltTicketOrderService gltTicketOrderService;
|
||||||
|
|
||||||
|
@PreAuthorize("hasAuthority('glt:gltTicketOrder:list')")
|
||||||
|
@Operation(summary = "分页查询送水订单")
|
||||||
|
@GetMapping("/page")
|
||||||
|
public ApiResult<PageResult<GltTicketOrder>> page(GltTicketOrderParam param) {
|
||||||
|
// 使用关联查询
|
||||||
|
return success(gltTicketOrderService.pageRel(param));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PreAuthorize("hasAuthority('glt:gltTicketOrder:list')")
|
||||||
|
@Operation(summary = "查询全部送水订单")
|
||||||
|
@GetMapping()
|
||||||
|
public ApiResult<List<GltTicketOrder>> list(GltTicketOrderParam param) {
|
||||||
|
// 使用关联查询
|
||||||
|
return success(gltTicketOrderService.listRel(param));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PreAuthorize("hasAuthority('glt:gltTicketOrder:list')")
|
||||||
|
@Operation(summary = "根据id查询送水订单")
|
||||||
|
@GetMapping("/{id}")
|
||||||
|
public ApiResult<GltTicketOrder> get(@PathVariable("id") Integer id) {
|
||||||
|
// 使用关联查询
|
||||||
|
return success(gltTicketOrderService.getByIdRel(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PreAuthorize("hasAuthority('glt:gltTicketOrder:save')")
|
||||||
|
@OperationLog
|
||||||
|
@Operation(summary = "添加送水订单")
|
||||||
|
@PostMapping()
|
||||||
|
public ApiResult<?> save(@RequestBody GltTicketOrder gltTicketOrder) {
|
||||||
|
// 记录当前登录用户id
|
||||||
|
// User loginUser = getLoginUser();
|
||||||
|
// if (loginUser != null) {
|
||||||
|
// gltTicketOrder.setUserId(loginUser.getUserId());
|
||||||
|
// }
|
||||||
|
if (gltTicketOrderService.save(gltTicketOrder)) {
|
||||||
|
return success("添加成功");
|
||||||
|
}
|
||||||
|
return fail("添加失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
@PreAuthorize("hasAuthority('glt:gltTicketOrder:update')")
|
||||||
|
@OperationLog
|
||||||
|
@Operation(summary = "修改送水订单")
|
||||||
|
@PutMapping()
|
||||||
|
public ApiResult<?> update(@RequestBody GltTicketOrder gltTicketOrder) {
|
||||||
|
if (gltTicketOrderService.updateById(gltTicketOrder)) {
|
||||||
|
return success("修改成功");
|
||||||
|
}
|
||||||
|
return fail("修改失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
@PreAuthorize("hasAuthority('glt:gltTicketOrder:remove')")
|
||||||
|
@OperationLog
|
||||||
|
@Operation(summary = "删除送水订单")
|
||||||
|
@DeleteMapping("/{id}")
|
||||||
|
public ApiResult<?> remove(@PathVariable("id") Integer id) {
|
||||||
|
if (gltTicketOrderService.removeById(id)) {
|
||||||
|
return success("删除成功");
|
||||||
|
}
|
||||||
|
return fail("删除失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
@PreAuthorize("hasAuthority('glt:gltTicketOrder:save')")
|
||||||
|
@OperationLog
|
||||||
|
@Operation(summary = "批量添加送水订单")
|
||||||
|
@PostMapping("/batch")
|
||||||
|
public ApiResult<?> saveBatch(@RequestBody List<GltTicketOrder> list) {
|
||||||
|
if (gltTicketOrderService.saveBatch(list)) {
|
||||||
|
return success("添加成功");
|
||||||
|
}
|
||||||
|
return fail("添加失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
@PreAuthorize("hasAuthority('glt:gltTicketOrder:update')")
|
||||||
|
@OperationLog
|
||||||
|
@Operation(summary = "批量修改送水订单")
|
||||||
|
@PutMapping("/batch")
|
||||||
|
public ApiResult<?> removeBatch(@RequestBody BatchParam<GltTicketOrder> batchParam) {
|
||||||
|
if (batchParam.update(gltTicketOrderService, "id")) {
|
||||||
|
return success("修改成功");
|
||||||
|
}
|
||||||
|
return fail("修改失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
@PreAuthorize("hasAuthority('glt:gltTicketOrder:remove')")
|
||||||
|
@OperationLog
|
||||||
|
@Operation(summary = "批量删除送水订单")
|
||||||
|
@DeleteMapping("/batch")
|
||||||
|
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
|
||||||
|
if (gltTicketOrderService.removeByIds(ids)) {
|
||||||
|
return success("删除成功");
|
||||||
|
}
|
||||||
|
return fail("删除失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
84
src/main/java/com/gxwebsoft/glt/entity/GltTicketOrder.java
Normal file
84
src/main/java/com/gxwebsoft/glt/entity/GltTicketOrder.java
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
package com.gxwebsoft.glt.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||||
|
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.math.BigDecimal;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 送水订单
|
||||||
|
*
|
||||||
|
* @author 科技小王子
|
||||||
|
* @since 2026-02-05 18:50:20
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
@Schema(name = "GltTicketOrder对象", description = "送水订单")
|
||||||
|
public class GltTicketOrder implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@TableId(value = "id", type = IdType.AUTO)
|
||||||
|
private Integer id;
|
||||||
|
|
||||||
|
@Schema(description = "用户水票ID")
|
||||||
|
private Integer userTicketId;
|
||||||
|
|
||||||
|
@Schema(description = "门店ID")
|
||||||
|
private Integer storeId;
|
||||||
|
|
||||||
|
@Schema(description = "配送员")
|
||||||
|
private Integer riderId;
|
||||||
|
|
||||||
|
@Schema(description = "仓库ID")
|
||||||
|
private Integer warehouseId;
|
||||||
|
|
||||||
|
@Schema(description = "关联收货地址")
|
||||||
|
private Integer addressId;
|
||||||
|
|
||||||
|
@Schema(description = "收货地址")
|
||||||
|
private String address;
|
||||||
|
|
||||||
|
@Schema(description = "买家留言")
|
||||||
|
private String buyerRemarks;
|
||||||
|
|
||||||
|
@Schema(description = "用于统计")
|
||||||
|
private BigDecimal price;
|
||||||
|
|
||||||
|
@Schema(description = "购买数量")
|
||||||
|
private Integer totalNum;
|
||||||
|
|
||||||
|
@Schema(description = "用户ID")
|
||||||
|
private Integer userId;
|
||||||
|
|
||||||
|
@Schema(description = "排序(数字越小越靠前)")
|
||||||
|
private Integer sortNumber;
|
||||||
|
|
||||||
|
@Schema(description = "备注")
|
||||||
|
private String comments;
|
||||||
|
|
||||||
|
@Schema(description = "状态, 0正常, 1冻结")
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
@Schema(description = "是否删除, 0否, 1是")
|
||||||
|
@TableLogic
|
||||||
|
private Integer deleted;
|
||||||
|
|
||||||
|
@Schema(description = "租户id")
|
||||||
|
private Integer tenantId;
|
||||||
|
|
||||||
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private LocalDateTime createTime;
|
||||||
|
|
||||||
|
@Schema(description = "修改时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private LocalDateTime updateTime;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package com.gxwebsoft.glt.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
import com.gxwebsoft.glt.entity.GltTicketOrder;
|
||||||
|
import com.gxwebsoft.glt.param.GltTicketOrderParam;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 送水订单Mapper
|
||||||
|
*
|
||||||
|
* @author 科技小王子
|
||||||
|
* @since 2026-02-05 18:50:20
|
||||||
|
*/
|
||||||
|
public interface GltTicketOrderMapper extends BaseMapper<GltTicketOrder> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询
|
||||||
|
*
|
||||||
|
* @param page 分页对象
|
||||||
|
* @param param 查询参数
|
||||||
|
* @return List<GltTicketOrder>
|
||||||
|
*/
|
||||||
|
List<GltTicketOrder> selectPageRel(@Param("page") IPage<GltTicketOrder> page,
|
||||||
|
@Param("param") GltTicketOrderParam param);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询全部
|
||||||
|
*
|
||||||
|
* @param param 查询参数
|
||||||
|
* @return List<User>
|
||||||
|
*/
|
||||||
|
List<GltTicketOrder> selectListRel(@Param("param") GltTicketOrderParam param);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
<?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.glt.mapper.GltTicketOrderMapper">
|
||||||
|
|
||||||
|
<!-- 关联查询sql -->
|
||||||
|
<sql id="selectSql">
|
||||||
|
SELECT a.*
|
||||||
|
FROM glt_ticket_order a
|
||||||
|
<where>
|
||||||
|
<if test="param.id != null">
|
||||||
|
AND a.id = #{param.id}
|
||||||
|
</if>
|
||||||
|
<if test="param.userTicketId != null">
|
||||||
|
AND a.user_ticket_id = #{param.userTicketId}
|
||||||
|
</if>
|
||||||
|
<if test="param.storeId != null">
|
||||||
|
AND a.store_id = #{param.storeId}
|
||||||
|
</if>
|
||||||
|
<if test="param.riderId != null">
|
||||||
|
AND a.rider_id = #{param.riderId}
|
||||||
|
</if>
|
||||||
|
<if test="param.warehouseId != null">
|
||||||
|
AND a.warehouse_id = #{param.warehouseId}
|
||||||
|
</if>
|
||||||
|
<if test="param.addressId != null">
|
||||||
|
AND a.address_id = #{param.addressId}
|
||||||
|
</if>
|
||||||
|
<if test="param.address != null">
|
||||||
|
AND a.address LIKE CONCAT('%', #{param.address}, '%')
|
||||||
|
</if>
|
||||||
|
<if test="param.buyerRemarks != null">
|
||||||
|
AND a.buyer_remarks LIKE CONCAT('%', #{param.buyerRemarks}, '%')
|
||||||
|
</if>
|
||||||
|
<if test="param.price != null">
|
||||||
|
AND a.price = #{param.price}
|
||||||
|
</if>
|
||||||
|
<if test="param.totalNum != null">
|
||||||
|
AND a.total_num = #{param.totalNum}
|
||||||
|
</if>
|
||||||
|
<if test="param.userId != null">
|
||||||
|
AND a.user_id = #{param.userId}
|
||||||
|
</if>
|
||||||
|
<if test="param.sortNumber != null">
|
||||||
|
AND a.sort_number = #{param.sortNumber}
|
||||||
|
</if>
|
||||||
|
<if test="param.comments != null">
|
||||||
|
AND a.comments LIKE CONCAT('%', #{param.comments}, '%')
|
||||||
|
</if>
|
||||||
|
<if test="param.status != null">
|
||||||
|
AND a.status = #{param.status}
|
||||||
|
</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.createTimeStart != null">
|
||||||
|
AND a.create_time >= #{param.createTimeStart}
|
||||||
|
</if>
|
||||||
|
<if test="param.createTimeEnd != null">
|
||||||
|
AND a.create_time <= #{param.createTimeEnd}
|
||||||
|
</if>
|
||||||
|
<if test="param.keywords != null">
|
||||||
|
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
|
||||||
|
)
|
||||||
|
</if>
|
||||||
|
</where>
|
||||||
|
</sql>
|
||||||
|
|
||||||
|
<!-- 分页查询 -->
|
||||||
|
<select id="selectPageRel" resultType="com.gxwebsoft.glt.entity.GltTicketOrder">
|
||||||
|
<include refid="selectSql"></include>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 查询全部 -->
|
||||||
|
<select id="selectListRel" resultType="com.gxwebsoft.glt.entity.GltTicketOrder">
|
||||||
|
<include refid="selectSql"></include>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</mapper>
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
package com.gxwebsoft.glt.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;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 送水订单查询参数
|
||||||
|
*
|
||||||
|
* @author 科技小王子
|
||||||
|
* @since 2026-02-05 18:50:19
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
|
@Schema(name = "GltTicketOrderParam对象", description = "送水订单查询参数")
|
||||||
|
public class GltTicketOrderParam extends BaseParam {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@QueryField(type = QueryType.EQ)
|
||||||
|
private Integer id;
|
||||||
|
|
||||||
|
@Schema(description = "用户水票ID")
|
||||||
|
@QueryField(type = QueryType.EQ)
|
||||||
|
private Integer userTicketId;
|
||||||
|
|
||||||
|
@Schema(description = "门店ID")
|
||||||
|
@QueryField(type = QueryType.EQ)
|
||||||
|
private Integer storeId;
|
||||||
|
|
||||||
|
@Schema(description = "配送员")
|
||||||
|
@QueryField(type = QueryType.EQ)
|
||||||
|
private Integer riderId;
|
||||||
|
|
||||||
|
@Schema(description = "仓库ID")
|
||||||
|
@QueryField(type = QueryType.EQ)
|
||||||
|
private Integer warehouseId;
|
||||||
|
|
||||||
|
@Schema(description = "关联收货地址")
|
||||||
|
@QueryField(type = QueryType.EQ)
|
||||||
|
private Integer addressId;
|
||||||
|
|
||||||
|
@Schema(description = "收货地址")
|
||||||
|
private String address;
|
||||||
|
|
||||||
|
@Schema(description = "买家留言")
|
||||||
|
private String buyerRemarks;
|
||||||
|
|
||||||
|
@Schema(description = "用于统计")
|
||||||
|
@QueryField(type = QueryType.EQ)
|
||||||
|
private BigDecimal price;
|
||||||
|
|
||||||
|
@Schema(description = "购买数量")
|
||||||
|
@QueryField(type = QueryType.EQ)
|
||||||
|
private Integer totalNum;
|
||||||
|
|
||||||
|
@Schema(description = "用户ID")
|
||||||
|
@QueryField(type = QueryType.EQ)
|
||||||
|
private Integer userId;
|
||||||
|
|
||||||
|
@Schema(description = "排序(数字越小越靠前)")
|
||||||
|
@QueryField(type = QueryType.EQ)
|
||||||
|
private Integer sortNumber;
|
||||||
|
|
||||||
|
@Schema(description = "备注")
|
||||||
|
private String comments;
|
||||||
|
|
||||||
|
@Schema(description = "状态, 0正常, 1冻结")
|
||||||
|
@QueryField(type = QueryType.EQ)
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
@Schema(description = "是否删除, 0否, 1是")
|
||||||
|
@QueryField(type = QueryType.EQ)
|
||||||
|
private Integer deleted;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package com.gxwebsoft.glt.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import com.gxwebsoft.common.core.web.PageResult;
|
||||||
|
import com.gxwebsoft.glt.entity.GltTicketOrder;
|
||||||
|
import com.gxwebsoft.glt.param.GltTicketOrderParam;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 送水订单Service
|
||||||
|
*
|
||||||
|
* @author 科技小王子
|
||||||
|
* @since 2026-02-05 18:50:20
|
||||||
|
*/
|
||||||
|
public interface GltTicketOrderService extends IService<GltTicketOrder> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页关联查询
|
||||||
|
*
|
||||||
|
* @param param 查询参数
|
||||||
|
* @return PageResult<GltTicketOrder>
|
||||||
|
*/
|
||||||
|
PageResult<GltTicketOrder> pageRel(GltTicketOrderParam param);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关联查询全部
|
||||||
|
*
|
||||||
|
* @param param 查询参数
|
||||||
|
* @return List<GltTicketOrder>
|
||||||
|
*/
|
||||||
|
List<GltTicketOrder> listRel(GltTicketOrderParam param);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据id查询
|
||||||
|
*
|
||||||
|
* @param id
|
||||||
|
* @return GltTicketOrder
|
||||||
|
*/
|
||||||
|
GltTicketOrder getByIdRel(Integer id);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package com.gxwebsoft.glt.service.impl;
|
||||||
|
|
||||||
|
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.glt.entity.GltTicketOrder;
|
||||||
|
import com.gxwebsoft.glt.mapper.GltTicketOrderMapper;
|
||||||
|
import com.gxwebsoft.glt.param.GltTicketOrderParam;
|
||||||
|
import com.gxwebsoft.glt.service.GltTicketOrderService;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 送水订单Service实现
|
||||||
|
*
|
||||||
|
* @author 科技小王子
|
||||||
|
* @since 2026-02-05 18:50:20
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class GltTicketOrderServiceImpl extends ServiceImpl<GltTicketOrderMapper, GltTicketOrder> implements GltTicketOrderService {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PageResult<GltTicketOrder> pageRel(GltTicketOrderParam param) {
|
||||||
|
PageParam<GltTicketOrder, GltTicketOrderParam> page = new PageParam<>(param);
|
||||||
|
page.setDefaultOrder("sort_number asc, create_time desc");
|
||||||
|
List<GltTicketOrder> list = baseMapper.selectPageRel(page, param);
|
||||||
|
return new PageResult<>(list, page.getTotal());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<GltTicketOrder> listRel(GltTicketOrderParam param) {
|
||||||
|
List<GltTicketOrder> list = baseMapper.selectListRel(param);
|
||||||
|
// 排序
|
||||||
|
PageParam<GltTicketOrder, GltTicketOrderParam> page = new PageParam<>();
|
||||||
|
page.setDefaultOrder("sort_number asc, create_time desc");
|
||||||
|
return page.sortRecords(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GltTicketOrder getByIdRel(Integer id) {
|
||||||
|
GltTicketOrderParam param = new GltTicketOrderParam();
|
||||||
|
param.setId(id);
|
||||||
|
return param.getOne(baseMapper.selectListRel(param));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ import com.gxwebsoft.common.core.annotation.IgnoreTenant;
|
|||||||
import com.gxwebsoft.shop.entity.ShopDealerCapital;
|
import com.gxwebsoft.shop.entity.ShopDealerCapital;
|
||||||
import com.gxwebsoft.shop.entity.ShopDealerOrder;
|
import com.gxwebsoft.shop.entity.ShopDealerOrder;
|
||||||
import com.gxwebsoft.shop.entity.ShopDealerReferee;
|
import com.gxwebsoft.shop.entity.ShopDealerReferee;
|
||||||
|
import com.gxwebsoft.shop.entity.ShopDealerSetting;
|
||||||
import com.gxwebsoft.shop.entity.ShopDealerUser;
|
import com.gxwebsoft.shop.entity.ShopDealerUser;
|
||||||
import com.gxwebsoft.shop.entity.ShopGoods;
|
import com.gxwebsoft.shop.entity.ShopGoods;
|
||||||
import com.gxwebsoft.shop.entity.ShopOrder;
|
import com.gxwebsoft.shop.entity.ShopOrder;
|
||||||
@@ -15,11 +16,13 @@ import com.gxwebsoft.common.system.mapper.UserMapper;
|
|||||||
import com.gxwebsoft.shop.service.ShopDealerCapitalService;
|
import com.gxwebsoft.shop.service.ShopDealerCapitalService;
|
||||||
import com.gxwebsoft.shop.service.ShopDealerOrderService;
|
import com.gxwebsoft.shop.service.ShopDealerOrderService;
|
||||||
import com.gxwebsoft.shop.service.ShopDealerRefereeService;
|
import com.gxwebsoft.shop.service.ShopDealerRefereeService;
|
||||||
|
import com.gxwebsoft.shop.service.ShopDealerSettingService;
|
||||||
import com.gxwebsoft.shop.service.ShopDealerUserService;
|
import com.gxwebsoft.shop.service.ShopDealerUserService;
|
||||||
import com.gxwebsoft.shop.service.ShopGoodsService;
|
import com.gxwebsoft.shop.service.ShopGoodsService;
|
||||||
import com.gxwebsoft.shop.service.ShopOrderService;
|
import com.gxwebsoft.shop.service.ShopOrderService;
|
||||||
import com.gxwebsoft.shop.service.ShopOrderGoodsService;
|
import com.gxwebsoft.shop.service.ShopOrderGoodsService;
|
||||||
import com.gxwebsoft.shop.util.UpstreamUserFinder;
|
import com.gxwebsoft.shop.util.UpstreamUserFinder;
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@@ -72,6 +75,9 @@ public class DealerOrderSettlement10584Task {
|
|||||||
@Resource
|
@Resource
|
||||||
private ShopDealerOrderService shopDealerOrderService;
|
private ShopDealerOrderService shopDealerOrderService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ShopDealerSettingService shopDealerSettingService;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private ShopGoodsService shopGoodsService;
|
private ShopGoodsService shopGoodsService;
|
||||||
|
|
||||||
@@ -96,10 +102,12 @@ public class DealerOrderSettlement10584Task {
|
|||||||
// Per-run caches to reduce DB chatter across orders.
|
// Per-run caches to reduce DB chatter across orders.
|
||||||
Map<Integer, Integer> level1ParentCache = new HashMap<>();
|
Map<Integer, Integer> level1ParentCache = new HashMap<>();
|
||||||
Map<Integer, Boolean> shopRoleCache = new HashMap<>();
|
Map<Integer, Boolean> shopRoleCache = new HashMap<>();
|
||||||
Integer totalDealerUserId = findTotalDealerUserId();
|
DealerBasicSetting dealerBasicSetting = findDealerBasicSetting();
|
||||||
if (totalDealerUserId == null) {
|
ShopDealerUser totalDealerUser = findTotalDealerUser();
|
||||||
|
if (totalDealerUser == null || totalDealerUser.getUserId() == null) {
|
||||||
log.warn("未找到总经销商账号,订单仍可结算但不会发放总经销商分润 - tenantId={}", TENANT_ID);
|
log.warn("未找到总经销商账号,订单仍可结算但不会发放总经销商分润 - tenantId={}", TENANT_ID);
|
||||||
}
|
}
|
||||||
|
log.debug("租户{}分销设置 - level={}", TENANT_ID, dealerBasicSetting.level);
|
||||||
|
|
||||||
log.info("租户{}待结算订单数: {}, orderNos(sample)={}",
|
log.info("租户{}待结算订单数: {}, orderNos(sample)={}",
|
||||||
TENANT_ID,
|
TENANT_ID,
|
||||||
@@ -113,7 +121,7 @@ public class DealerOrderSettlement10584Task {
|
|||||||
if (!claimOrderToSettle(order.getOrderId())) {
|
if (!claimOrderToSettle(order.getOrderId())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
settleOneOrder(order, level1ParentCache, shopRoleCache, totalDealerUserId);
|
settleOneOrder(order, level1ParentCache, shopRoleCache, totalDealerUser, dealerBasicSetting.level);
|
||||||
});
|
});
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("订单结算失败,将回滚本订单并在下次任务重试 - orderId={}, orderNo={}", order.getOrderId(), order.getOrderNo(), e);
|
log.error("订单结算失败,将回滚本订单并在下次任务重试 - orderId={}, orderNo={}", order.getOrderId(), order.getOrderNo(), e);
|
||||||
@@ -150,7 +158,8 @@ public class DealerOrderSettlement10584Task {
|
|||||||
ShopOrder order,
|
ShopOrder order,
|
||||||
Map<Integer, Integer> level1ParentCache,
|
Map<Integer, Integer> level1ParentCache,
|
||||||
Map<Integer, Boolean> shopRoleCache,
|
Map<Integer, Boolean> shopRoleCache,
|
||||||
Integer totalDealerUserId
|
ShopDealerUser totalDealerUser,
|
||||||
|
int dealerLevel
|
||||||
) {
|
) {
|
||||||
if (order.getUserId() == null || order.getOrderNo() == null) {
|
if (order.getUserId() == null || order.getOrderNo() == null) {
|
||||||
throw new IllegalStateException("订单关键信息缺失,无法结算 - orderId=" + order.getOrderId());
|
throw new IllegalStateException("订单关键信息缺失,无法结算 - orderId=" + order.getOrderId());
|
||||||
@@ -188,13 +197,13 @@ public class DealerOrderSettlement10584Task {
|
|||||||
commissionConfig.storeSimpleValue);
|
commissionConfig.storeSimpleValue);
|
||||||
|
|
||||||
// 1) 直推/间推(shop_dealer_referee)
|
// 1) 直推/间推(shop_dealer_referee)
|
||||||
DealerRefereeCommission dealerRefereeCommission = settleDealerRefereeCommission(order, baseAmount, goodsQty, commissionConfig);
|
DealerRefereeCommission dealerRefereeCommission = settleDealerRefereeCommission(order, baseAmount, goodsQty, commissionConfig, dealerLevel);
|
||||||
|
|
||||||
// 2) 门店分红上级:从下单用户开始逐级向上找,命中 ShopDealerUser.type=1 的最近两级(直推门店/间推门店)。
|
// 2) 门店分红上级:从下单用户开始逐级向上找,命中 ShopDealerUser.type=1 的最近两级(直推门店/间推门店)。
|
||||||
ShopRoleCommission shopRoleCommission = settleShopRoleRefereeCommission(order, baseAmount, goodsQty, commissionConfig, level1ParentCache, shopRoleCache);
|
ShopRoleCommission shopRoleCommission = settleShopRoleRefereeCommission(order, baseAmount, goodsQty, commissionConfig, level1ParentCache, shopRoleCache);
|
||||||
|
|
||||||
// 3) 总经销商分润:固定比率,每个订单都分。
|
// 3) 总经销商分润:固定比率,每个订单都分。
|
||||||
TotalDealerCommission totalDealerCommission = settleTotalDealerCommission(order, baseAmount, goodsQty, totalDealerUserId);
|
TotalDealerCommission totalDealerCommission = settleTotalDealerCommission(order, baseAmount, goodsQty, totalDealerUser);
|
||||||
|
|
||||||
// 4) 写入分销订单记录(用于排查/统计;详细分佣以 ShopDealerCapital 为准)
|
// 4) 写入分销订单记录(用于排查/统计;详细分佣以 ShopDealerCapital 为准)
|
||||||
createDealerOrderRecord(order, baseAmount, dealerRefereeCommission, shopRoleCommission, totalDealerCommission);
|
createDealerOrderRecord(order, baseAmount, dealerRefereeCommission, shopRoleCommission, totalDealerCommission);
|
||||||
@@ -202,19 +211,39 @@ public class DealerOrderSettlement10584Task {
|
|||||||
log.info("订单结算完成 - orderId={}, orderNo={}, baseAmount={}", order.getOrderId(), order.getOrderNo(), baseAmount);
|
log.info("订单结算完成 - orderId={}, orderNo={}, baseAmount={}", order.getOrderId(), order.getOrderNo(), baseAmount);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DealerRefereeCommission settleDealerRefereeCommission(ShopOrder order, BigDecimal baseAmount, int goodsQty, CommissionConfig commissionConfig) {
|
private DealerRefereeCommission settleDealerRefereeCommission(
|
||||||
|
ShopOrder order,
|
||||||
|
BigDecimal baseAmount,
|
||||||
|
int goodsQty,
|
||||||
|
CommissionConfig commissionConfig,
|
||||||
|
int dealerLevel
|
||||||
|
) {
|
||||||
// 兼容两种数据形态:
|
// 兼容两种数据形态:
|
||||||
// 1) 同一 userId 下有 level=1/2 的多级关系(直接按 level 取);
|
// 1) 同一 userId 下有 level=1/2/3 的多级关系(直接按 level 取);
|
||||||
// 2) 仅维护 level=1(用“查两次”回退获取上级)。
|
// 2) 仅维护 level=1(用“查两次”回退获取上级)。
|
||||||
Integer directDealerId = getDealerRefereeId(order.getUserId(), 1);
|
//
|
||||||
Integer simpleDealerId = getDealerRefereeId(order.getUserId(), 2);
|
// 严格按“分销设置 level”决定发放到第几级,避免 level=2 时仍触发第3级发放逻辑。
|
||||||
|
int normalizedLevel = normalizeDealerLevel(dealerLevel);
|
||||||
|
|
||||||
|
Integer directDealerId = null;
|
||||||
|
Integer simpleDealerId = null;
|
||||||
|
Integer thirdDealerId = null;
|
||||||
|
|
||||||
|
if (normalizedLevel >= 1) {
|
||||||
|
directDealerId = getDealerRefereeId(order.getUserId(), 1);
|
||||||
|
}
|
||||||
|
if (normalizedLevel >= 2) {
|
||||||
|
simpleDealerId = getDealerRefereeId(order.getUserId(), 2);
|
||||||
if (simpleDealerId == null && directDealerId != null) {
|
if (simpleDealerId == null && directDealerId != null) {
|
||||||
simpleDealerId = getDealerRefereeId(directDealerId, 1);
|
simpleDealerId = getDealerRefereeId(directDealerId, 1);
|
||||||
}
|
}
|
||||||
Integer thirdDealerId = getDealerRefereeId(order.getUserId(), 3);
|
}
|
||||||
|
if (normalizedLevel >= 3) {
|
||||||
|
thirdDealerId = getDealerRefereeId(order.getUserId(), 3);
|
||||||
if (thirdDealerId == null && simpleDealerId != null) {
|
if (thirdDealerId == null && simpleDealerId != null) {
|
||||||
thirdDealerId = getDealerRefereeId(simpleDealerId, 1);
|
thirdDealerId = getDealerRefereeId(simpleDealerId, 1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BigDecimal directMoney =
|
BigDecimal directMoney =
|
||||||
directDealerId != null ? calcMoneyByCommissionType(baseAmount, commissionConfig.dealerDirectValue, goodsQty, 2, commissionConfig.commissionType) : BigDecimal.ZERO;
|
directDealerId != null ? calcMoneyByCommissionType(baseAmount, commissionConfig.dealerDirectValue, goodsQty, 2, commissionConfig.commissionType) : BigDecimal.ZERO;
|
||||||
@@ -228,6 +257,7 @@ public class DealerOrderSettlement10584Task {
|
|||||||
order.getOrderNo(), order.getUserId(), directDealerId, directMoney, simpleDealerId, simpleMoney, thirdDealerId, thirdMoney);
|
order.getOrderNo(), order.getUserId(), directDealerId, directMoney, simpleDealerId, simpleMoney, thirdDealerId, thirdMoney);
|
||||||
|
|
||||||
// 直推:对方=买家;推荐奖(5%):对方=直推分销商(便于在资金明细中看出“来自哪个下级分销商/团队订单”)
|
// 直推:对方=买家;推荐奖(5%):对方=直推分销商(便于在资金明细中看出“来自哪个下级分销商/团队订单”)
|
||||||
|
if (normalizedLevel >= 1) {
|
||||||
creditDealerCommission(
|
creditDealerCommission(
|
||||||
directDealerId,
|
directDealerId,
|
||||||
directMoney,
|
directMoney,
|
||||||
@@ -235,6 +265,8 @@ public class DealerOrderSettlement10584Task {
|
|||||||
order.getUserId(),
|
order.getUserId(),
|
||||||
buildCommissionComment("直推佣金", commissionConfig.commissionType, commissionConfig.dealerDirectValue, goodsQty)
|
buildCommissionComment("直推佣金", commissionConfig.commissionType, commissionConfig.dealerDirectValue, goodsQty)
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
if (normalizedLevel >= 2) {
|
||||||
creditDealerCommission(
|
creditDealerCommission(
|
||||||
simpleDealerId,
|
simpleDealerId,
|
||||||
simpleMoney,
|
simpleMoney,
|
||||||
@@ -242,6 +274,8 @@ public class DealerOrderSettlement10584Task {
|
|||||||
directDealerId,
|
directDealerId,
|
||||||
buildCommissionComment("推荐奖", commissionConfig.commissionType, commissionConfig.dealerSimpleValue, goodsQty)
|
buildCommissionComment("推荐奖", commissionConfig.commissionType, commissionConfig.dealerSimpleValue, goodsQty)
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
if (normalizedLevel >= 3) {
|
||||||
creditDealerCommission(
|
creditDealerCommission(
|
||||||
thirdDealerId,
|
thirdDealerId,
|
||||||
thirdMoney,
|
thirdMoney,
|
||||||
@@ -249,6 +283,7 @@ public class DealerOrderSettlement10584Task {
|
|||||||
simpleDealerId,
|
simpleDealerId,
|
||||||
buildCommissionComment("分润收入", commissionConfig.commissionType, commissionConfig.dealerThirdValue, goodsQty)
|
buildCommissionComment("分润收入", commissionConfig.commissionType, commissionConfig.dealerThirdValue, goodsQty)
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return new DealerRefereeCommission(directDealerId, directMoney, simpleDealerId, simpleMoney, thirdDealerId, thirdMoney);
|
return new DealerRefereeCommission(directDealerId, directMoney, simpleDealerId, simpleMoney, thirdDealerId, thirdMoney);
|
||||||
}
|
}
|
||||||
@@ -340,26 +375,30 @@ public class DealerOrderSettlement10584Task {
|
|||||||
ShopOrder order,
|
ShopOrder order,
|
||||||
BigDecimal baseAmount,
|
BigDecimal baseAmount,
|
||||||
int goodsQty,
|
int goodsQty,
|
||||||
Integer totalDealerUserId
|
ShopDealerUser totalDealerUser
|
||||||
) {
|
) {
|
||||||
if (totalDealerUserId == null) {
|
if (totalDealerUser == null || totalDealerUser.getUserId() == null) {
|
||||||
return TotalDealerCommission.empty();
|
return TotalDealerCommission.empty();
|
||||||
}
|
}
|
||||||
BigDecimal money = calcMoneyByCommissionType(baseAmount, TOTAL_DEALER_DIVIDEND_RATE, goodsQty, DIVIDEND_SCALE, 20);
|
BigDecimal rate = safePositive(totalDealerUser.getRate());
|
||||||
|
if (rate.signum() <= 0) {
|
||||||
|
rate = TOTAL_DEALER_DIVIDEND_RATE;
|
||||||
|
}
|
||||||
|
BigDecimal money = calcMoneyByCommissionType(baseAmount, rate, goodsQty, DIVIDEND_SCALE, 20);
|
||||||
log.info("总经销商分润发放 - orderNo={}, totalDealerUserId={}, rate={}, money={}",
|
log.info("总经销商分润发放 - orderNo={}, totalDealerUserId={}, rate={}, money={}",
|
||||||
order.getOrderNo(), totalDealerUserId, TOTAL_DEALER_DIVIDEND_RATE, money);
|
order.getOrderNo(), totalDealerUser.getUserId(), rate, money);
|
||||||
creditDealerCommission(
|
creditDealerCommission(
|
||||||
totalDealerUserId,
|
totalDealerUser.getUserId(),
|
||||||
money,
|
money,
|
||||||
order,
|
order,
|
||||||
order.getUserId(),
|
order.getUserId(),
|
||||||
buildCommissionComment("总经销商分润", 20, TOTAL_DEALER_DIVIDEND_RATE, goodsQty)
|
buildCommissionComment("总经销商分润", 20, rate, goodsQty)
|
||||||
);
|
);
|
||||||
return new TotalDealerCommission(totalDealerUserId, money);
|
return new TotalDealerCommission(totalDealerUser.getUserId(), money);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Integer findTotalDealerUserId() {
|
private ShopDealerUser findTotalDealerUser() {
|
||||||
ShopDealerUser dealerUser = shopDealerUserService.getOne(
|
return shopDealerUserService.getOne(
|
||||||
new LambdaQueryWrapper<ShopDealerUser>()
|
new LambdaQueryWrapper<ShopDealerUser>()
|
||||||
.eq(ShopDealerUser::getTenantId, TENANT_ID)
|
.eq(ShopDealerUser::getTenantId, TENANT_ID)
|
||||||
.eq(ShopDealerUser::getType, 2)
|
.eq(ShopDealerUser::getType, 2)
|
||||||
@@ -367,7 +406,46 @@ public class DealerOrderSettlement10584Task {
|
|||||||
.orderByAsc(ShopDealerUser::getId)
|
.orderByAsc(ShopDealerUser::getId)
|
||||||
.last("limit 1")
|
.last("limit 1")
|
||||||
);
|
);
|
||||||
return dealerUser != null ? dealerUser.getUserId() : null;
|
}
|
||||||
|
|
||||||
|
private DealerBasicSetting findDealerBasicSetting() {
|
||||||
|
int level = 2;
|
||||||
|
ShopDealerSetting setting = shopDealerSettingService.getOne(
|
||||||
|
new LambdaQueryWrapper<ShopDealerSetting>()
|
||||||
|
.eq(ShopDealerSetting::getTenantId, TENANT_ID)
|
||||||
|
.eq(ShopDealerSetting::getKey, "basic")
|
||||||
|
.last("limit 1")
|
||||||
|
);
|
||||||
|
if (setting != null && setting.getValues() != null && !setting.getValues().isBlank()) {
|
||||||
|
try {
|
||||||
|
JSONObject json = JSONObject.parseObject(setting.getValues());
|
||||||
|
Integer levelVal = json.getInteger("level");
|
||||||
|
if (levelVal != null && levelVal > 0) {
|
||||||
|
level = Math.min(levelVal, 3);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("解析分销设置失败,将使用默认等级 - tenantId={}, values={}", TENANT_ID, setting.getValues(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new DealerBasicSetting(level);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int normalizeDealerLevel(int dealerLevel) {
|
||||||
|
if (dealerLevel <= 0) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
return Math.min(dealerLevel, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* shop_dealer_setting(key=basic) 的关键配置(仅取结算任务需要的字段)。
|
||||||
|
*/
|
||||||
|
private static class DealerBasicSetting {
|
||||||
|
private final int level;
|
||||||
|
|
||||||
|
private DealerBasicSetting(int level) {
|
||||||
|
this.level = level;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -265,7 +265,7 @@ public class ShopOrderController extends BaseController {
|
|||||||
return fail("订单不存在");
|
return fail("订单不存在");
|
||||||
}
|
}
|
||||||
// 退款相关操作单独走退款接口,便于做财务权限隔离
|
// 退款相关操作单独走退款接口,便于做财务权限隔离
|
||||||
if (Objects.equals(shopOrder.getOrderStatus(), 4) || Objects.equals(shopOrder.getOrderStatus(), 6)) {
|
if (Objects.equals(shopOrder.getOrderStatus(), 6)) {
|
||||||
return fail("退款相关操作请使用退款接口: PUT /api/shop/shop-order/refund");
|
return fail("退款相关操作请使用退款接口: PUT /api/shop/shop-order/refund");
|
||||||
}
|
}
|
||||||
ShopOrder shopOrderNow = shopOrderService.getById(shopOrder.getOrderId());
|
ShopOrder shopOrderNow = shopOrderService.getById(shopOrder.getOrderId());
|
||||||
|
|||||||
Reference in New Issue
Block a user