|
|
@@ -0,0 +1,312 @@
|
|
|
+package com.etotem.cfc.service;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.etotem.cfc.dto.FamilyEarningsMemberDTO;
|
|
|
+import com.etotem.cfc.dto.FamilyEarningsSummaryDTO;
|
|
|
+import com.etotem.cfc.entity.*;
|
|
|
+import com.etotem.cfc.mapper.*;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.util.Date;
|
|
|
+import java.util.List;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+@Service
|
|
|
+public class FamilyEarningsService {
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private FamilyEarningsMapper familyEarningsMapper;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private FamilyEarningsMemberMapper familyEarningsMemberMapper;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private FamilyEarningsRecordMapper familyEarningsRecordMapper;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private UserMapper userMapper;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private FamilyMapper familyMapper;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取家庭收益总览
|
|
|
+ */
|
|
|
+ public FamilyEarningsSummaryDTO getFamilySummary(Long familyId) {
|
|
|
+ FamilyEarningsSummaryDTO summary = new FamilyEarningsSummaryDTO();
|
|
|
+
|
|
|
+ // 获取家庭总账
|
|
|
+ FamilyEarnings earnings = familyEarningsMapper.selectOne(
|
|
|
+ new LambdaQueryWrapper<FamilyEarnings>().eq(FamilyEarnings::getFamilyId, familyId)
|
|
|
+ );
|
|
|
+
|
|
|
+ if (earnings != null) {
|
|
|
+ summary.setFamilyId(earnings.getFamilyId());
|
|
|
+ summary.setTotalEarned(earnings.getTotalEarned());
|
|
|
+ summary.setAvailableAmount(earnings.getAvailableAmount());
|
|
|
+ summary.setWithdrawnAmount(earnings.getWithdrawnAmount());
|
|
|
+ summary.setDistributedAmount(earnings.getDistributedAmount());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取成员列表
|
|
|
+ List<FamilyEarningsMemberDTO> members = getMemberContributions(familyId);
|
|
|
+ summary.setMembers(members);
|
|
|
+
|
|
|
+ return summary;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取家庭成员贡献列表
|
|
|
+ */
|
|
|
+ public List<FamilyEarningsMemberDTO> getMemberContributions(Long familyId) {
|
|
|
+ // 获取家庭成员
|
|
|
+ List<User> familyUsers = userMapper.selectList(
|
|
|
+ new LambdaQueryWrapper<User>().eq(User::getFamilyId, familyId)
|
|
|
+ );
|
|
|
+
|
|
|
+ return familyUsers.stream().map(user -> {
|
|
|
+ FamilyEarningsMemberDTO dto = new FamilyEarningsMemberDTO();
|
|
|
+ dto.setUserId(user.getId());
|
|
|
+ dto.setNickname(user.getNickname());
|
|
|
+ dto.setAvatar(user.getAvatar());
|
|
|
+ dto.setIsAdmin(user.getIsFamilyAdmin() != null && user.getIsFamilyAdmin());
|
|
|
+
|
|
|
+ // 获取成员收益信息
|
|
|
+ FamilyEarningsMember member = familyEarningsMemberMapper.selectOne(
|
|
|
+ new LambdaQueryWrapper<FamilyEarningsMember>()
|
|
|
+ .eq(FamilyEarningsMember::getFamilyId, familyId)
|
|
|
+ .eq(FamilyEarningsMember::getUserId, user.getId())
|
|
|
+ );
|
|
|
+
|
|
|
+ if (member != null) {
|
|
|
+ dto.setAllocatedAmount(member.getAllocatedAmount());
|
|
|
+ dto.setConsumedAmount(member.getConsumedAmount());
|
|
|
+ dto.setAvailableAmount(member.getAvailableAmount());
|
|
|
+ dto.setCanUseFamilyBalance(member.getCanUseFamilyBalance());
|
|
|
+ } else {
|
|
|
+ // 初始化默认值
|
|
|
+ dto.setAllocatedAmount(0L);
|
|
|
+ dto.setConsumedAmount(0L);
|
|
|
+ dto.setAvailableAmount(0L);
|
|
|
+ dto.setCanUseFamilyBalance(false);
|
|
|
+ }
|
|
|
+
|
|
|
+ return dto;
|
|
|
+ }).collect(Collectors.toList());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 收入(佣金结算时调用)
|
|
|
+ */
|
|
|
+ @Transactional
|
|
|
+ public void earn(Long familyId, Long amount, Long fromUserId) {
|
|
|
+ if (familyId == null || amount == null || amount <= 0) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取或创建家庭收益记录
|
|
|
+ FamilyEarnings earnings = familyEarningsMapper.selectOne(
|
|
|
+ new LambdaQueryWrapper<FamilyEarnings>().eq(FamilyEarnings::getFamilyId, familyId)
|
|
|
+ );
|
|
|
+
|
|
|
+ if (earnings == null) {
|
|
|
+ earnings = new FamilyEarnings();
|
|
|
+ earnings.setFamilyId(familyId);
|
|
|
+ earnings.setTotalEarned(amount);
|
|
|
+ earnings.setAvailableAmount(amount);
|
|
|
+ earnings.setWithdrawnAmount(0L);
|
|
|
+ earnings.setDistributedAmount(0L);
|
|
|
+ earnings.setCreatedAt(new Date());
|
|
|
+ earnings.setUpdatedAt(new Date());
|
|
|
+ familyEarningsMapper.insert(earnings);
|
|
|
+ } else {
|
|
|
+ earnings.setTotalEarned(earnings.getTotalEarned() + amount);
|
|
|
+ earnings.setAvailableAmount(earnings.getAvailableAmount() + amount);
|
|
|
+ earnings.setUpdatedAt(new Date());
|
|
|
+ familyEarningsMapper.updateById(earnings);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 记录流水
|
|
|
+ FamilyEarningsRecord record = new FamilyEarningsRecord();
|
|
|
+ record.setFamilyId(familyId);
|
|
|
+ record.setType("earn");
|
|
|
+ record.setAmount(amount);
|
|
|
+ record.setFromUserId(fromUserId);
|
|
|
+ record.setCreatedAt(new Date());
|
|
|
+ familyEarningsRecordMapper.insert(record);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 提现(管理员发起)
|
|
|
+ */
|
|
|
+ @Transactional
|
|
|
+ public void withdraw(Long familyId, Long amount, Long adminUserId) {
|
|
|
+ if (familyId == null || amount == null || amount <= 0) {
|
|
|
+ throw new RuntimeException("提现金额必须大于0");
|
|
|
+ }
|
|
|
+
|
|
|
+ FamilyEarnings earnings = familyEarningsMapper.selectOne(
|
|
|
+ new LambdaQueryWrapper<FamilyEarnings>().eq(FamilyEarnings::getFamilyId, familyId)
|
|
|
+ );
|
|
|
+
|
|
|
+ if (earnings == null || earnings.getAvailableAmount() < amount) {
|
|
|
+ throw new RuntimeException("可用余额不足");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新家庭收益
|
|
|
+ earnings.setAvailableAmount(earnings.getAvailableAmount() - amount);
|
|
|
+ earnings.setWithdrawnAmount(earnings.getWithdrawnAmount() + amount);
|
|
|
+ earnings.setUpdatedAt(new Date());
|
|
|
+ familyEarningsMapper.updateById(earnings);
|
|
|
+
|
|
|
+ // 记录流水
|
|
|
+ FamilyEarningsRecord record = new FamilyEarningsRecord();
|
|
|
+ record.setFamilyId(familyId);
|
|
|
+ record.setType("withdraw");
|
|
|
+ record.setAmount(amount);
|
|
|
+ record.setFromUserId(adminUserId);
|
|
|
+ record.setCreatedAt(new Date());
|
|
|
+ familyEarningsRecordMapper.insert(record);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 颁发给成员(管理员分配)
|
|
|
+ */
|
|
|
+ @Transactional
|
|
|
+ public void distribute(Long familyId, Long toUserId, Long amount, Long adminUserId) {
|
|
|
+ if (familyId == null || toUserId == null || amount == null || amount <= 0) {
|
|
|
+ throw new RuntimeException("分配金额必须大于0");
|
|
|
+ }
|
|
|
+
|
|
|
+ FamilyEarnings earnings = familyEarningsMapper.selectOne(
|
|
|
+ new LambdaQueryWrapper<FamilyEarnings>().eq(FamilyEarnings::getFamilyId, familyId)
|
|
|
+ );
|
|
|
+
|
|
|
+ if (earnings == null || earnings.getAvailableAmount() < amount) {
|
|
|
+ throw new RuntimeException("可用余额不足");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新家庭收益
|
|
|
+ earnings.setAvailableAmount(earnings.getAvailableAmount() - amount);
|
|
|
+ earnings.setDistributedAmount(earnings.getDistributedAmount() + amount);
|
|
|
+ earnings.setUpdatedAt(new Date());
|
|
|
+ familyEarningsMapper.updateById(earnings);
|
|
|
+
|
|
|
+ // 获取或创建成员收益记录
|
|
|
+ FamilyEarningsMember member = familyEarningsMemberMapper.selectOne(
|
|
|
+ new LambdaQueryWrapper<FamilyEarningsMember>()
|
|
|
+ .eq(FamilyEarningsMember::getFamilyId, familyId)
|
|
|
+ .eq(FamilyEarningsMember::getUserId, toUserId)
|
|
|
+ );
|
|
|
+
|
|
|
+ if (member == null) {
|
|
|
+ member = new FamilyEarningsMember();
|
|
|
+ member.setFamilyId(familyId);
|
|
|
+ member.setUserId(toUserId);
|
|
|
+ member.setAllocatedAmount(amount);
|
|
|
+ member.setConsumedAmount(0L);
|
|
|
+ member.setAvailableAmount(amount);
|
|
|
+ member.setCanUseFamilyBalance(false); // 默认不允许使用家庭公共池
|
|
|
+ member.setCreatedAt(new Date());
|
|
|
+ member.setUpdatedAt(new Date());
|
|
|
+ familyEarningsMemberMapper.insert(member);
|
|
|
+ } else {
|
|
|
+ member.setAllocatedAmount(member.getAllocatedAmount() + amount);
|
|
|
+ member.setAvailableAmount(member.getAvailableAmount() + amount);
|
|
|
+ member.setUpdatedAt(new Date());
|
|
|
+ familyEarningsMemberMapper.updateById(member);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 记录流水
|
|
|
+ FamilyEarningsRecord record = new FamilyEarningsRecord();
|
|
|
+ record.setFamilyId(familyId);
|
|
|
+ record.setType("distribute");
|
|
|
+ record.setAmount(amount);
|
|
|
+ record.setFromUserId(adminUserId);
|
|
|
+ record.setToUserId(toUserId);
|
|
|
+ record.setCreatedAt(new Date());
|
|
|
+ familyEarningsRecordMapper.insert(record);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 消费扣款(支付时调用)
|
|
|
+ */
|
|
|
+ @Transactional
|
|
|
+ public void consume(Long familyId, Long userId, Long amount) {
|
|
|
+ if (familyId == null || userId == null || amount == null || amount <= 0) {
|
|
|
+ throw new RuntimeException("消费金额必须大于0");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查成员是否有足够的可用余额
|
|
|
+ FamilyEarningsMember member = familyEarningsMemberMapper.selectOne(
|
|
|
+ new LambdaQueryWrapper<FamilyEarningsMember>()
|
|
|
+ .eq(FamilyEarningsMember::getFamilyId, familyId)
|
|
|
+ .eq(FamilyEarningsMember::getUserId, userId)
|
|
|
+ );
|
|
|
+
|
|
|
+ if (member == null || member.getAvailableAmount() < amount) {
|
|
|
+ throw new RuntimeException("可用余额不足");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新成员收益
|
|
|
+ member.setConsumedAmount(member.getConsumedAmount() + amount);
|
|
|
+ member.setAvailableAmount(member.getAvailableAmount() - amount);
|
|
|
+ member.setUpdatedAt(new Date());
|
|
|
+ familyEarningsMemberMapper.updateById(member);
|
|
|
+
|
|
|
+ // 记录流水
|
|
|
+ FamilyEarningsRecord record = new FamilyEarningsRecord();
|
|
|
+ record.setFamilyId(familyId);
|
|
|
+ record.setType("consume");
|
|
|
+ record.setAmount(amount);
|
|
|
+ record.setToUserId(userId);
|
|
|
+ record.setCreatedAt(new Date());
|
|
|
+ familyEarningsRecordMapper.insert(record);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 流水查询
|
|
|
+ */
|
|
|
+ public List<FamilyEarningsRecord> getRecords(Long familyId, String type) {
|
|
|
+ LambdaQueryWrapper<FamilyEarningsRecord> wrapper = new LambdaQueryWrapper<FamilyEarningsRecord>()
|
|
|
+ .eq(FamilyEarningsRecord::getFamilyId, familyId);
|
|
|
+
|
|
|
+ if (type != null && !type.isEmpty()) {
|
|
|
+ wrapper.eq(FamilyEarningsRecord::getType, type);
|
|
|
+ }
|
|
|
+
|
|
|
+ wrapper.orderByDesc(FamilyEarningsRecord::getCreatedAt);
|
|
|
+ return familyEarningsRecordMapper.selectList(wrapper);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 切换成员是否允许使用家庭公共池
|
|
|
+ */
|
|
|
+ @Transactional
|
|
|
+ public void toggleMemberAccess(Long familyId, Long userId, Boolean enabled) {
|
|
|
+ FamilyEarningsMember member = familyEarningsMemberMapper.selectOne(
|
|
|
+ new LambdaQueryWrapper<FamilyEarningsMember>()
|
|
|
+ .eq(FamilyEarningsMember::getFamilyId, familyId)
|
|
|
+ .eq(FamilyEarningsMember::getUserId, userId)
|
|
|
+ );
|
|
|
+
|
|
|
+ if (member == null) {
|
|
|
+ member = new FamilyEarningsMember();
|
|
|
+ member.setFamilyId(familyId);
|
|
|
+ member.setUserId(userId);
|
|
|
+ member.setAllocatedAmount(0L);
|
|
|
+ member.setConsumedAmount(0L);
|
|
|
+ member.setAvailableAmount(0L);
|
|
|
+ member.setCanUseFamilyBalance(enabled);
|
|
|
+ member.setCreatedAt(new Date());
|
|
|
+ member.setUpdatedAt(new Date());
|
|
|
+ familyEarningsMemberMapper.insert(member);
|
|
|
+ } else {
|
|
|
+ member.setCanUseFamilyBalance(enabled);
|
|
|
+ member.setUpdatedAt(new Date());
|
|
|
+ familyEarningsMemberMapper.updateById(member);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|