IProfitSharing
This commit is contained in:
parent
255ea42f81
commit
3f493b0d81
@ -6,6 +6,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
@MapperScan(basePackages = "com.ycwl.basic.mapper")
|
||||
@MapperScan(basePackages = "com.ycwl.basic.*.mapper")
|
||||
public class Application {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
@ -0,0 +1,84 @@
|
||||
package com.ycwl.basic.profitsharing.biz;
|
||||
|
||||
import com.ycwl.basic.profitsharing.entity.ProfitSharingConfig;
|
||||
import com.ycwl.basic.profitsharing.entity.ProfitSharingRecord;
|
||||
import com.ycwl.basic.profitsharing.entity.ProfitSharingUser;
|
||||
import com.ycwl.basic.profitsharing.mapper.ProfitSharingConfigMapper;
|
||||
import com.ycwl.basic.profitsharing.mapper.ProfitSharingRecordMapper;
|
||||
import com.ycwl.basic.profitsharing.repository.ProfitSharingRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class ProfitSharingBiz {
|
||||
@Autowired
|
||||
private ProfitSharingRepository repository;
|
||||
|
||||
@Autowired
|
||||
private ProfitSharingRecordMapper recordMapper;
|
||||
|
||||
public void processProfitSharing(Long scenicId, Long orderId, BigDecimal amount) {
|
||||
ProfitSharingConfig config = repository.getScenicConfig(scenicId);
|
||||
if (config == null || config.getUsers() == null || config.getUsers().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<ProfitSharingRecord> records = new ArrayList<>();
|
||||
BigDecimal totalPercentage = BigDecimal.ZERO;
|
||||
for (ProfitSharingUser user : config.getUsers()) {
|
||||
totalPercentage = totalPercentage.add(user.getRealRate());
|
||||
}
|
||||
if (totalPercentage.compareTo(BigDecimal.valueOf(100)) > 0) {
|
||||
throw new RuntimeException("分账比例总和超过100%");
|
||||
}
|
||||
BigDecimal myPercentage = BigDecimal.valueOf(100).subtract(totalPercentage);
|
||||
|
||||
for (ProfitSharingUser user : config.getUsers()) {
|
||||
BigDecimal userAmount = amount.multiply(user.getRealRate()).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_DOWN);
|
||||
BigDecimal wxAmount = amount.multiply(user.getWxRate()).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_DOWN);
|
||||
BigDecimal manualAmount = userAmount.subtract(wxAmount);
|
||||
ProfitSharingRecord record = new ProfitSharingRecord();
|
||||
record.setScenicId(scenicId);
|
||||
record.setOrderId(orderId);
|
||||
record.setUserId(user.getId());
|
||||
record.setUserName(user.getName());
|
||||
record.setAmount(userAmount);
|
||||
record.setWxAmount(wxAmount);
|
||||
record.setManualAmount(manualAmount);
|
||||
record.setWxRate(user.getWxRate());
|
||||
record.setRealRate(user.getRealRate());
|
||||
record.setOrderAmount(amount);
|
||||
record.setCreateTime(new Date());
|
||||
records.add(record);
|
||||
}
|
||||
BigDecimal remainAmount = amount;
|
||||
for (ProfitSharingRecord record : records) {
|
||||
remainAmount = remainAmount.subtract(record.getAmount());
|
||||
}
|
||||
|
||||
if (remainAmount.compareTo(BigDecimal.ZERO) > 0) {
|
||||
ProfitSharingRecord record = new ProfitSharingRecord();
|
||||
record.setScenicId(scenicId);
|
||||
record.setOrderId(orderId);
|
||||
record.setUserId(0L);
|
||||
record.setUserName("自己");
|
||||
record.setAmount(remainAmount);
|
||||
record.setWxAmount(BigDecimal.ZERO);
|
||||
record.setManualAmount(remainAmount);
|
||||
record.setWxRate(BigDecimal.ZERO);
|
||||
record.setRealRate(myPercentage);
|
||||
record.setOrderAmount(amount);
|
||||
record.setCreateTime(new Date());
|
||||
records.add(record);
|
||||
}
|
||||
|
||||
recordMapper.batchInsert(records);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,108 @@
|
||||
package com.ycwl.basic.profitsharing.controller;
|
||||
|
||||
import com.ycwl.basic.profitsharing.entity.ProfitSharingConfig;
|
||||
import com.ycwl.basic.profitsharing.entity.ProfitSharingUser;
|
||||
import com.ycwl.basic.profitsharing.mapper.ProfitSharingConfigMapper;
|
||||
import com.ycwl.basic.profitsharing.mapper.ProfitSharingUserMapper;
|
||||
import com.ycwl.basic.utils.ApiResponse;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/profitSharingConfig/v1")
|
||||
public class ProfitSharingController {
|
||||
|
||||
@Autowired
|
||||
private ProfitSharingConfigMapper configMapper;
|
||||
@Autowired
|
||||
private ProfitSharingUserMapper userMapper;
|
||||
|
||||
// 增加: 插入新的ProfitSharingConfig记录
|
||||
@PostMapping("/add")
|
||||
public ApiResponse addConfig(@RequestBody ProfitSharingConfig config) {
|
||||
// 检查是否存在相同 scenicId 的配置
|
||||
ProfitSharingConfig existingConfig = configMapper.findByScenicId(config.getScenicId());
|
||||
if (existingConfig != null) {
|
||||
return ApiResponse.fail("该景区已存在配置");
|
||||
}
|
||||
configMapper.insert(config);
|
||||
// 获取生成的 configId
|
||||
Long configId = config.getId();
|
||||
// 插入 users 列表
|
||||
if (config.getUsers() != null) {
|
||||
// 提前检查,避免realRate总和超过100
|
||||
BigDecimal totalPercentage = BigDecimal.ZERO;
|
||||
for (ProfitSharingUser user : config.getUsers()) {
|
||||
totalPercentage = totalPercentage.add(user.getRealRate());
|
||||
}
|
||||
if (totalPercentage.compareTo(BigDecimal.valueOf(100)) > 0) {
|
||||
return ApiResponse.fail("分账比例总和超过100%");
|
||||
}
|
||||
for (ProfitSharingUser user : config.getUsers()) {
|
||||
user.setConfigId(configId);
|
||||
userMapper.insert(user);
|
||||
}
|
||||
}
|
||||
return ApiResponse.success("配置添加成功");
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete/{id}")
|
||||
public ApiResponse deleteConfig(@PathVariable Long id) {
|
||||
configMapper.deleteById(id);
|
||||
return ApiResponse.success("配置删除成功");
|
||||
}
|
||||
|
||||
// 更新: 更新指定ID的ProfitSharingConfig记录
|
||||
@PutMapping("/update")
|
||||
public ApiResponse updateConfig(@RequestBody ProfitSharingConfig config) {
|
||||
// 更新 ProfitSharingConfig 记录
|
||||
configMapper.update(config);
|
||||
// 获取 configId
|
||||
Long configId = config.getId();
|
||||
if (configId == null) {
|
||||
return ApiResponse.fail("configId不能为空");
|
||||
}
|
||||
// 插入新的 users 列表
|
||||
if (config.getUsers() != null) {
|
||||
// 提前检查,避免realRate总和超过100
|
||||
BigDecimal totalPercentage = BigDecimal.ZERO;
|
||||
for (ProfitSharingUser user : config.getUsers()) {
|
||||
totalPercentage = totalPercentage.add(user.getRealRate());
|
||||
}
|
||||
if (totalPercentage.compareTo(BigDecimal.valueOf(100)) > 0) {
|
||||
return ApiResponse.fail("分账比例总和超过100%");
|
||||
}
|
||||
// 删除原有 users 列表
|
||||
userMapper.deleteByConfigId(configId);
|
||||
for (ProfitSharingUser user : config.getUsers()) {
|
||||
user.setConfigId(configId);
|
||||
userMapper.insert(user);
|
||||
}
|
||||
}
|
||||
return ApiResponse.success("配置更新成功");
|
||||
}
|
||||
|
||||
@GetMapping("/findById/{id}")
|
||||
public ApiResponse findById(@PathVariable Long id) {
|
||||
ProfitSharingConfig config = configMapper.findById(id);
|
||||
config.setUsers(userMapper.findByConfigId(id));
|
||||
return ApiResponse.success(config);
|
||||
}
|
||||
|
||||
// 查询: 查询所有记录
|
||||
@GetMapping("/findAll")
|
||||
public ApiResponse findAllConfigs() {
|
||||
List<ProfitSharingConfig> configs = configMapper.findAll();
|
||||
return ApiResponse.success(configs);
|
||||
}
|
||||
|
||||
// 查询: 根据scenicId查询单个记录
|
||||
@GetMapping("/findByScenicId/{scenicId}")
|
||||
public ApiResponse findByScenicId(@PathVariable Long scenicId) {
|
||||
ProfitSharingConfig config = configMapper.findByScenicId(scenicId);
|
||||
return ApiResponse.success(config);
|
||||
}
|
||||
}
|
@ -2,11 +2,16 @@ package com.ycwl.basic.profitsharing.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class ProfitSharingConfig {
|
||||
private boolean enabled;
|
||||
private Long id;
|
||||
private Long scenicId;
|
||||
private List<ProfitSharingUser> profitSharingList;
|
||||
private String name;
|
||||
private String description;
|
||||
private Date createTime;
|
||||
private Date updateTime;
|
||||
private List<ProfitSharingUser> users;
|
||||
}
|
||||
|
@ -0,0 +1,22 @@
|
||||
package com.ycwl.basic.profitsharing.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class ProfitSharingRecord {
|
||||
private Long id;
|
||||
private Long scenicId;
|
||||
private Long orderId;
|
||||
private Long userId;
|
||||
private String userName;
|
||||
private BigDecimal amount;
|
||||
private BigDecimal wxAmount;
|
||||
private BigDecimal manualAmount;
|
||||
private BigDecimal wxRate; // 微信分账比例
|
||||
private BigDecimal realRate; // 实际分账比例
|
||||
private BigDecimal orderAmount; // 订单金额
|
||||
private Date createTime;
|
||||
}
|
@ -1,15 +1,35 @@
|
||||
package com.ycwl.basic.profitsharing.entity;
|
||||
|
||||
import com.ycwl.basic.profitsharing.enums.ProfitSharingUserType;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.ycwl.basic.profitsharing.enums.ProfitSharingWxPayType;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
public class ProfitSharingUser {
|
||||
private ProfitSharingUserType type;
|
||||
private Integer amount;
|
||||
private Long id;
|
||||
private Long configId;
|
||||
private ProfitSharingWxPayType wxPayType;
|
||||
private Map<String, String> wxPayConfig;
|
||||
private String name;
|
||||
private String description;
|
||||
/**
|
||||
* 微信分账比例,单位为%
|
||||
*/
|
||||
private BigDecimal wxRate;
|
||||
/**
|
||||
* 实际分账比例,单位为%
|
||||
*/
|
||||
private BigDecimal realRate;
|
||||
private BigDecimal orderAmount; // 订单金额
|
||||
|
||||
public void setWxPayConfig(String wxPayConfig) {
|
||||
this.wxPayConfig = JSON.parseObject(wxPayConfig, Map.class);
|
||||
}
|
||||
|
||||
public String getWxPayConfig() {
|
||||
return JSON.toJSONString(wxPayConfig);
|
||||
}
|
||||
}
|
@ -1,23 +1,16 @@
|
||||
package com.ycwl.basic.profitsharing.enums;
|
||||
|
||||
public enum ProfitSharingUserType {
|
||||
MERCHANT("MERCHANT_ID", "商户号"),
|
||||
PERSON_SUB("PERSONAL_SUB_OPENID", "子商户个人"),
|
||||
PERSON_PARENT("PERSONAL_OPENID", "父商户个人");
|
||||
|
||||
private final String code;
|
||||
private final String desc;
|
||||
SCENIC("SCENIC", "景区方"),
|
||||
AGENT("AGENT", "代理商方"),
|
||||
PROVIDER("PROVIDER", "技术提供方"),
|
||||
SELF("SELF", "自己"),
|
||||
;
|
||||
|
||||
public final String code;
|
||||
public final String desc;
|
||||
ProfitSharingUserType(String code, String desc) {
|
||||
this.code = code;
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,24 @@
|
||||
package com.ycwl.basic.profitsharing.enums;
|
||||
|
||||
public enum ProfitSharingWxPayType {
|
||||
MERCHANT("MERCHANT_ID", "商户号"),
|
||||
PERSON_SUB("PERSONAL_SUB_OPENID", "子商户个人"),
|
||||
PERSON_PARENT("PERSONAL_OPENID", "父商户个人"),
|
||||
MANUAL("MANUAL", "手动结算");
|
||||
|
||||
private final String code;
|
||||
private final String desc;
|
||||
|
||||
ProfitSharingWxPayType(String code, String desc) {
|
||||
this.code = code;
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package com.ycwl.basic.profitsharing.mapper;
|
||||
|
||||
import com.ycwl.basic.profitsharing.entity.ProfitSharingConfig;
|
||||
import org.apache.ibatis.annotations.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface ProfitSharingConfigMapper {
|
||||
@Insert("INSERT INTO profit_sharing_config (scenic_id, name, description, create_time, update_time) " +
|
||||
"VALUES (#{scenicId}, #{name}, #{description}, #{createTime}, #{updateTime})")
|
||||
@Options(useGeneratedKeys = true, keyProperty = "id")
|
||||
void insert(ProfitSharingConfig config);
|
||||
|
||||
@Update("UPDATE profit_sharing_config SET scenic_id = #{scenicId}, name = #{name}, description = #{description}, " +
|
||||
"create_time = #{createTime}, update_time = #{updateTime} WHERE id = #{id}")
|
||||
void update(ProfitSharingConfig config);
|
||||
|
||||
@Delete("DELETE FROM profit_sharing_config WHERE id = #{id}")
|
||||
void deleteById(Long id);
|
||||
|
||||
@Select("SELECT * FROM profit_sharing_config WHERE id = #{id}")
|
||||
ProfitSharingConfig findById(Long id);
|
||||
|
||||
@Select("SELECT * FROM profit_sharing_config")
|
||||
List<ProfitSharingConfig> findAll();
|
||||
|
||||
// 修改: 根据scenicId查询单个记录
|
||||
@Select("SELECT * FROM profit_sharing_config WHERE scenic_id = #{scenicId}")
|
||||
ProfitSharingConfig findByScenicId(Long scenicId);
|
||||
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package com.ycwl.basic.profitsharing.mapper;
|
||||
|
||||
import com.ycwl.basic.profitsharing.entity.ProfitSharingRecord;
|
||||
import org.apache.ibatis.annotations.Delete;
|
||||
import org.apache.ibatis.annotations.Insert;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Options;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface ProfitSharingRecordMapper {
|
||||
void batchInsert(List<ProfitSharingRecord> records);
|
||||
|
||||
@Delete("DELETE FROM profit_sharing_record WHERE scenic_id = #{scenicId} AND order_id = #{orderId}")
|
||||
void deleteByScenicIdAndOrderId(Long scenicId, Long orderId);
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package com.ycwl.basic.profitsharing.mapper;
|
||||
|
||||
import com.ycwl.basic.profitsharing.entity.ProfitSharingUser;
|
||||
import org.apache.ibatis.annotations.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface ProfitSharingUserMapper {
|
||||
@Insert("INSERT INTO profit_sharing_user (config_id, wx_pay_type, wx_pay_config, name, description, wx_rate, real_rate) " +
|
||||
"VALUES (#{configId}, #{wxPayType}, #{wxPayConfig}, #{name}, #{description}, #{wxRate}, #{realRate})")
|
||||
@Options(useGeneratedKeys = true, keyProperty = "id")
|
||||
void insert(ProfitSharingUser user);
|
||||
|
||||
@Update("UPDATE profit_sharing_user SET config_id = #{configId}, wx_pay_type = #{wxPayType}, wx_pay_config = #{wxPayConfig}, " +
|
||||
"name = #{name}, description = #{description}, wx_rate = #{wxRate}, real_rate = #{realRate} WHERE id = #{id}")
|
||||
void update(ProfitSharingUser user);
|
||||
|
||||
@Delete("DELETE FROM profit_sharing_user WHERE id = #{id}")
|
||||
void deleteById(Long id);
|
||||
|
||||
@Delete("DELETE FROM profit_sharing_user WHERE config_id = #{configId}")
|
||||
void deleteByConfigId(Long configId);
|
||||
|
||||
@Select("SELECT * FROM profit_sharing_user WHERE id = #{id}")
|
||||
ProfitSharingUser findById(Long id);
|
||||
|
||||
@Select("SELECT * FROM profit_sharing_user")
|
||||
List<ProfitSharingUser> findAll();
|
||||
|
||||
// 新增: 根据configId查询所有记录
|
||||
@Select("SELECT * FROM profit_sharing_user WHERE config_id = #{configId}")
|
||||
List<ProfitSharingUser> findByConfigId(Long configId);
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package com.ycwl.basic.profitsharing.repository;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.ycwl.basic.profitsharing.entity.ProfitSharingConfig;
|
||||
import com.ycwl.basic.profitsharing.mapper.ProfitSharingConfigMapper;
|
||||
import com.ycwl.basic.profitsharing.mapper.ProfitSharingUserMapper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class ProfitSharingRepository {
|
||||
@Autowired
|
||||
private ProfitSharingConfigMapper configMapper;
|
||||
@Autowired
|
||||
private ProfitSharingUserMapper userMapper;
|
||||
@Autowired
|
||||
private RedisTemplate<String, String> redisTemplate;
|
||||
public static final String PROFIT_SHARING_SCENIC_CONFIG_CACHE_KEY = "profit:scenic:%s";
|
||||
|
||||
public ProfitSharingConfig getScenicConfig(Long id) {
|
||||
if (redisTemplate.hasKey(String.format(PROFIT_SHARING_SCENIC_CONFIG_CACHE_KEY, id))) {
|
||||
return JSONObject.parseObject(redisTemplate.opsForValue().get(String.format(PROFIT_SHARING_SCENIC_CONFIG_CACHE_KEY, id)), ProfitSharingConfig.class);
|
||||
}
|
||||
ProfitSharingConfig scenicConfig = configMapper.findByScenicId(id);
|
||||
if (scenicConfig != null) {
|
||||
scenicConfig.setUsers(userMapper.findByConfigId(scenicConfig.getId()));
|
||||
redisTemplate.opsForValue().set(String.format(PROFIT_SHARING_SCENIC_CONFIG_CACHE_KEY, id), JSONObject.toJSONString(scenicConfig));
|
||||
}
|
||||
return scenicConfig;
|
||||
}
|
||||
|
||||
public void clearScenicConfigCache(Long id) {
|
||||
redisTemplate.delete(String.format(PROFIT_SHARING_SCENIC_CONFIG_CACHE_KEY, id));
|
||||
}
|
||||
}
|
11
src/main/resources/mapper/ProfitSharingRecordMapper.xml
Normal file
11
src/main/resources/mapper/ProfitSharingRecordMapper.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<?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.ycwl.basic.profitsharing.mapper.ProfitSharingRecordMapper" >
|
||||
<insert id="batchInsert">
|
||||
INSERT INTO profit_sharing_record (scenic_id, order_id, user_id, user_name, amount, wx_amount, manual_amount, wx_rate, real_rate, order_amount, create_time)
|
||||
VALUES
|
||||
<foreach collection="records" item="record" separator=",">
|
||||
(#{record.scenicId}, #{record.orderId}, #{record.userId}, #{record.userName}, #{record.amount}, #{record.wxAmount}, #{record.manualAmount}, #{record.wxRate}, #{record.realRate}, #{record.orderAmount}, #{record.createTime})
|
||||
</foreach>
|
||||
</insert>
|
||||
</mapper>
|
Loading…
x
Reference in New Issue
Block a user