|
@@ -2,20 +2,22 @@ package com.ym.mec.biz.service.impl;
|
|
|
|
|
|
import com.alibaba.fastjson.JSON;
|
|
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
+import com.ym.mec.auth.api.client.SysUserFeignService;
|
|
|
+import com.ym.mec.auth.api.entity.SysUser;
|
|
|
import com.ym.mec.biz.dal.dao.TenantAssetsInfoDao;
|
|
|
-import com.ym.mec.biz.dal.entity.CourseSchedule;
|
|
|
-import com.ym.mec.biz.dal.entity.TenantAssetsInfo;
|
|
|
-import com.ym.mec.biz.dal.entity.TenantConfig;
|
|
|
-import com.ym.mec.biz.dal.entity.TenantConfigDetail;
|
|
|
+import com.ym.mec.biz.dal.entity.*;
|
|
|
import com.ym.mec.biz.dal.entity.TenantConfigDetail.CloudRoomRule;
|
|
|
import com.ym.mec.biz.dal.enums.TeachModeEnum;
|
|
|
import com.ym.mec.biz.service.TenantAssetsInfoService;
|
|
|
+import com.ym.mec.biz.service.TenantCloudCourseRecordService;
|
|
|
import com.ym.mec.biz.service.TenantConfigService;
|
|
|
import com.ym.mec.common.exception.BizException;
|
|
|
-import com.ym.mec.common.filters.TenantIdThreadLocal;
|
|
|
import com.ym.mec.common.page.WrapperUtil;
|
|
|
import com.ym.mec.common.tenant.TenantContextHolder;
|
|
|
+import com.ym.mec.thirdparty.yqpay.DateUtils;
|
|
|
import org.apache.commons.collections.CollectionUtils;
|
|
|
+import org.redisson.api.RBucket;
|
|
|
+import org.redisson.api.RedissonClient;
|
|
|
import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
@@ -25,10 +27,9 @@ import org.springframework.transaction.annotation.Transactional;
|
|
|
import java.math.BigDecimal;
|
|
|
import java.math.MathContext;
|
|
|
import java.math.RoundingMode;
|
|
|
-import java.util.List;
|
|
|
-import java.util.Map;
|
|
|
-import java.util.Objects;
|
|
|
-import java.util.Optional;
|
|
|
+import java.text.ParseException;
|
|
|
+import java.util.*;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
/**
|
|
@@ -44,6 +45,12 @@ public class TenantAssetsInfoServiceImpl extends ServiceImpl<TenantAssetsInfoDao
|
|
|
|
|
|
@Autowired
|
|
|
private TenantConfigService tenantConfigService;
|
|
|
+ @Autowired
|
|
|
+ private SysUserFeignService sysUserFeignService;
|
|
|
+ @Autowired
|
|
|
+ private TenantCloudCourseRecordService tenantCloudCourseRecordService;
|
|
|
+ @Autowired
|
|
|
+ private RedissonClient redissonClient;
|
|
|
|
|
|
/**
|
|
|
* 排课扣费计算
|
|
@@ -53,43 +60,115 @@ public class TenantAssetsInfoServiceImpl extends ServiceImpl<TenantAssetsInfoDao
|
|
|
@Override
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
public void courseDeductionRules(List<CourseSchedule> dto) {
|
|
|
- dto = Optional.ofNullable(dto)
|
|
|
+ Integer tenantId = TenantContextHolder.getTenantId();
|
|
|
+
|
|
|
+ //防止重复点击 加锁
|
|
|
+ String key = "Tenant_Course_Deduct:" + tenantId;
|
|
|
+ RBucket<Object> bucket = redissonClient.getBucket(key);
|
|
|
+ //原子操作 抢锁成功为true
|
|
|
+ if (!bucket.trySet(tenantId, 1L, TimeUnit.MINUTES)) {
|
|
|
+ throw new BizException("有人正在排课请勿同时操作!");
|
|
|
+ }
|
|
|
+ //校验课程 筛选出线上课
|
|
|
+ dto = getOnlineCourse(dto);
|
|
|
+ if (CollectionUtils.isEmpty(dto)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ TenantAssetsInfo assetsInfo = this.getOne(new WrapperUtil<TenantAssetsInfo>()
|
|
|
+ .hasEq("tenant_id_", tenantId).queryWrapper());
|
|
|
+ if (Objects.isNull(assetsInfo)) {
|
|
|
+ throw new BizException("未查询到该机构的账户资产信息!");
|
|
|
+ }
|
|
|
+
|
|
|
+ //获取云教室规则 String人数-BigDecimal每分钟扣费标准
|
|
|
+ Map<String, BigDecimal> rule = getRule(tenantId);
|
|
|
+ BigDecimal frozenAmount = BigDecimal.ZERO;
|
|
|
+
|
|
|
+ for (CourseSchedule course : dto) {//获取总人数 ,+1是算上老师
|
|
|
+ Integer totalPeople = course.getStudentNum() + 1;
|
|
|
+ //获取每分钟扣费标准
|
|
|
+ BigDecimal minutePrice = rule.get(String.valueOf(totalPeople));
|
|
|
+ if (Objects.isNull(minutePrice)) {
|
|
|
+ throw new BizException("该机构未设置 " + totalPeople + " 人(含老师)的课程收费标准,请前往机构产品设置中确认该人数的设置是否存在!");
|
|
|
+ }
|
|
|
+ //计算总上课时间
|
|
|
+ BigDecimal courseDate = getCourseDate(course);
|
|
|
+ //课程单价 = 每分钟扣费标准 * 总上课时间
|
|
|
+ BigDecimal coursePrice = minutePrice.multiply(courseDate, new MathContext(2, RoundingMode.HALF_UP));
|
|
|
+ frozenAmount = frozenAmount.add(coursePrice);
|
|
|
+ //判断余额是否足够
|
|
|
+ if (assetsInfo.getBalance().compareTo(frozenAmount) < 0) {
|
|
|
+ throw new BizException("余额不足!");
|
|
|
+ }
|
|
|
+
|
|
|
+ //写入流水
|
|
|
+ TenantCloudCourseRecord record = new TenantCloudCourseRecord();
|
|
|
+ record.setCourseId(course.getId().intValue());
|
|
|
+ record.setAmount(coursePrice);
|
|
|
+ record.setTenantId(tenantId);
|
|
|
+ record.setDeductState(0);
|
|
|
+ record.setCreatedBy(getUserId());
|
|
|
+ record.setCreatedTime(new Date());
|
|
|
+ tenantCloudCourseRecordService.save(record);
|
|
|
+ }
|
|
|
+
|
|
|
+ assetsInfo.setBalance(assetsInfo.getBalance().subtract(frozenAmount));
|
|
|
+ assetsInfo.setFrozenAmount(frozenAmount.add(assetsInfo.getFrozenAmount()));
|
|
|
+ this.updateById(assetsInfo);
|
|
|
+ bucket.delete();
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<CourseSchedule> getOnlineCourse(List<CourseSchedule> dto) {
|
|
|
+ return Optional.ofNullable(dto)
|
|
|
.filter(CollectionUtils::isNotEmpty)
|
|
|
- .orElseThrow(() -> new BizException("请传入课程表参数!"))
|
|
|
+ .orElseThrow(() -> new BizException("请传入课程数据!"))
|
|
|
.stream()
|
|
|
.filter(c -> c.getTeachMode().equals(TeachModeEnum.ONLINE))
|
|
|
.collect(Collectors.toList());
|
|
|
+ }
|
|
|
|
|
|
- Integer tenantId = TenantContextHolder.getTenantId();
|
|
|
+ private Map<String, BigDecimal> getRule(Integer tenantId) {
|
|
|
+ //查询云教室扣费标准
|
|
|
TenantConfig tenantConfig = tenantConfigService.getOne(new WrapperUtil<TenantConfig>()
|
|
|
.hasEq("tenant_id_", tenantId).queryWrapper());
|
|
|
if (Objects.isNull(tenantConfig)) {
|
|
|
throw new BizException("未查询到机构云教室规则信息!");
|
|
|
}
|
|
|
- //获取云教室规则
|
|
|
- Map<String, BigDecimal> rule = Optional.ofNullable(tenantConfig.getConfig())
|
|
|
+ return Optional.ofNullable(tenantConfig.getConfig())
|
|
|
.map(c -> JSON.parseObject(c, TenantConfigDetail.class))
|
|
|
.map(TenantConfigDetail::getCloud_room_rule)
|
|
|
.map(CloudRoomRule::getCloud_room_config)
|
|
|
.orElseThrow(() -> new BizException("未查询到机构云教室规则!"));
|
|
|
- BigDecimal total = BigDecimal.ZERO;
|
|
|
-// dto.forEach(course -> {
|
|
|
-// Integer peopleNum = course.getPeopleNum();
|
|
|
-// BigDecimal minutePrice = rule.get(String.valueOf(peopleNum));
|
|
|
-// BigDecimal duration = BigDecimal.valueOf(course.getCourseDuration());
|
|
|
-// BigDecimal coursePrice = minutePrice.multiply(duration, new MathContext(2, RoundingMode.HALF_UP));
|
|
|
-//
|
|
|
-// });
|
|
|
+ }
|
|
|
|
|
|
- System.out.println(1);
|
|
|
+ private BigDecimal getCourseDate(CourseSchedule course) {
|
|
|
+ String date = DateUtils.formatDate(course.getClassDate(), DateUtils.YYYY_MM_DD_DEF);
|
|
|
+ Date startDT = getDateTime(date, course.getStartClassTime());
|
|
|
+ Date endDT = getDateTime(date, course.getEndClassTime());
|
|
|
+ //课程结束时间-课程开始时间
|
|
|
+ long durationTime = endDT.getTime() - startDT.getTime();
|
|
|
+ //相差多少分钟
|
|
|
+ int durationMinute = new Long(durationTime / 1000 / 60).intValue();
|
|
|
+ return BigDecimal.valueOf(durationMinute);
|
|
|
+ }
|
|
|
|
|
|
- TenantAssetsInfo assetsInfo = this.getOne(new WrapperUtil<TenantAssetsInfo>()
|
|
|
- .hasEq("tenant_id_", tenantId).queryWrapper());
|
|
|
- if (Objects.isNull(assetsInfo)) {
|
|
|
- throw new BizException("未查询到该机构的账户资产信息!");
|
|
|
+ private Date getDateTime(String dateStr, Date time) {
|
|
|
+ String timeStr = DateUtils.formatDate(time, "HH:mm:ss");
|
|
|
+ String s = dateStr + " " + timeStr;
|
|
|
+ try {
|
|
|
+ return DateUtils.parseDate(s, DateUtils.DATE_WEB_FORMAT);
|
|
|
+ } catch (ParseException e) {
|
|
|
+ throw new BizException("课程时间格式错误!");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private Integer getUserId() {
|
|
|
+ //修改机构基础信息
|
|
|
+ return Optional.ofNullable(sysUserFeignService.queryUserInfo())
|
|
|
+ .map(SysUser::getId)
|
|
|
+ .orElseThrow(() -> new BizException("用户信息获取失败,请刷新页面或者重新登录!"));
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|