Compare commits

...

8 Commits

Author SHA1 Message Date
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
1350250847@qq.com
bc3842faee 变更数据库链接 2026-04-20 16:38:04 +08:00
1350250847@qq.com
8d2a0c46b7 常量注释 2026-04-14 16:57:34 +08:00
24 changed files with 504 additions and 317 deletions

View File

@@ -103,7 +103,8 @@ public class MybatisPlusConfig {
"shop_dealer_user", "shop_dealer_user",
"shop_dealer_order", "shop_dealer_order",
"shop_dealer_referee", "shop_dealer_referee",
"shop_store_rider" "shop_store_rider",
"shop_goods_profit"
).contains(tableName); ).contains(tableName);
} }
}; };

View File

@@ -143,7 +143,8 @@ public class GltTicketIssueService {
//2.执行分销员分销、统计门店/服务商分销业务 //2.执行分销员分销、统计门店/服务商分销业务
dealerOrderSettlement.orderSettlement(orderNo); dealerOrderSettlement.orderSettlement(orderNo);
//3.执行平台分红业务 TODO 待开发 //3.执行平台分红业务
dealerOrderSettlement.partnerProfit(orderNo, tenantId);
//4.普通商品【非水票订单】如果是需要自配送的,则会同步生成派单信息 //4.普通商品【非水票订单】如果是需要自配送的,则会同步生成派单信息
gltTicketOrderService.dispatchOrder(orderNo, tenantId); gltTicketOrderService.dispatchOrder(orderNo, tenantId);

View File

@@ -17,10 +17,10 @@ import java.time.LocalDateTime;
*/ */
public interface GltTicketOrderService extends IService<GltTicketOrder> { public interface GltTicketOrderService extends IService<GltTicketOrder> {
int DELIVERY_STATUS_WAITING = 10; int DELIVERY_STATUS_WAITING = 10; //待配送
int DELIVERY_STATUS_DELIVERING = 20; int DELIVERY_STATUS_DELIVERING = 20; //配送中
int DELIVERY_STATUS_WAIT_CONFIRM = 30; int DELIVERY_STATUS_WAIT_CONFIRM = 30; //等待收货
int DELIVERY_STATUS_FINISHED = 40; int DELIVERY_STATUS_FINISHED = 40; //收货完成
int RECEIVE_CONFIRM_TYPE_MANUAL = 10; int RECEIVE_CONFIRM_TYPE_MANUAL = 10;
int RECEIVE_CONFIRM_TYPE_PHOTO = 20; int RECEIVE_CONFIRM_TYPE_PHOTO = 20;

View File

@@ -8,8 +8,11 @@ import com.gxwebsoft.common.core.enums.ShopDealerCapitalUpdateEnum;
import com.gxwebsoft.common.core.enums.ShopDealerTypeEnum; import com.gxwebsoft.common.core.enums.ShopDealerTypeEnum;
import com.gxwebsoft.common.system.entity.User; import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.common.system.mapper.UserMapper; import com.gxwebsoft.common.system.mapper.UserMapper;
import com.gxwebsoft.common.system.redis.OrderNoUtils;
import com.gxwebsoft.glt.entity.GltTicketTemplate; import com.gxwebsoft.glt.entity.GltTicketTemplate;
import com.gxwebsoft.glt.service.GltTicketTemplateService; import com.gxwebsoft.glt.service.GltTicketTemplateService;
import com.gxwebsoft.shop.dto.ShopDealerSettlementDto;
import com.gxwebsoft.shop.dto.ShopDealerSettlementItemDto;
import com.gxwebsoft.shop.dto.ShopDealerUserReduceDto; import com.gxwebsoft.shop.dto.ShopDealerUserReduceDto;
import com.gxwebsoft.shop.entity.*; import com.gxwebsoft.shop.entity.*;
import com.gxwebsoft.shop.mapper.ShopDealerRefereeMapper; import com.gxwebsoft.shop.mapper.ShopDealerRefereeMapper;
@@ -17,6 +20,7 @@ import com.gxwebsoft.shop.mapper.ShopOrderMapper;
import com.gxwebsoft.shop.service.*; import com.gxwebsoft.shop.service.*;
import com.gxwebsoft.shop.util.UpstreamUserFinder; import com.gxwebsoft.shop.util.UpstreamUserFinder;
import com.gxwebsoft.shop.vo.ShopDealerRefereeVO; import com.gxwebsoft.shop.vo.ShopDealerRefereeVO;
import com.gxwebsoft.shop.vo.ShopGoodsProfitVO;
import com.gxwebsoft.shop.vo.ShopOrderGoodsVO; import com.gxwebsoft.shop.vo.ShopOrderGoodsVO;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
@@ -33,6 +37,7 @@ import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.*; import java.util.*;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
/** /**
* 租户10584分销订单结算任务 * 租户10584分销订单结算任务
@@ -94,6 +99,12 @@ public class DealerOrderSettlement10584Task {
@Resource @Resource
private ShopDealerRefereeMapper shopDealerRefereeMapper; private ShopDealerRefereeMapper shopDealerRefereeMapper;
@Resource
private ShopGoodsProfitService shopGoodsProfitService;
@Resource
private OrderNoUtils orderNoUtils;
/** /**
* 每10秒执行一次。 * 每10秒执行一次。
*/ */
@@ -230,6 +241,68 @@ public class DealerOrderSettlement10584Task {
} }
} }
/**
* 股东/合伙人分红
* @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), 2, RoundingMode.HALF_UP).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) { private List<ShopOrder> findUnsettledPaidOrders(Set<Integer> waterFormIds) {
// 租户10584约定 // 租户10584约定
// - 普通订单以发货为准deliveryStatus=20才结算 // - 普通订单以发货为准deliveryStatus=20才结算
@@ -380,12 +453,12 @@ public class DealerOrderSettlement10584Task {
// 已日结形式统计分销记录表shop_dealer_order 做对应一级二级管理津贴结算】 // 已日结形式统计分销记录表shop_dealer_order 做对应一级二级管理津贴结算】
ShopRoleCommission shopRoleCommission = settleShopRoleRefereeCommissionV2(order, rate, orderGoodsVOList, level1ParentCache, shopRoleCache); ShopRoleCommission shopRoleCommission = settleShopRoleRefereeCommissionV2(order, rate, orderGoodsVOList, level1ParentCache, shopRoleCache);
// 3) 分红:固定比率,每个订单都分 TODO 总分红未开发,还按原逻辑走 // // 3) 分红:固定比率,每个订单都分
int goodsQty = orderGoodsVOList.stream().mapToInt(ShopOrderGoodsVO::getTotalNum).sum(); // int goodsQty = orderGoodsVOList.stream().mapToInt(ShopOrderGoodsVO::getTotalNum).sum();
TotalDealerCommission totalDealerCommission = settleTotalDealerCommissionV2(order, goodsQty, totalDealerUser); // TotalDealerCommission totalDealerCommission = settleTotalDealerCommissionV2(order, goodsQty, totalDealerUser);
// 4) 写入分销订单记录(用于排查/统计;详细分佣以 ShopDealerCapital 为准) // 3) 写入分销订单记录(用于排查/统计;详细分佣以 ShopDealerCapital 为准)
createDealerOrderRecordV2(order, dealerRefereeCommission, shopRoleCommission, totalDealerCommission); createDealerOrderRecordV2(order, dealerRefereeCommission, shopRoleCommission);
log.info("订单结算完成 - orderId={}, orderNo={}, baseAmount={}", order.getOrderId(), order.getOrderNo(), payPrice); log.info("订单结算完成 - orderId={}, orderNo={}, baseAmount={}", order.getOrderId(), order.getOrderNo(), payPrice);
}else { }else {
@@ -1067,7 +1140,7 @@ public class DealerOrderSettlement10584Task {
* @param dealerRefereeCommission 一级、二级分销员分销数据 * @param dealerRefereeCommission 一级、二级分销员分销数据
* @param shopRoleCommission 门店/服务商一级、二级管理津贴数据 * @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 作为业务唯一) // 幂等:同一订单只写一条(依赖 order_no + tenant_id 作为业务唯一)
ShopDealerOrder existed = shopDealerOrderService.getOne( ShopDealerOrder existed = shopDealerOrderService.getOne(
new LambdaQueryWrapper<ShopDealerOrder>() new LambdaQueryWrapper<ShopDealerOrder>()
@@ -1141,7 +1214,7 @@ public class DealerOrderSettlement10584Task {
dealerOrder.setSettleTime(LocalDateTime.now()); dealerOrder.setSettleTime(LocalDateTime.now());
dealerOrder.setMonth(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM"))); dealerOrder.setMonth(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM")));
dealerOrder.setTenantId(TENANT_ID); dealerOrder.setTenantId(TENANT_ID);
dealerOrder.setComments(buildCommissionTraceCommentV2(dealerRefereeCommission, shopRoleCommission, totalDealerCommission)); dealerOrder.setComments(buildCommissionTraceCommentV2(dealerRefereeCommission, shopRoleCommission));
shopDealerOrderService.save(dealerOrder); shopDealerOrderService.save(dealerOrder);
} }
@@ -1163,8 +1236,7 @@ public class DealerOrderSettlement10584Task {
private String buildCommissionTraceCommentV2( private String buildCommissionTraceCommentV2(
DealerRefereeCommissionV2 dealerRefereeCommission, DealerRefereeCommissionV2 dealerRefereeCommission,
ShopRoleCommission shopRoleCommission, ShopRoleCommission shopRoleCommission
TotalDealerCommission totalDealerCommission
) { ) {
// 轻量“过程”留痕,方便排查;详细分佣以 ShopDealerCapital 为准。 // 轻量“过程”留痕,方便排查;详细分佣以 ShopDealerCapital 为准。
Integer direct = dealerRefereeCommission != null ? dealerRefereeCommission.directDealerId : null; Integer direct = dealerRefereeCommission != null ? dealerRefereeCommission.directDealerId : null;
@@ -1175,14 +1247,11 @@ public class DealerOrderSettlement10584Task {
BigDecimal storeDirectMoney = shopRoleCommission != null ? shopRoleCommission.storeDirectMoney : BigDecimal.ZERO; BigDecimal storeDirectMoney = shopRoleCommission != null ? shopRoleCommission.storeDirectMoney : BigDecimal.ZERO;
Integer storeSimpleUserId = shopRoleCommission != null ? shopRoleCommission.storeSimpleUserId : null; Integer storeSimpleUserId = shopRoleCommission != null ? shopRoleCommission.storeSimpleUserId : null;
BigDecimal storeSimpleMoney = shopRoleCommission != null ? shopRoleCommission.storeSimpleMoney : BigDecimal.ZERO; 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 return "direct=" + direct + ":" + directMoney
+ ",simple=" + simpleDealerId + ":" + simpleMoney + ",simple=" + simpleDealerId + ":" + simpleMoney
+ ",dividend1=" + storeDirectUserId + ":" + storeDirectMoney + ",dividend1=" + storeDirectUserId + ":" + storeDirectMoney
+ ",dividend2=" + storeSimpleUserId + ":" + storeSimpleMoney + ",dividend2=" + storeSimpleUserId + ":" + storeSimpleMoney;
+ ",totalDealer=" + userId + ":" + money;
} }
private BigDecimal getOrderBaseAmount(ShopOrder order) { private BigDecimal getOrderBaseAmount(ShopOrder order) {

View File

@@ -3,13 +3,14 @@ package com.gxwebsoft.shop.controller;
import com.gxwebsoft.common.core.annotation.OperationLog; import com.gxwebsoft.common.core.annotation.OperationLog;
import com.gxwebsoft.common.core.web.ApiResult; import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.BaseController; import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.common.core.web.PageResult; import com.gxwebsoft.shop.dto.ShopGoodsProfitUpdateDto;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.shop.entity.ShopGoodsProfit;
import com.gxwebsoft.shop.param.ShopGoodsProfitParam;
import com.gxwebsoft.shop.service.ShopGoodsProfitService; 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.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.ibatis.annotations.Param;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource; import javax.annotation.Resource;
@@ -29,65 +30,22 @@ public class ShopGoodsProfitController extends BaseController {
private ShopGoodsProfitService shopGoodsProfitService; private ShopGoodsProfitService shopGoodsProfitService;
// @PreAuthorize("hasAuthority('shop:shopGoodsProfit:list')") // @PreAuthorize("hasAuthority('shop:shopGoodsProfit:list')")
@Operation(summary = "分页查询商品分润设定") @Operation(summary = "通过商品、类型查询分润信息")
@GetMapping("/page") @GetMapping("/getByGoodsId")
public ApiResult<PageResult<ShopGoodsProfit>> page(ShopGoodsProfitParam param) { @Parameters({
// 使用关联查询 @Parameter(name = "goodsId", description = "商品ID", required = true, example = "10086"),
return success(shopGoodsProfitService.pageRel(param)); @Parameter(name = "type", description = "类型 1-分红 2-其他", required = true, example = "1")
} })
public ApiResult<List<ShopGoodsProfitVO>> getByGoodsId(@RequestParam("goodsId") Integer goodsId, @Param("type") Integer type) {
// @PreAuthorize("hasAuthority('shop:shopGoodsProfit:list')") return success(shopGoodsProfitService.getByGoodsId(goodsId, type));
@Operation(summary = "查询全部商品分润设定")
@GetMapping()
public ApiResult<List<ShopGoodsProfit>> list(ShopGoodsProfitParam param) {
// 使用关联查询
return success(shopGoodsProfitService.listRel(param));
}
// @PreAuthorize("hasAuthority('shop:shopGoodsProfit:list')")
@Operation(summary = "根据id查询商品分润设定")
@GetMapping("/{id}")
public ApiResult<ShopGoodsProfit> get(@PathVariable("id") Integer id) {
// 使用关联查询
return success(shopGoodsProfitService.getByIdRel(id));
}
// @PreAuthorize("hasAuthority('shop:shopGoodsProfit:save')")
@OperationLog
@Operation(summary = "添加商品分润设定")
@PostMapping()
public ApiResult<?> save(@RequestBody ShopGoodsProfit shopGoodsProfit) {
// 记录当前登录用户id
User loginUser = getLoginUser();
if (loginUser != null) {
shopGoodsProfit.setUserId(loginUser.getUserId());
}
if (shopGoodsProfitService.save(shopGoodsProfit)) {
return success("添加成功");
}
return fail("添加失败");
} }
// @PreAuthorize("hasAuthority('shop:shopGoodsProfit:update')") // @PreAuthorize("hasAuthority('shop:shopGoodsProfit:update')")
@OperationLog @OperationLog
@Operation(summary = "修改商品分润设定") @Operation(summary = "根据商品ID修改商品分润设定")
@PutMapping() @PutMapping("/updateByGoodsId")
public ApiResult<?> update(@RequestBody ShopGoodsProfit shopGoodsProfit) { public ApiResult<Boolean> update(@RequestBody ShopGoodsProfitUpdateDto updateDto) {
if (shopGoodsProfitService.updateById(shopGoodsProfit)) { return success(shopGoodsProfitService.updateByGoodsId(updateDto));
return success("修改成功");
}
return fail("修改失败");
}
// @PreAuthorize("hasAuthority('shop:shopGoodsProfit:remove')")
@OperationLog
@Operation(summary = "删除商品分润设定")
@DeleteMapping("/{id}")
public ApiResult<?> remove(@PathVariable("id") Integer id) {
if (shopGoodsProfitService.removeById(id)) {
return success("删除成功");
}
return fail("删除失败");
} }
} }

View File

@@ -1001,6 +1001,13 @@ public class ShopOrderController extends BaseController {
return success(Boolean.TRUE); 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 = "用户支付成功后主动同步订单状态") @Operation(summary = "更新订单支付状态", description = "用户支付成功后主动同步订单状态")
@PutMapping("/payment-status") @PutMapping("/payment-status")
public ApiResult<?> updateOrderPaymentStatus(@RequestBody UpdatePaymentStatusRequest request) { public ApiResult<?> updateOrderPaymentStatus(@RequestBody UpdatePaymentStatusRequest request) {

View File

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

View File

@@ -20,9 +20,15 @@ public class ShopDealerSettlementDto {
@Schema(description = "资金流动类型 (10分销收入 11团队管理津贴收入 12分红收入 13现场推广收入 20提现支出 30转账支出 40转账收入 50佣金解冻 60配送奖励 70佣金退回【退单】)") @Schema(description = "资金流动类型 (10分销收入 11团队管理津贴收入 12分红收入 13现场推广收入 20提现支出 30转账支出 40转账收入 50佣金解冻 60配送奖励 70佣金退回【退单】)")
private Integer flowType; private Integer flowType;
@Schema(description = "订单号")
private String orderNo;
@Schema(description = "描述") @Schema(description = "描述")
private String comments; private String comments;
@Schema(description = "分销来源")
private Integer toUserId;
@Schema(description = "商城ID") @Schema(description = "商城ID")
private Integer tenantId; private Integer tenantId;

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

@@ -69,7 +69,7 @@ public class ShopFlashSaleActivity implements Serializable {
@Schema(description = "库存") @Schema(description = "库存")
private Integer stock; private Integer stock;
@Schema(description = "展示类型0普通用户1新用户") @Schema(description = "展示类型0普通用户1新用户 2老用户")
private Integer displayType; private Integer displayType;
@Schema(description = "备注") @Schema(description = "备注")

View File

@@ -1,12 +1,7 @@
package com.gxwebsoft.shop.mapper; package com.gxwebsoft.shop.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.gxwebsoft.shop.entity.ShopGoodsProfit; import com.gxwebsoft.shop.entity.ShopGoodsProfit;
import com.gxwebsoft.shop.param.ShopGoodsProfitParam;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/** /**
* 商品分润设定Mapper * 商品分润设定Mapper
@@ -16,22 +11,4 @@ import java.util.List;
*/ */
public interface ShopGoodsProfitMapper extends BaseMapper<ShopGoodsProfit> { public interface ShopGoodsProfitMapper extends BaseMapper<ShopGoodsProfit> {
/**
* 分页查询
*
* @param page 分页对象
* @param param 查询参数
* @return List<ShopGoodsProfit>
*/
List<ShopGoodsProfit> selectPageRel(@Param("page") IPage<ShopGoodsProfit> page,
@Param("param") ShopGoodsProfitParam param);
/**
* 查询全部
*
* @param param 查询参数
* @return List<User>
*/
List<ShopGoodsProfit> selectListRel(@Param("param") ShopGoodsProfitParam 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 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 LEFT JOIN shop_order e ON a.order_no = e.order_no
<where> <where>
a.deleted = 0
<if test="param.id != null"> <if test="param.id != null">
AND a.id = #{param.id} AND a.id = #{param.id}
</if> </if>

View File

@@ -2,62 +2,4 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!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 namespace="com.gxwebsoft.shop.mapper.ShopGoodsProfitMapper">
<!-- 关联查询sql -->
<sql id="selectSql">
SELECT a.*
FROM shop_goods_profit a
<where>
<if test="param.id != null">
AND a.id = #{param.id}
</if>
<if test="param.type != null">
AND a.type = #{param.type}
</if>
<if test="param.goodsId != null">
AND a.goods_id = #{param.goodsId}
</if>
<if test="param.userId != null">
AND a.user_id = #{param.userId}
</if>
<if test="param.profit != null">
AND a.profit = #{param.profit}
</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.ShopGoodsProfit">
<include refid="selectSql"></include>
</select>
<!-- 查询全部 -->
<select id="selectListRel" resultType="com.gxwebsoft.shop.entity.ShopGoodsProfit">
<include refid="selectSql"></include>
</select>
</mapper> </mapper>

View File

@@ -1,13 +1,7 @@
package com.gxwebsoft.shop.param; package com.gxwebsoft.shop.param;
import java.math.BigDecimal;
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.Data;
import lombok.EqualsAndHashCode;
/** /**
* 商品分润设定查询参数 * 商品分润设定查询参数
@@ -16,46 +10,12 @@ import lombok.EqualsAndHashCode;
* @since 2026-05-20 14:33:00 * @since 2026-05-20 14:33:00
*/ */
@Data @Data
@EqualsAndHashCode(callSuper = false) public class ShopGoodsProfitParam {
@JsonInclude(JsonInclude.Include.NON_NULL)
@Schema(name = "ShopGoodsProfitParam对象", description = "商品分润设定查询参数")
public class ShopGoodsProfitParam extends BaseParam {
private static final long serialVersionUID = 1L;
@Schema(description = "主键ID")
@QueryField(type = QueryType.EQ)
private Integer id;
@Schema(description = "类型 1-股东分红 2-其他") @Schema(description = "类型 1-股东分红 2-其他")
@QueryField(type = QueryType.EQ)
private Integer type; private Integer type;
@Schema(description = "商品ID") @Schema(description = "商品ID")
@QueryField(type = QueryType.EQ)
private Integer goodsId; private Integer goodsId;
@Schema(description = "用户ID")
@QueryField(type = QueryType.EQ)
private Integer userId;
@Schema(description = "分佣比例 百分比")
@QueryField(type = QueryType.EQ)
private BigDecimal profit;
@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

@@ -67,6 +67,14 @@ public interface ShopDealerUserService extends IService<ShopDealerUser> {
*/ */
Boolean settlementBatch(ShopDealerSettlementDto dto); Boolean settlementBatch(ShopDealerSettlementDto dto);
/**
* 订单分红变更冻结账户
* @param dto
* @return
*/
Boolean orderProfit(ShopDealerSettlementDto dto);
/** /**
* 开启/关闭分销商用户核销权限 * 开启/关闭分销商用户核销权限
* @param id * @param id

View File

@@ -1,9 +1,9 @@
package com.gxwebsoft.shop.service; package com.gxwebsoft.shop.service;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import com.gxwebsoft.common.core.web.PageResult; import com.gxwebsoft.shop.dto.ShopGoodsProfitUpdateDto;
import com.gxwebsoft.shop.entity.ShopGoodsProfit; import com.gxwebsoft.shop.entity.ShopGoodsProfit;
import com.gxwebsoft.shop.param.ShopGoodsProfitParam; import com.gxwebsoft.shop.vo.ShopGoodsProfitVO;
import java.util.List; import java.util.List;
@@ -16,27 +16,26 @@ import java.util.List;
public interface ShopGoodsProfitService extends IService<ShopGoodsProfit> { public interface ShopGoodsProfitService extends IService<ShopGoodsProfit> {
/** /**
* 分页关联查询 * 通过商品、类型查询分润信息
* * @param goodsId
* @param param 查询参数 * @param type
* @return PageResult<ShopGoodsProfit> * @return
*/ */
PageResult<ShopGoodsProfit> pageRel(ShopGoodsProfitParam param); List<ShopGoodsProfitVO> getByGoodsId(Integer goodsId, Integer type);
/** /**
* 关联查询全部 * 查询启用状态的商品分润信息
* * @param goodsIdList 商品ID集合
* @param param 查询参数 * @param type 分润类型
* @return List<ShopGoodsProfit> * @return
*/ */
List<ShopGoodsProfit> listRel(ShopGoodsProfitParam param); List<ShopGoodsProfitVO> getGoodsProfit(List<Integer> goodsIdList, Integer type);
/** /**
* 根据id查询 * 根据商品ID修改商品分润设定
* * @param updateDto
* @param id 主键ID * @return
* @return ShopGoodsProfit
*/ */
ShopGoodsProfit getByIdRel(Integer id); Boolean updateByGoodsId(ShopGoodsProfitUpdateDto updateDto);
} }

View File

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

View File

@@ -14,6 +14,7 @@ import lombok.AllArgsConstructor;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -38,8 +39,12 @@ public class ShopActiveImageServiceImpl extends ServiceImpl<ShopActiveImageMappe
if(CollectionUtils.isNotEmpty(list)){ if(CollectionUtils.isNotEmpty(list)){
List<Integer> goodsIdList = list.stream().filter(shopActiveImage -> shopActiveImage.getGoodsId() != null).map(ShopActiveImage::getGoodsId) List<Integer> goodsIdList = list.stream().filter(shopActiveImage -> shopActiveImage.getGoodsId() != null).map(ShopActiveImage::getGoodsId)
.distinct().collect(Collectors.toList()); .distinct().collect(Collectors.toList());
List<ShopGoods> shopGoodsList = shopGoodsMapper.selectBatchIds(goodsIdList); List<ShopGoods> shopGoodsList = new ArrayList<>();
if(CollectionUtils.isNotEmpty(goodsIdList)){
shopGoodsList = shopGoodsMapper.selectBatchIds(goodsIdList);
}
List<ShopGoods> finalShopGoodsList = shopGoodsList;
list.forEach(shopActiveImage -> { list.forEach(shopActiveImage -> {
if(!StringUtils.isEmpty(shopActiveImage.getImgUrl())){ if(!StringUtils.isEmpty(shopActiveImage.getImgUrl())){
shopActiveImage.setImgUrlList(Arrays.asList(shopActiveImage.getImgUrl().split(","))); shopActiveImage.setImgUrlList(Arrays.asList(shopActiveImage.getImgUrl().split(",")));
@@ -47,7 +52,7 @@ public class ShopActiveImageServiceImpl extends ServiceImpl<ShopActiveImageMappe
//回显商品名称 //回显商品名称
if(shopActiveImage.getGoodsId() != null){ if(shopActiveImage.getGoodsId() != null){
ShopGoods shopGoods = shopGoodsList.stream().filter(goods -> shopActiveImage.getGoodsId().equals(goods.getGoodsId())).findFirst().orElse(null); ShopGoods shopGoods = finalShopGoodsList.stream().filter(goods -> shopActiveImage.getGoodsId().equals(goods.getGoodsId())).findFirst().orElse(null);
if(shopGoods != null){ if(shopGoods != null){
shopActiveImage.setGoodsName(shopGoods.getName()); shopActiveImage.setGoodsName(shopGoods.getName());
} }

View File

@@ -210,58 +210,67 @@ public class ShopDealerUserServiceImpl extends ServiceImpl<ShopDealerUserMapper,
List<Integer> userIdList = dealerCapitalList.stream().map(ShopDealerCapital::getUserId).distinct().collect(Collectors.toList()); List<Integer> userIdList = dealerCapitalList.stream().map(ShopDealerCapital::getUserId).distinct().collect(Collectors.toList());
List<ShopDealerUser> shopDealerUserList = lambdaQuery().in(ShopDealerUser::getUserId, userIdList).list(); List<ShopDealerUser> shopDealerUserList = lambdaQuery().in(ShopDealerUser::getUserId, userIdList).list();
List<ShopDealerCapital> updateCapitalList = new ArrayList<>();
List<ShopDealerCapital> newCapitalList = new ArrayList<>();
Map<Integer, List<ShopDealerCapital>> userCapitalMap = dealerCapitalList.stream().collect(Collectors.groupingBy(ShopDealerCapital::getUserId)); Map<Integer, List<ShopDealerCapital>> userCapitalMap = dealerCapitalList.stream().collect(Collectors.groupingBy(ShopDealerCapital::getUserId));
userCapitalMap.forEach((k, value) ->{ userCapitalMap.forEach((k, value) ->{
//5.4 查询是否存在待解冻订单数据 //5.4 查询是否存在待解冻订单数据
ShopDealerCapital userCapital = value.stream().filter(capital -> ShopDealerTypeEnum.FREEZE_ACCOUNT.getCode().equals(capital.getType()) && capital.getPaymentFlag() != null List<ShopDealerCapital> capitalList = value.stream().filter(capital -> ShopDealerTypeEnum.FREEZE_ACCOUNT.getCode().equals(capital.getType()) && capital.getPaymentFlag() != null
&& capital.getPaymentFlag() == 0).findFirst().orElse(null); && capital.getPaymentFlag() == 0).collect(Collectors.toList());
if(userCapital != null){ if(CollectionUtils.isNotEmpty(capitalList)){
ShopDealerUser dealerUser = shopDealerUserList.stream().filter(shopDealerUser -> k.equals(shopDealerUser.getUserId())).findFirst().orElse(null);
//5.5 查询此订单是否已结算 //5.6 判断分销账户分销金额是否大于解冻金额
ShopDealerCapital alreadyCapital = value.stream().filter(capital -> ShopDealerTypeEnum.DEFROST.getCode().equals(capital.getType())).findFirst().orElse(null); BigDecimal freezeMoney = capitalList.stream().map(ShopDealerCapital::getFreezeMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
if(alreadyCapital == null){ if(dealerUser != null && dealerUser.getFreezeMoney().compareTo(freezeMoney) >= 0){
ShopDealerUser dealerUser = shopDealerUserList.stream().filter(shopDealerUser -> k.equals(shopDealerUser.getUserId())).findFirst().orElse(null); //5.7 账户解冻金额、可提现增加金额
dealerUser.setFreezeMoney(dealerUser.getFreezeMoney().subtract(freezeMoney));
dealerUser.setMoney(dealerUser.getMoney().add(freezeMoney));
baseMapper.updateById(dealerUser);
//5.6 判断分销账户分销金额是否大于解冻金额 //5.8 生成流水
BigDecimal freezeMoney = userCapital.getFreezeMoney(); ShopDealerCapital dealerCapital = new ShopDealerCapital();
if(dealerUser != null && dealerUser.getFreezeMoney().compareTo(freezeMoney) >= 0){ String no = orderNoUtils.generate("C");
//5.7 账户解冻金额、可提现增加金额 dealerCapital.setNo(no);
dealerUser.setFreezeMoney(dealerUser.getFreezeMoney().subtract(freezeMoney)); dealerCapital.setUserId(k);
dealerUser.setMoney(dealerUser.getMoney().add(freezeMoney)); dealerCapital.setType(typeEnum.getCode());
baseMapper.updateById(dealerUser); dealerCapital.setOrderNo(entity.getOrderNo());
dealerCapital.setFlowType(updateEnum.getType());
//5.8 生成流水 dealerCapital.setFreezeMoney(freezeMoney.negate());
ShopDealerCapital dealerCapital = new ShopDealerCapital(); dealerCapital.setFreezeMoneyAfter(dealerUser.getFreezeMoney());
String no = orderNoUtils.generate("C"); dealerCapital.setMoney(freezeMoney);
dealerCapital.setNo(no); dealerCapital.setMoneyAfter(dealerUser.getMoney());
dealerCapital.setUserId(k); dealerCapital.setComments(updateEnum.getDescription());
dealerCapital.setType(typeEnum.getCode()); dealerCapital.setToUserId(entity.getOrderUserId());
dealerCapital.setOrderNo(entity.getOrderNo()); dealerCapital.setPaymentFlag(1);
dealerCapital.setFlowType(updateEnum.getType()); dealerCapital.setTenantId(TENANT_ID);
dealerCapital.setFreezeMoney(freezeMoney.negate()); dealerCapital.setCreateTime(now);
dealerCapital.setFreezeMoneyAfter(dealerUser.getFreezeMoney()); User loginUser = LoginUserUtil.getLoginUser();
dealerCapital.setMoney(freezeMoney); if (loginUser != null) {
dealerCapital.setMoneyAfter(dealerUser.getMoney()); dealerCapital.setCreator(loginUser.getUserId());
dealerCapital.setComments(updateEnum.getDescription());
dealerCapital.setToUserId(entity.getOrderUserId());
dealerCapital.setPaymentFlag(1);
dealerCapital.setTenantId(TENANT_ID);
dealerCapital.setCreateTime(now);
User loginUser = LoginUserUtil.getLoginUser();
if (loginUser != null) {
dealerCapital.setCreator(loginUser.getUserId());
}
shopDealerCapitalMapper.insert(dealerCapital);
userCapital.setPaymentFlag(1);
} }
} newCapitalList.add(dealerCapital);
//5.6 更新冻结流水为已结算状态 capitalList.forEach(capital -> {
userCapital.setUpdateTime(now); capital.setPaymentFlag(1);
shopDealerCapitalMapper.updateById(userCapital); capital.setUpdateTime(now);
});
updateCapitalList.addAll(capitalList);
}
} }
}); });
//6.批量修改原待结算解冻订单为结算状态
if(CollectionUtils.isNotEmpty(updateCapitalList)){
shopDealerCapitalService.updateBatchById(updateCapitalList);
}
//7.批量新增结算记录
if(CollectionUtils.isNotEmpty(newCapitalList)){
shopDealerCapitalService.saveBatch(newCapitalList);
}
}else { }else {
log.error("未查询到待解冻订单信息:" + entity.getOrderNo()); log.error("未查询到待解冻订单信息:" + entity.getOrderNo());
} }
@@ -423,6 +432,52 @@ public class ShopDealerUserServiceImpl extends ServiceImpl<ShopDealerUserMapper,
return Boolean.TRUE; return Boolean.TRUE;
} }
@Override
public Boolean orderProfit(ShopDealerSettlementDto entity) {
if(entity != null && CollectionUtils.isNotEmpty(entity.getItemList())){
LocalDateTime now = LocalDateTime.now();
List<ShopDealerSettlementItemDto> itemList = entity.getItemList();
List<Integer> userIdList = itemList.stream().map(ShopDealerSettlementItemDto::getUserId).distinct().collect(Collectors.toList());
List<ShopDealerUser> shopDealerUserList = baseMapper.selectList(new LambdaQueryWrapper<ShopDealerUser>().select(ShopDealerUser::getId, ShopDealerUser::getUserId,
ShopDealerUser::getMoney, ShopDealerUser::getTotalMoney, ShopDealerUser::getFreezeMoney).in(ShopDealerUser::getUserId, userIdList));
List<ShopDealerUser> updateDealerUserList = new ArrayList<>();
List<ShopDealerCapital> capitalList = new ArrayList<>();
itemList.forEach(item ->{
ShopDealerUser dealerUser = shopDealerUserList.stream().filter(shopDealerUser -> item.getUserId().equals(shopDealerUser.getUserId())).findFirst().orElse(null);
if(dealerUser != null){
dealerUser.setFreezeMoney(dealerUser.getFreezeMoney().add(item.getMoney()));
dealerUser.setTotalMoney(dealerUser.getTotalMoney().add(item.getMoney()));
dealerUser.setUpdateTime(now);
updateDealerUserList.add(dealerUser);
ShopDealerCapital capital = BeanUtil.toBean(entity, ShopDealerCapital.class);
capital.setNo(item.getNo());
capital.setType(ShopDealerTypeEnum.FREEZE_ACCOUNT.getCode());
capital.setFlowType(ShopDealerCapitalUpdateEnum.DIVIDEND_INCOME.getType());
capital.setComments(ShopDealerCapitalUpdateEnum.DIVIDEND_INCOME.getDescription());
capital.setUserId(item.getUserId());
capital.setFreezeMoney(item.getMoney());
capital.setFreezeMoneyAfter(dealerUser.getFreezeMoney());
capital.setMoneyAfter(dealerUser.getMoney());
capital.setCreateTime(now);
capitalList.add(capital);
}
});
if(CollectionUtils.isNotEmpty(updateDealerUserList)){
updateBatchById(updateDealerUserList);
}
if(CollectionUtils.isNotEmpty(capitalList)){
shopDealerCapitalService.saveBatch(capitalList);
}
}
return Boolean.TRUE;
}
@Override @Override
public Boolean verifyEnable(Integer id) { public Boolean verifyEnable(Integer id) {
ShopDealerUser dealerUser = baseMapper.selectById(id); ShopDealerUser dealerUser = baseMapper.selectById(id);

View File

@@ -100,13 +100,14 @@ public class ShopFlashSaleActivityServiceImpl extends ServiceImpl<ShopFlashSaleA
@Override @Override
public List<ShopFlashSaleActivityVO> getMyActive(Integer tenantId, Integer popFlag) { public List<ShopFlashSaleActivityVO> getMyActive(Integer tenantId, Integer popFlag) {
List<ShopFlashSaleActivityVO> resultVOList = new ArrayList<>(); List<ShopFlashSaleActivityVO> resultVOList = new ArrayList<>();
//1.判断当前登录用户
User loginUser = LoginUserUtil.getLoginUser(); User loginUser = LoginUserUtil.getLoginUser();
if(loginUser == null){ if(loginUser == null){
throw new BusinessException(GlobalErrorCodeConstants.UNAUTHORIZED.getMsg()); throw new BusinessException(GlobalErrorCodeConstants.UNAUTHORIZED.getMsg());
} }
Boolean newUser = true; Boolean newUser = true;
//判断是否为新用户【只要未成功下单都判定为新用户】 //2.判断是否为新用户【只要未成功下单都判定为新用户】
LambdaQueryWrapper<ShopOrder> shopOrderLambdaQueryWrapper = new LambdaQueryWrapper<ShopOrder>().eq(ShopOrder::getUserId, loginUser.getUserId()).eq(ShopOrder::getPayStatus, 1) LambdaQueryWrapper<ShopOrder> shopOrderLambdaQueryWrapper = new LambdaQueryWrapper<ShopOrder>().eq(ShopOrder::getUserId, loginUser.getUserId()).eq(ShopOrder::getPayStatus, 1)
.in(ShopOrder::getOrderStatus, Arrays.asList(0, 1)); .in(ShopOrder::getOrderStatus, Arrays.asList(0, 1));
List<ShopOrder> shopOrderList = shopOrderMapper.selectList(shopOrderLambdaQueryWrapper); List<ShopOrder> shopOrderList = shopOrderMapper.selectList(shopOrderLambdaQueryWrapper);
@@ -114,55 +115,65 @@ public class ShopFlashSaleActivityServiceImpl extends ServiceImpl<ShopFlashSaleA
newUser = false; newUser = false;
} }
//查询满足条件的活动数据 //3.查询满足条件的活动数据
LambdaQueryChainWrapper<ShopFlashSaleActivity> activityWrapper = lambdaQuery().eq(ShopFlashSaleActivity::getStatus, 0).gt(ShopFlashSaleActivity::getStock, 0).eq(ShopFlashSaleActivity::getTenantId, tenantId) LambdaQueryChainWrapper<ShopFlashSaleActivity> activityWrapper = lambdaQuery().eq(ShopFlashSaleActivity::getStatus, 0).gt(ShopFlashSaleActivity::getStock, 0)
.apply("NOW() BETWEEN start_time AND end_time"); .eq(ShopFlashSaleActivity::getTenantId, tenantId).apply("NOW() BETWEEN start_time AND end_time");
if(popFlag != null){ if(popFlag != null){
activityWrapper.eq(ShopFlashSaleActivity::getPopFlag, popFlag); activityWrapper.eq(ShopFlashSaleActivity::getPopFlag, popFlag);
} }
activityWrapper.orderByAsc(ShopFlashSaleActivity::getSortNumber);
List<ShopFlashSaleActivity> activityList = activityWrapper.list();
//4.查询老用户已下单爆款活动订单数据
Map<Integer, Integer> activityMap = new HashMap<>(); Map<Integer, Integer> activityMap = new HashMap<>();
if(!newUser){ if(!newUser){
//查询当前用户是否有下过秒杀活动订单数据【判断下单数量是否超过限制】 //查询当前用户是否有下过秒杀活动订单数据【判断下单数量是否超过限制】
List<Integer> activityIdList = activityWrapper.list().stream().map(ShopFlashSaleActivity::getId).collect(Collectors.toList()); List<Integer> activityIdList = activityList.stream().map(ShopFlashSaleActivity::getId).collect(Collectors.toList());
if(CollectionUtils.isNotEmpty(activityIdList)){ if(CollectionUtils.isNotEmpty(activityIdList)){
LambdaQueryWrapper<ShopOrder> shopOrderWrapper = new LambdaQueryWrapper<ShopOrder>().select(ShopOrder::getOrderId, ShopOrder::getActivityId, ShopOrder::getTotalNum) LambdaQueryWrapper<ShopOrder> shopOrderWrapper = new LambdaQueryWrapper<ShopOrder>().select(ShopOrder::getOrderId, ShopOrder::getActivityId, ShopOrder::getTotalNum)
.eq(ShopOrder::getUserId, loginUser.getUserId()).in(ShopOrder::getActivityId, activityIdList).in(ShopOrder::getOrderStatus, Arrays.asList(0, 1)); .eq(ShopOrder::getUserId, loginUser.getUserId()).in(ShopOrder::getActivityId, activityIdList).in(ShopOrder::getOrderStatus, Arrays.asList(0, 1));
activityMap = shopOrderMapper.selectList(shopOrderWrapper).stream().collect(Collectors.groupingBy(ShopOrder::getActivityId, Collectors.summingInt(ShopOrder::getTotalNum))); activityMap = shopOrderMapper.selectList(shopOrderWrapper).stream().collect(Collectors.groupingBy(ShopOrder::getActivityId, Collectors.summingInt(ShopOrder::getTotalNum)));
} }
activityWrapper.eq(ShopFlashSaleActivity::getDisplayType, 0);
} }
activityWrapper.orderByAsc(ShopFlashSaleActivity::getSortNumber);
List<ShopFlashSaleActivity> activityList = activityWrapper.list();
//5.存在活动爆款,则判断用户购买能力
if(CollectionUtils.isNotEmpty(activityList)){ if(CollectionUtils.isNotEmpty(activityList)){
resultVOList = BeanUtil.copyToList(activityList, ShopFlashSaleActivityVO.class); resultVOList = BeanUtil.copyToList(activityList, ShopFlashSaleActivityVO.class);
List<Integer> goodsIdList = resultVOList.stream().map(ShopFlashSaleActivityVO::getGoodsId).distinct().collect(Collectors.toList()); List<Integer> goodsIdList = resultVOList.stream().map(ShopFlashSaleActivityVO::getGoodsId).distinct().collect(Collectors.toList());
List<ShopGoods> shopGoods = shopGoodsMapper.selectBatchIds(goodsIdList); List<ShopGoods> shopGoods = shopGoodsMapper.selectBatchIds(goodsIdList);
resultVOList.forEach(activity -> { for(ShopFlashSaleActivityVO activityVO : resultVOList){
ShopGoods shopGood = shopGoods.stream().filter(goods -> activity.getGoodsId().equals(goods.getGoodsId())).findFirst().orElse(null); if(newUser){
if(shopGood != null){ if(activityVO.getDisplayType() == 2){
activity.setGoodsPrice(shopGood.getPrice()); activityVO.setEnable(false);
activity.setGoodsTotalPrice(shopGood.getPrice().multiply(new BigDecimal(activity.getNum()))); activityVO.setEnableMsg("当前商品仅限老用户购买!");
activity.setGoodsName(shopGood.getName()); }
activity.setImage(shopGood.getImage()); }else {
activity.setUnitName(shopGood.getUnitName()); if(activityVO.getDisplayType() == 1){
} activityVO.setEnable(false);
}); activityVO.setEnableMsg("当前商品仅限新用户购买!");
} }
//过滤超下单数量活动 if(activityVO.getEnable()){
if(!activityMap.isEmpty()){ //超下单数量活动不可选
Iterator<ShopFlashSaleActivityVO> iterator = resultVOList.iterator(); Integer orderTotalNum = activityMap.get(activityVO.getId());
while (iterator.hasNext()){ if(orderTotalNum != null && orderTotalNum >= activityVO.getSaleLimit()){
ShopFlashSaleActivityVO vo = iterator.next(); activityVO.setEnable(false);
Integer orderTotalNum = activityMap.get(vo.getId()); activityVO.setEnableMsg("当前商品您购买次数已达上限!");
if(orderTotalNum != null && orderTotalNum >= vo.getSaleLimit()){ }
iterator.remove(); }
}
//5.2 回显商品信息
ShopGoods shopGood = shopGoods.stream().filter(goods -> activityVO.getGoodsId().equals(goods.getGoodsId())).findFirst().orElse(null);
if(shopGood != null){
activityVO.setGoodsPrice(shopGood.getPrice());
activityVO.setGoodsTotalPrice(shopGood.getPrice().multiply(new BigDecimal(activityVO.getNum())));
activityVO.setGoodsName(shopGood.getName());
activityVO.setImage(shopGood.getImage());
activityVO.setUnitName(shopGood.getUnitName());
} }
} }
} }
return resultVOList; return resultVOList;
} }

View File

@@ -1,16 +1,33 @@
package com.gxwebsoft.shop.service.impl; package com.gxwebsoft.shop.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 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.ShopGoodsProfitUpdateDto;
import com.gxwebsoft.shop.dto.ShopGoodsProfitUpdateItemDto;
import com.gxwebsoft.shop.entity.ShopDealerUser;
import com.gxwebsoft.shop.entity.ShopGoods;
import com.gxwebsoft.shop.entity.ShopGoodsProfit;
import com.gxwebsoft.shop.mapper.ShopDealerUserMapper;
import com.gxwebsoft.shop.mapper.ShopGoodsMapper;
import com.gxwebsoft.shop.mapper.ShopGoodsProfitMapper; import com.gxwebsoft.shop.mapper.ShopGoodsProfitMapper;
import com.gxwebsoft.shop.service.ShopGoodsProfitService; import com.gxwebsoft.shop.service.ShopGoodsProfitService;
import com.gxwebsoft.shop.entity.ShopGoodsProfit; import com.gxwebsoft.shop.vo.ShopGoodsProfitVO;
import com.gxwebsoft.shop.param.ShopGoodsProfitParam;
import com.gxwebsoft.common.core.web.PageParam;
import com.gxwebsoft.common.core.web.PageResult;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/** /**
* 商品分润设定Service实现 * 商品分润设定Service实现
@@ -22,28 +39,101 @@ import java.util.List;
@AllArgsConstructor @AllArgsConstructor
public class ShopGoodsProfitServiceImpl extends ServiceImpl<ShopGoodsProfitMapper, ShopGoodsProfit> implements ShopGoodsProfitService { public class ShopGoodsProfitServiceImpl extends ServiceImpl<ShopGoodsProfitMapper, ShopGoodsProfit> implements ShopGoodsProfitService {
private ShopDealerUserMapper shopDealerUserMapper;
private ShopGoodsMapper shopGoodsMapper;
@Override @Override
public PageResult<ShopGoodsProfit> pageRel(ShopGoodsProfitParam param) { public List<ShopGoodsProfitVO> getByGoodsId(Integer goodsId, Integer type) {
PageParam<ShopGoodsProfit, ShopGoodsProfitParam> page = new PageParam<>(param); List<ShopGoodsProfit> list = lambdaQuery().select(ShopGoodsProfit::getId, ShopGoodsProfit::getGoodsId, ShopGoodsProfit::getUserId, ShopGoodsProfit::getProfit,
page.setDefaultOrder("sort_number asc, create_time desc"); ShopGoodsProfit::getStatus).eq(ShopGoodsProfit::getGoodsId, goodsId).eq(ShopGoodsProfit::getType, type).list();
List<ShopGoodsProfit> list = baseMapper.selectPageRel(page, param);
return new PageResult<>(list, page.getTotal()); if(CollectionUtils.isNotEmpty(list)){
List<Integer> userIdList = list.stream().map(ShopGoodsProfit::getUserId).distinct().collect(Collectors.toList());
List<ShopDealerUser> shopDealerUserList = shopDealerUserMapper.selectList(new LambdaQueryWrapper<ShopDealerUser>().in(ShopDealerUser::getUserId, userIdList));
List<ShopGoodsProfitVO> shopGoodsProfitVOS = BeanUtil.copyToList(list, ShopGoodsProfitVO.class);
for(ShopGoodsProfitVO shopGoodsProfitVO : shopGoodsProfitVOS){
shopDealerUserList.stream().filter(shopDealerUser -> shopGoodsProfitVO.getUserId().equals(shopDealerUser.getUserId())).findFirst()
.ifPresent(shopDealerUser -> shopGoodsProfitVO.setUserName(shopDealerUser.getRealName()));
}
return shopGoodsProfitVOS;
}
return new ArrayList<>();
} }
@Override @Override
public List<ShopGoodsProfit> listRel(ShopGoodsProfitParam param) { public List<ShopGoodsProfitVO> getGoodsProfit(List<Integer> goodsIdList, Integer type) {
List<ShopGoodsProfit> list = baseMapper.selectListRel(param); List<ShopGoodsProfit> profitList = lambdaQuery().select(ShopGoodsProfit::getId, ShopGoodsProfit::getGoodsId, ShopGoodsProfit::getUserId, ShopGoodsProfit::getProfit,
// 排序 ShopGoodsProfit::getStatus).in(ShopGoodsProfit::getGoodsId, goodsIdList).eq(ShopGoodsProfit::getType, type).eq(ShopGoodsProfit::getStatus, 1).list();
PageParam<ShopGoodsProfit, ShopGoodsProfitParam> page = new PageParam<>(); if(CollectionUtils.isNotEmpty(profitList)){
page.setDefaultOrder("sort_number asc, create_time desc"); return BeanUtil.copyToList(profitList, ShopGoodsProfitVO.class);
return page.sortRecords(list); }
return new ArrayList<>();
} }
@Override @Override
public ShopGoodsProfit getByIdRel(Integer id) { public Boolean updateByGoodsId(ShopGoodsProfitUpdateDto entity) {
ShopGoodsProfitParam param = new ShopGoodsProfitParam(); User loginUser = LoginUserUtil.getLoginUser();
param.setId(id); if(loginUser == null){
return param.getOne(baseMapper.selectListRel(param)); throw new BusinessException(GlobalErrorCodeConstants.UNAUTHORIZED.getMsg());
}
List<ShopGoodsProfitUpdateItemDto> itemList = entity.getItemList();
LocalDateTime now = LocalDateTime.now();
if(CollectionUtils.isNotEmpty(itemList)){
//1.先检查传入的分润总和是否超过100
BigDecimal profitSum = itemList.stream().map(ShopGoodsProfitUpdateItemDto::getProfit).reduce(BigDecimal.ZERO, BigDecimal::add);
if(profitSum.compareTo(BigDecimal.valueOf(100)) > 0){
throw new BusinessException("股东分红比例总和不能超过100%");
}
//2.检查分润对象是否有重复
Map<Integer, List<ShopGoodsProfitUpdateItemDto>> userMap = itemList.stream().collect(Collectors.groupingBy(ShopGoodsProfitUpdateItemDto::getUserId)).entrySet().stream()
.filter(entry -> entry.getValue().size() > 1).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
if(!userMap.isEmpty()){
String userIds = String.join(",", userMap.keySet().stream().map(String::valueOf).toList());
throw new BusinessException("用户:【" + userIds + "】存在多条分红数据,请修改后重新提交!");
}
//3.查询商品原有分润数据并做超100%管控
ShopGoods shopGoods = shopGoodsMapper.selectById(entity.getGoodsId());
if(shopGoods == null){
throw new BusinessException(GlobalErrorCodeConstants.NOT_FOUND.getMsg());
}
BigDecimal goodsOriginalProfit = shopGoods.getVerifyRate().add(shopGoods.getVerifyParentRate());
if(shopGoods.getCommissionType() == 20){
goodsOriginalProfit = goodsOriginalProfit.add(shopGoods.getFirstMoney()).add(shopGoods.getSecondMoney()).add(shopGoods.getFirstDividend())
.add(shopGoods.getSecondDividend()).add(shopGoods.getDeliveryMoney());
}
if(profitSum.add(goodsOriginalProfit).compareTo(BigDecimal.valueOf(100)) > 0){
throw new BusinessException("股东分红比例与商品原有分销比例加总不能超过100");
}
//4.查询有分润数据并删除
removeByGoodsId(entity.getGoodsId(), entity.getType(), loginUser.getUserId(), now);
//5.批量新增分润数据
List<ShopGoodsProfit> shopGoodsProfits = BeanUtil.copyToList(itemList, ShopGoodsProfit.class);
shopGoodsProfits.forEach(shopGoodsProfit -> {
shopGoodsProfit.setType(entity.getType());
shopGoodsProfit.setGoodsId(entity.getGoodsId());
shopGoodsProfit.setTenantId(loginUser.getTenantId());
shopGoodsProfit.setCreator(loginUser.getUserId());
shopGoodsProfit.setCreateTime(now);
});
saveBatch(shopGoodsProfits);
}else {
removeByGoodsId(entity.getGoodsId(), entity.getType(), loginUser.getUserId(), now);
}
return Boolean.TRUE;
}
private void removeByGoodsId(Integer goodsId, Integer type, Integer userId, LocalDateTime date){
LambdaUpdateWrapper<ShopGoodsProfit> updateWrapper = new LambdaUpdateWrapper<ShopGoodsProfit>().eq(ShopGoodsProfit::getGoodsId, goodsId).eq(ShopGoodsProfit::getType, type)
.set(ShopGoodsProfit::getUpdater, userId).set(ShopGoodsProfit::getUpdateTime, date).set(ShopGoodsProfit::getDeleted, 1);
update(updateWrapper);
} }
} }

View File

@@ -65,7 +65,7 @@ public class ShopFlashSaleActivityVO implements Serializable {
@Schema(description = "库存") @Schema(description = "库存")
private Integer stock; private Integer stock;
@Schema(description = "展示类型0普通用户1新用户") @Schema(description = "展示类型0普通用户1新用户 2老用户")
private Integer displayType; private Integer displayType;
@Schema(description = "备注") @Schema(description = "备注")
@@ -77,6 +77,12 @@ public class ShopFlashSaleActivityVO implements Serializable {
@Schema(description = "是否弹窗 0-否 1-是") @Schema(description = "是否弹窗 0-否 1-是")
private Integer popFlag; private Integer popFlag;
@Schema(description = "是否可选")
private Boolean enable = true;
@Schema(description = "不可购买原因!")
private String enableMsg;
@Schema(description = "租户id") @Schema(description = "租户id")
private Integer tenantId; private Integer tenantId;

View File

@@ -0,0 +1,35 @@
package com.gxwebsoft.shop.vo;
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 ShopGoodsProfitVO {
@Schema(description = "主键ID")
private Integer id;
@Schema(description = "商品ID")
private Integer goodsId;
@Schema(description = "用户ID")
private Integer userId;
@Schema(description = "用户名称")
private String userName;
@Schema(description = "分佣比例 百分比")
private BigDecimal profit;
@Schema(description = "开启状态 0-未开启 1-开启")
private Integer status;
}