1、新增组织编辑修改首购价格能力;2、账单分页支持非管理端只允许查看本组织下;3、统计公共入参和方法抽象、过期组织接口分离移到system、新增销售额统计接口;

This commit is contained in:
gaoqr
2025-09-30 14:50:57 +08:00
parent 7076c64811
commit 23bc07160d
38 changed files with 736 additions and 772 deletions
@@ -1,7 +1,6 @@
package com.cf.imes.module.system.api.organ;
import com.cf.imes.framework.common.pojo.CommonResult;
import com.cf.imes.module.system.api.organ.dto.OrgStatisticsReqDTO;
import com.cf.imes.module.system.api.organ.dto.OrganizationDTO;
import com.cf.imes.module.system.enums.ApiConstants;
import io.swagger.v3.oas.annotations.Operation;
@@ -9,12 +8,9 @@ import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import jakarta.validation.Valid;
import java.util.List;
import java.util.Map;
@FeignClient(name = ApiConstants.NAME) // TODO 晨丰:fallbackFactory =
@Tag(name = "RPC 服务 - 多组织")
@@ -31,15 +27,6 @@ public interface OrganApi {
@Parameter(name = "id", description = "组织编号", required = true, example = "1024")
CommonResult<Boolean> validOrgan(@RequestParam("id") Long id);
@PostMapping(PREFIX + "/separate/org")
@Operation(summary = "新增、注销组织数量统计")
CommonResult<Map<String, Object>> getOrgSeparate(@Valid OrgStatisticsReqDTO reqVO);
@GetMapping(PREFIX + "/warn/org")
@Operation(summary = "组织过期日期统计")
CommonResult<Map<String, List<Object>>> getWarnToOrg();
@GetMapping(PREFIX + "/organ-details")
@Operation(summary = "根据组织ID获取组织的详细信息")
CommonResult<OrganizationDTO> getOrganDetails(@RequestParam("organId") Long organId);
@@ -139,7 +139,6 @@ public class ErrorCodeConstants {
public static final ErrorCode ORGAN_ALREADY_EXISTS = new ErrorCode(1_002_015_007, "该新增组织已授权机台数量无需重复新增!");
public static final ErrorCode ORGAN_USER_OPER_NOT_ALLOW = new ErrorCode(1_002_015_008, "不允许操作用户自身组织");
public static final ErrorCode ORGAN_CONTACTMOBILE_DUPLICATE = new ErrorCode(1_002_015_009, "手机号为【{}】的组织已存在");
public static final ErrorCode ORGAN_CREATE_PRODUCTLIST_EMPTY_ERROR = new ErrorCode(1_002_015_010, "组织创建购买产品列表不能为空");
// ========== 组织套餐 1-002-016-000 ==========
public static final ErrorCode TENANT_PACKAGE_NOT_EXISTS = new ErrorCode(1_002_016_000, "组织套餐不存在");
@@ -475,6 +474,8 @@ public class ErrorCodeConstants {
public static final ErrorCode PRODUCTS_DETAIL_DURATION_UNIT_NOT_SUPPORT = new ErrorCode(1_002_045_011, "不支持的时长单位,请检查该定价规则的时长单位");
public static final ErrorCode ORG_PRODUCT_PURCHASE_WAIT_PAY_ERROR = new ErrorCode(1_002_045_012, "组织下存在当前产品的待支付记录,请确认或取消支付后再次发起软件购买");
public static final ErrorCode PRODUCT_PRICE_NULL_ERROR = new ErrorCode(1_002_045_013, "产品建议价格为空,请联系客服");
public static final ErrorCode ORG_PRODUCT_PURCHASE_NOT_EXIST_ERROR = new ErrorCode(1_002_045_014, "组织订购记录不存在,请检查数据");
public static final ErrorCode ORG_PRODUCT_PURCHASE_EXIST_ERROR = new ErrorCode(1_002_045_014, "组织[{}]订购记录已存在,请勿重复定义订购机构");
//=========== 广告相关 1-002-046-000 ============
public static final ErrorCode ADVERTISEMENT_POSITION_NO_EXIST = new ErrorCode(1_002_046_001, "广告所选放置位置不存在");
@@ -2,15 +2,11 @@ package com.cf.imes.module.system.api.organ;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.cf.imes.framework.common.enums.OrderStatisticsUnit;
import com.cf.imes.framework.common.pojo.CommonResult;
import com.cf.imes.framework.common.util.object.BeanUtils;
import com.cf.imes.module.system.api.organ.dto.OrgStatisticsIsLapseRespDTO;
import com.cf.imes.module.system.api.organ.dto.OrgStatisticsReqDTO;
import com.cf.imes.module.system.api.organ.dto.OrganizationDTO;
import com.cf.imes.module.system.controller.admin.funds.delay.vo.PreviouProductDelayRespVO;
import com.cf.imes.module.system.controller.admin.funds.delay.vo.ProductDelayRespVO;
import com.cf.imes.module.system.controller.admin.organ.vo.organ.OrganRespVO;
import com.cf.imes.module.system.dal.dataobject.funds.purchase.PurchaseRecordDO;
import com.cf.imes.module.system.service.funds.delay.ProductDelayService;
import com.cf.imes.module.system.service.organ.OrganService;
@@ -19,15 +15,11 @@ import org.springframework.web.bind.annotation.RestController;
import jakarta.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import static com.cf.imes.framework.common.exception.enums.GlobalErrorCodeConstants.ORG_PRODUCT_EXPIRED;
import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.cf.imes.framework.common.pojo.CommonResult.success;
import static com.cf.imes.framework.common.util.time.StatisticsChangeUtils.generateDateRangeAxis;
import static com.cf.imes.framework.common.util.time.StatisticsChangeUtils.getDateList;
@RestController // 提供 RESTful API 接口,给 Feign 调用
@Validated
@@ -50,70 +42,6 @@ public class OrganApiImpl implements OrganApi {
return success(true);
}
@Override
public CommonResult<Map<String, Object>> getOrgSeparate(OrgStatisticsReqDTO reqVO) {
setOrgStatisticsReqVO(reqVO);
Map<String, Object> resultMap = new LinkedHashMap<>();
// 所有的日期集合
List<String> dateList = getDateList(reqVO.getCreateTime(),reqVO.getUnit());
// 组织有效数量
Map<String, List<OrgStatisticsIsLapseRespDTO>> orderNotLapseRespMap = organService.orgCountAddByOrderDateAdd(reqVO).stream()
.sorted(Comparator.naturalOrder())
.collect(Collectors.groupingBy(OrgStatisticsIsLapseRespDTO::getDate, LinkedHashMap::new, Collectors.toList()));
// 组织无效数量
Map<String, List<OrgStatisticsIsLapseRespDTO>> orderLapseRespMap = organService.orgCountLapseByOrderDate(reqVO).stream()
.sorted(Comparator.naturalOrder())
.collect(Collectors.groupingBy(OrgStatisticsIsLapseRespDTO::getDate, LinkedHashMap::new, Collectors.toList()));
// 遍历时间跨度列表,匹配数量存入数组,没有补0存入数组
for (String dateStr : dateList) {
int[] countArr = new int[2];
// 组织有效数量
Integer orderNotLapseCount = Optional.ofNullable(orderNotLapseRespMap.get(dateStr))
.map(list -> list.stream().findFirst().orElse(new OrgStatisticsIsLapseRespDTO()))
.map(OrgStatisticsIsLapseRespDTO::getOrgCount)
.orElse(0);
countArr[0] = orderNotLapseCount;
// 组织无效数量
Integer orderLapseCount = Optional.ofNullable(orderLapseRespMap.get(dateStr))
.map(list -> list.stream().findFirst().orElse(new OrgStatisticsIsLapseRespDTO()))
.map(OrgStatisticsIsLapseRespDTO::getOrgCount)
.orElse(0);
countArr[1] = orderLapseCount;
resultMap.put(generateDateRangeAxis(dateStr, reqVO.getUnit()), countArr);
}
return success(resultMap);
}
@Override
public CommonResult<Map<String, List<Object>>> getWarnToOrg() {
Map<String, List<Object>> map = new HashMap<>();
LocalDateTime today = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0);
LocalDateTime afterDay = today.plusDays(15).withHour(23).withMinute(59).withSecond(59);
LocalDateTime alertDay = LocalDateTime.now().withHour(23).withMinute(59).withSecond(59);
// 即将过期组织
List<OrganRespVO> expireOrg = organService.orgCountExpire(today, afterDay);
map.put("expireOrg", Collections.singletonList(expireOrg));
// 已过期组织
List<OrganRespVO> lapseOrg = organService.orgCountExpired(alertDay);
map.put("expiredOrg", Collections.singletonList(lapseOrg));
return success(map);
}
@Override
public CommonResult<OrganizationDTO> getOrganDetails(Long organId) {
@@ -127,18 +55,6 @@ public class OrganApiImpl implements OrganApi {
return null;
}
private void setOrgStatisticsReqVO(OrgStatisticsReqDTO reqVO){
if (ObjectUtil.isNull(reqVO.getUnit())){
reqVO.setUnit(OrderStatisticsUnit.DAY.getValue());
}
if (ObjectUtil.isNull(reqVO.getCreateTime())){
reqVO.setCreateTime(new LocalDate[2]);
}
LocalDate[] time = reqVO.getCreateTime();
reqVO.setCreateTime(new LocalDate[]{time[0], time[1]});
}
@Override
public CommonResult<Boolean> validOrganProduct(Long organId, Long productId) {
PreviouProductDelayRespVO recordsByProductId = productDelayService.getActiveRecordsByProductId(productId, organId);
@@ -43,6 +43,7 @@ public class BalanceDetailsController {
@GetMapping("")
@Operation(summary = "查询组织账户明细分页")
public CommonResult<PageResult<BalanceDetailsRespVO>> getBalanceDetailsPage(@Valid BalanceDetailsPageReqVO pageReqVO) {
// 非管理端只能查看本组织数据
boolean manageEndPoint = SecurityFrameworkUtils.isManageEndPoint();
if (!manageEndPoint) {
pageReqVO.setOrganId(SecurityFrameworkUtils.getUserOrganId());
@@ -55,9 +56,10 @@ public class BalanceDetailsController {
@OperateLog(type = EXPORT)
public void balanceDetailsExport(@Valid BalanceDetailsPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
// 非管理端只能查看本组织数据
boolean manageEndPoint = SecurityFrameworkUtils.isManageEndPoint();
if (!manageEndPoint) {
pageReqVO.setOrganId(null);
pageReqVO.setOrganId(SecurityFrameworkUtils.getUserOrganId());
}
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<BalanceDetailsRespVO> list = incomeExpenseService.getBalanceDetailsPage(pageReqVO).getList();
@@ -1,12 +1,8 @@
package com.cf.imes.module.system.controller.admin.funds.organamount.vo;
import com.cf.imes.module.system.validation.pay.FundsStatisticsUnitInEnum;
import com.cf.imes.framework.common.pojo.CommonStatisticsReqVO;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDate;
/**
* @author Gqr
@@ -14,17 +10,5 @@ import java.time.LocalDate;
*/
@Schema(description = "管理后台 - 资金统计趋势 Request VO")
@Data
public class OrganFundsStatisticsReqVO {
@Schema(description = "创建时间")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private LocalDate[] createTime;
/**
* 统计维度单位
*/
@Schema(description = "统计维度单位", example = "0", allowableValues = {"0", "1", "2", "3"}, type = "integer")
@NotNull(message = "统计维度单位不能为空")
@FundsStatisticsUnitInEnum
private Integer unit;
public class OrganFundsStatisticsReqVO extends CommonStatisticsReqVO {
}
@@ -43,7 +43,11 @@ public class PurchaseController {
@GetMapping("")
@Operation(summary = "获取软件的购买记录")
public CommonResult<PageResult<PurchaseRecordRespVO>> getPurchaseRecord(@Valid PurchaseRecordPageReqVO pageReqVO) {
// 非管理端只能查看本组织数据
boolean manageEndPoint = SecurityFrameworkUtils.isManageEndPoint();
if (!manageEndPoint) {
pageReqVO.setOrganId(SecurityFrameworkUtils.getUserOrganId());
}
return success(purchaseService.getPurchaseRecord(pageReqVO));
}
@@ -53,6 +57,11 @@ public class PurchaseController {
@OperateLog(type = EXPORT)
public void billDetailsExport(@Valid PurchaseRecordPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
// 非管理端只能查看本组织数据
boolean manageEndPoint = SecurityFrameworkUtils.isManageEndPoint();
if (!manageEndPoint) {
pageReqVO.setOrganId(SecurityFrameworkUtils.getUserOrganId());
}
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<PurchaseRecordRespVO> list = purchaseService.getPurchaseRecord(pageReqVO).getList();
if (SecurityFrameworkUtils.isManageEndPoint()) {
@@ -17,6 +17,7 @@ import com.cf.imes.module.system.dal.dataobject.organ.OrganizationDO;
import com.cf.imes.module.system.dal.dataobject.organ.TenantPackageDO;
import com.cf.imes.module.system.dal.mysql.organ.TenantPackageMapper;
import com.cf.imes.module.system.enums.pay.DurationUnitEnum;
import com.cf.imes.module.system.enums.pay.PurchaseRecordStatusEnum;
import com.cf.imes.module.system.service.funds.delay.ProductDelayService;
import com.cf.imes.module.system.service.funds.purchase.PurchaseService;
import com.cf.imes.module.system.service.organ.OrganService;
@@ -89,7 +90,7 @@ public class OrganController {
@PutMapping("/update")
@Operation(summary = "更新组织")
@PreAuthorize("@ss.hasPermission('organizationLIst:update')")
public CommonResult<Boolean> updateOrgan(@Valid @RequestBody OrganSaveReqVO updateReqVO) {
public CommonResult<Boolean> updateOrgan(@Validated(OrganSaveUpdateGroup.class) @RequestBody OrganSaveReqVO updateReqVO) {
organService.updateOrgan(updateReqVO);
return success(true);
}
@@ -115,10 +116,13 @@ public class OrganController {
OrganRespVO bean = BeanUtils.toBean(organ, OrganRespVO.class);
Long organId = bean.getId();
// 查询当次列表组织下的所有购记录
List<OrganPagePurchaseRespVO> orgPurchaseList = BeanUtil.copyToList(purchaseService.getOrgPurchaseNotInitialList(Set.of(organId)), OrganPagePurchaseRespVO.class);
// 查询当次列表组织下的所有产品的首购记录
List<OrganPagePurchaseRespVO> orgPurchaseList = BeanUtil.copyToList(
purchaseService.getOrgPurchaseList(Set.of(organId)).stream().filter(p -> p.getInitial()).collect(Collectors.toList()), OrganPagePurchaseRespVO.class
);
// 查询购买记录下的延期记录
orgPurchaseList.forEach(p -> {
p.setPrice(p.getTotalAmount());
List<ProductDelayRespVO> delayRecordsByPurchaseId = productDelayService.getRecordsByPurchaseId(p.getId(), organId);
if (CollUtil.isNotEmpty(delayRecordsByPurchaseId)) {
// 产品有效时间展示为第一项的计算延期时间
@@ -143,7 +147,8 @@ public class OrganController {
Set<Long> organIds = bean.getList().stream().map(OrganRespVO::getId).collect(Collectors.toSet());
// 查询当次列表组织下的所有购买记录
List<PurchaseRecordDO> orgPurchaseList = purchaseService.getOrgPurchaseNotInitialList(organIds);
List<PurchaseRecordDO> orgPurchaseList = purchaseService.getOrgPurchaseList(organIds)
.stream().filter(p -> PurchaseRecordStatusEnum.ACTIVE.getStatus().equals(p.getStatus())).collect(Collectors.toList());
// 匹配到对应的组织下
bean.getList().forEach(e -> {
List<OrganPagePurchaseRespVO> purchaseRespVOList = orgPurchaseList.stream()
@@ -152,6 +157,7 @@ public class OrganController {
.toList();
// 查询购买记录下的延期记录
purchaseRespVOList.forEach(p -> {
p.setPrice(p.getTotalAmount());
List<ProductDelayRespVO> delayRecordsByPurchaseId = productDelayService.getRecordsByPurchaseId(p.getId(), e.getId());
if (CollUtil.isNotEmpty(delayRecordsByPurchaseId)) {
// 产品有效时间展示为第一项的计算延期时间
@@ -13,13 +13,16 @@ import java.math.BigDecimal;
@Data
public class OrganCreateProductPurchaseReqVO {
@Schema(description = "产品编号", example = "1")
@NotNull(message = "产品编号不能为空", groups = {OrganSaveCreateGroup.class})
@NotNull(message = "产品编号不能为空")
private Long productId;
@Schema(description = "产品购买金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
@NotNull(message = "产品购买金额不能为空", groups = {OrganSaveCreateGroup.class})
@NotNull(message = "产品购买金额不能为空")
@DecimalMin(value = "0.01", message = "产品购买金额必须大于零")
@DecimalMax(value = "100000", message = "产品购买金额不能超过十万")
@Digits(integer = 6, fraction = 2, message = "产品购买金额格式不正确")
private BigDecimal price;
@Schema(description = "产品购买编号", example = "1")
private Long purchaseId;
}
@@ -19,6 +19,9 @@ public class OrganPagePurchaseRespVO {
@Schema(description = "购买记录编号")
private Long id;
@Schema(description = "产品编号")
private Long productId;
@Schema(description = "产品名称")
private String productName;
@@ -44,4 +47,6 @@ public class OrganPagePurchaseRespVO {
@JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY)
private LocalDate endTime;
@Schema(description = "订购价格")
private BigDecimal price;
}
@@ -0,0 +1,10 @@
package com.cf.imes.module.system.controller.admin.organ.vo.organ;
/**
* 组织更新请求校验组
*
* @author Gqr
* @since 2025/9/24 16:28
*/
public interface OrganSaveUpdateGroup {
}
@@ -1,20 +1,29 @@
package com.cf.imes.module.system.controller.admin.statistics;
import com.cf.imes.framework.common.pojo.CommonResult;
import com.cf.imes.framework.common.pojo.PageParam;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.module.system.controller.admin.organ.vo.organ.OrganRespVO;
import com.cf.imes.module.system.controller.admin.statistics.vo.ManageOrgTotalStatisticRespVO;
import com.cf.imes.module.system.controller.admin.statistics.vo.ManageSalesTotalStatisticRespVO;
import com.cf.imes.module.system.controller.admin.statistics.vo.ManageUserActTotalStatisticRespVO;
import com.cf.imes.module.system.controller.admin.statistics.vo.ManageUserTotalStatisticRespVO;
import com.cf.imes.module.system.controller.admin.statistics.vo.OrgStatusGroupStatisticsReqVO;
import com.cf.imes.module.system.service.funds.purchase.PurchaseService;
import com.cf.imes.module.system.service.organ.OrganService;
import com.cf.imes.module.system.service.user.AdminUserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
import static com.cf.imes.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - 管理端分析页管理")
@@ -24,15 +33,15 @@ import static com.cf.imes.framework.common.pojo.CommonResult.success;
@Slf4j
public class ManageStatisticsController {
// @Resource
// private OrderSupStatisticsService orderSupStatisticsService;
@Resource
private OrganService organService;
@Resource
private AdminUserService userService;
@Resource
private PurchaseService purchaseService;
@GetMapping("/total/org")
@Operation(summary = "组织总数")
public CommonResult<ManageOrgTotalStatisticRespVO> getOrgTotal() {
@@ -45,42 +54,33 @@ public class ManageStatisticsController {
return success(userService.getUserTotal());
}
@GetMapping("/total/sales")
@Operation(summary = "销售额")
public CommonResult<ManageSalesTotalStatisticRespVO> getSalesTotal() {
return success(purchaseService.getSalesTotalStatistics());
}
@GetMapping("/total/userAct")
@Operation(summary = "用户活跃数")
public CommonResult<ManageUserActTotalStatisticRespVO> getUserActTotal() {
return success(userService.getUserActTotal());
}
// @GetMapping("/total/order")
// @Operation(summary = "生产单总数")
// @PreAuthorize("@ss.hasPermission('homePage:analysis:org-statistic')")
// public CommonResult<Map<String, Integer>> getOrderTotal() {
// return success(orderSupStatisticsService.orderTotal());
// }
//
// @GetMapping("/total/plateArea")
// @Operation(summary = "拆单板件平方数")
// public CommonResult<Map<String, Double>> getPlateAreaTotal() {
// return success(orderSupStatisticsService.plateAreaTotal());
// }
//
// @GetMapping("/separate/order")
// @Operation(summary = "有效、无效生产单数量统计")
// @PreAuthorize("@ss.hasPermission('homePage:analysis:order-count')")
// public CommonResult<Map<String, Object>> getOrderSeparate(@Valid OrderStatisticsReqVO reqVO) {
// return success(orderSupStatisticsService.orderSeparate(reqVO));
// }
//
// @GetMapping("/separate/org")
// @Operation(summary = "新增、注销组织数量统计")
// @PreAuthorize("@ss.hasPermission('homePage:analysis:org-count')")
// public CommonResult<Map<String, Object>> getOrgSeparate(@Valid OrgStatisticsReqDTO reqVO) {
// return organApi.getOrgSeparate(reqVO);
// }
//
// @GetMapping("/warn/org")
// @Operation(summary = "组织过期日期统计")
// public CommonResult<Map<String, List<Object>>> getWarnToOrg() {
// return organApi.getWarnToOrg();
// }
@GetMapping("/org/status/group")
@Operation(summary = "新增、注销组织数量统计")
public CommonResult<Map<String, Object>> getOrgStatusGroupStatistics(@Valid OrgStatusGroupStatisticsReqVO reqVO) {
return success(organService.getOrgStatusGroupStatistics(reqVO));
}
@GetMapping("/org/expiring")
@Operation(summary = "获取即将过期组织分页")
public CommonResult<PageResult<OrganRespVO>> getAboutExpireOrg(@Valid PageParam param) {
return success(organService.getOrgAboutExpire(param));
}
@GetMapping("/org/expired")
@Operation(summary = "获取已过期组织分页")
public CommonResult<PageResult<OrganRespVO>> getExpiredOrg(@Valid PageParam param) {
return success(organService.getOrgExpired(param));
}
}
@@ -0,0 +1,21 @@
package com.cf.imes.module.system.controller.admin.statistics.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
/**
* @author Gqr
* @since 2025/9/29 14:37
*/
@Schema(description = "管理后台 - 管理端销售额统计 Response VO")
@Data
public class ManageSalesTotalStatisticRespVO {
@Schema(description = "当日销售额")
private BigDecimal salesToday;
@Schema(description = "销售总额")
private BigDecimal salesTotal;
}
@@ -0,0 +1,14 @@
package com.cf.imes.module.system.controller.admin.statistics.vo;
import com.cf.imes.framework.common.pojo.CommonStatisticsReqVO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 统计集合 --- 组织数量统计
*/
@Schema(description = "管理后台 - 组织数量统计 Request VO")
@Data
public class OrgStatusGroupStatisticsReqVO extends CommonStatisticsReqVO {
}
@@ -92,6 +92,12 @@ public interface PurchaseRecordMapper extends BaseMapperX<PurchaseRecordDO> {
*/
TotalSalesAmountRespVO getTotalSales();
/**
* 查询当日销售总额
* @return
*/
BigDecimal getTodaySales();
/**
* 查询购买记录中的现金使用金额总数
*
@@ -1,13 +1,16 @@
package com.cf.imes.module.system.dal.mysql.organ;
import cn.hutool.core.text.CharSequenceUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cf.imes.framework.common.pojo.PageParam;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX;
import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.cf.imes.module.executor.enums.OrderDeletedEnum;
import com.cf.imes.module.system.api.organ.dto.OrgStatisticsIsLapseRespDTO;
import com.cf.imes.module.system.api.organ.dto.OrgStatisticsReqDTO;
import com.cf.imes.module.system.controller.admin.organ.vo.organ.OrganPageReqVO;
import com.cf.imes.module.system.controller.admin.statistics.vo.OrgStatusGroupStatisticsReqVO;
import com.cf.imes.module.system.dal.dataobject.organ.OrganizationDO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@@ -105,24 +108,41 @@ public interface OrganMapper extends BaseMapperX<OrganizationDO> {
/**
* 组织按时间统计新增数量
*/
List<OrgStatisticsIsLapseRespDTO> selectOrgCountAddByOrderDate(@Param("req") OrgStatisticsReqDTO reqVO);
List<OrgStatisticsIsLapseRespDTO> selectOrgCountAddByOrderDate(@Param("req") OrgStatusGroupStatisticsReqVO reqVO);
/**
* 组织按时间分组统计注销数量
*/
List<OrgStatisticsIsLapseRespDTO> selectOrgCountLapseByOrderDate(@Param("req") OrgStatisticsReqDTO reqVO);
List<OrgStatisticsIsLapseRespDTO> selectOrgCountLapseByOrderDate(@Param("req") OrgStatusGroupStatisticsReqVO reqVO);
default List<OrganizationDO> selectOrgCountExpire(LocalDateTime today, LocalDateTime afterDay){
return selectList(new LambdaQueryWrapperX<OrganizationDO>()
.eq(OrganizationDO::getDeleted,false)
.between(OrganizationDO::getExpireTime,today,afterDay));
/**
* 分页查询即将过期的组织
* @param param
* @return
*/
default IPage<OrganizationDO> selectOrgCountExpire(PageParam param) {
Page<OrganizationDO> page = new Page<>(param.getPageNo(), param.getPageSize());
LocalDateTime today = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0);
LocalDateTime afterDay = today.plusDays(15).withHour(23).withMinute(59).withSecond(59);
return selectPage(page, new LambdaQueryWrapperX<OrganizationDO>()
.eq(OrganizationDO::getDeleted, false)
.between(OrganizationDO::getExpireTime, today, afterDay)
.orderByDesc(OrganizationDO::getId));
}
default List<OrganizationDO> selectOrgCountExpired(LocalDateTime alertDay){
return selectList(new LambdaQueryWrapperX<OrganizationDO>()
.eq(OrganizationDO::getDeleted,false)
.lt(OrganizationDO::getExpireTime,alertDay));
/**
* 分页查询过期的组织
* @param param
* @return
*/
default IPage<OrganizationDO> selectOrgCountExpired(PageParam param) {
Page<OrganizationDO> page = new Page<>(param.getPageNo(), param.getPageSize());
return selectPage(page, new LambdaQueryWrapperX<OrganizationDO>()
.eq(OrganizationDO::getDeleted, false)
.lt(OrganizationDO::getExpireTime, LocalDateTime.now().withHour(23).withMinute(59).withSecond(59))
.orderByDesc(OrganizationDO::getId));
}
default List<OrganizationDO> selectOrganListByName(String organName) {
return selectList(new LambdaQueryWrapperX<OrganizationDO>()
.eqIfPresent(OrganizationDO::getDeleted,false)
@@ -6,7 +6,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.common.util.Assert.AssertUtils;
import com.cf.imes.framework.common.util.object.BeanUtils;
import com.cf.imes.framework.id.core.util.SnowflakeIdWorker3rd;
import com.cf.imes.framework.id.core.util.SnowflakeSerialNoWorker3rd;
import com.cf.imes.framework.mybatis.core.query.LambdaUpdateWrapperX;
import com.cf.imes.module.system.controller.admin.funds.manualadjust.vo.ManualAdjustAccountBalancePageReqVO;
import com.cf.imes.module.system.controller.admin.funds.manualadjust.vo.ManualAdjustAccountBalanceRespVO;
@@ -73,7 +73,7 @@ public class ManualAdjustAccountBalanceServiceImpl implements ManualAdjustAccoun
private IncomeExpenseDetailsMapper incomeExpenseDetailsMapper;
@Resource
private SnowflakeIdWorker3rd snowflakeIdWorker3rd;
private SnowflakeSerialNoWorker3rd snowflakeSerialNoWorker3rd;
@Override
@Transactional(rollbackFor = Exception.class)
@@ -128,7 +128,7 @@ public class ManualAdjustAccountBalanceServiceImpl implements ManualAdjustAccoun
IncomeExpenseDetailsDO incomeExpenseDetailsDO = IncomeExpenseDetailsDO.builder()
.organId(organId)
.orderNo(payOrderDO.getPayNo())
.businessNo(snowflakeIdWorker3rd.nextSerialNo())
.businessNo(snowflakeSerialNoWorker3rd.nextSerialNo())
.tradeType(TradeTypeEnum.MANUAL_ADJUST.getCode())
.incomeExpenseType(incomeExpenseType)
.cashAmountChange(rechargeAmount)
@@ -47,6 +47,8 @@ import java.util.stream.Collectors;
import static cn.hutool.core.date.DatePattern.NORM_DATETIME_FORMATTER;
import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.cf.imes.framework.common.util.time.StatisticsChangeUtils.generateDateRangeAxis;
import static com.cf.imes.framework.common.util.time.StatisticsChangeUtils.getDateList;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.ORGAN_AMOUNT_NO_EXIST;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.ORGAN_PRODUCT_PAY_AMOUNT_CHANGE_ERROR;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.ORGAN_RECHARGE_AMOUNT_UPDATE_ERROR;
@@ -277,192 +279,6 @@ public class OrganAmountServiceImpl implements OrganAmountService {
return resultMap;
}
/**
* 获取日期区间格式下的所有日期字符串
* 1、reqVO设置机构id
* 2、计算时间跨度设置到reqVO
* 3、返回所有日期的集合
* @param reqVO
* @return
*/
private List<String> getDateList(OrganFundsStatisticsReqVO reqVO) {
// 计算时间跨度
getTimeSpan(reqVO);
// 重新计算开始时间喝结束时间
countTimeSpan(reqVO);
// 所有的日期集合
return generateDateRange(reqVO);
}
/**
* 获取统计的时间跨度
* 计算起止时间:前端不传入时间就根据维度单位从当前日期计算
*
* @param reqVO
*/
private void getTimeSpan(OrganFundsStatisticsReqVO reqVO) {
LocalDate[] createTime = reqVO.getCreateTime();
LocalDate startTime = null;
LocalDate endTime;
LocalDate now = LocalDate.now();
if (ArrayUtil.isEmpty(createTime) || ObjectUtil.isNull(createTime[0]) || ObjectUtil.isNull(createTime[1])) {
endTime = now;
switch (OrderStatisticsUnit.fromValue(reqVO.getUnit())) {
case QUARTER:
// 从now往前的1年
startTime = now.minusYears(1);
break;
case MONTH:
// 包含now往前的12个月
startTime = now.minusMonths(11);
break;
case WEEK:
// 包含now往前的12周
startTime = now.minusWeeks(11);
break;
case DAY:
// 包含now往前的15天
startTime = now.minusDays(14);
break;
default:
break;
}
// 声明一个LocalDateTime的数组,把startTime和endTime放进去
reqVO.setCreateTime(new LocalDate[]{startTime, endTime});
}
}
/**
* 根据传入信息重新计算时间范围
*
* @param reqVO
*/
private void countTimeSpan(OrganFundsStatisticsReqVO reqVO) {
Integer unit = reqVO.getUnit();
// 计算时间跨度
getTimeSpan(reqVO);
// 计算后的开始和结束时间
LocalDate startDate = ObjectUtil.clone(reqVO.getCreateTime()[0]);
LocalDate endDate = ObjectUtil.clone(reqVO.getCreateTime()[1]);
if (startDate.isAfter(endDate)) {
startDate = ObjectUtil.clone(reqVO.getCreateTime()[1]);
endDate = ObjectUtil.clone(reqVO.getCreateTime()[0]);
}
LocalDate first = startDate;
LocalDate end = endDate;
switch (OrderStatisticsUnit.fromValue(unit)) {
case QUARTER -> {
first = firstDayOfQuarter(startDate);
end = lastDayOfQuarter(endDate);
}
case MONTH -> {
first = startDate.with(TemporalAdjusters.firstDayOfMonth());
end = endDate.with(TemporalAdjusters.lastDayOfMonth());
}
case WEEK -> {
first = startDate.with(TemporalAdjusters.previousOrSame(java.time.DayOfWeek.MONDAY));
end = endDate.with(TemporalAdjusters.nextOrSame(java.time.DayOfWeek.SUNDAY));
}
default -> {
return;
}
}
reqVO.setCreateTime(new LocalDate[]{first, end});
}
private LocalDate firstDayOfQuarter(LocalDate date) {
int month = date.getMonthValue();
int quarter = (month - 1) / 3 + 1;
int startMonth = (quarter - 1) * 3 + 1;
return LocalDate.of(date.getYear(), startMonth, 1);
}
private LocalDate lastDayOfQuarter(LocalDate date) {
int month = date.getMonthValue();
int quarter = (month - 1) / 3 + 1;
int endMonth = (quarter - 1) * 3 + 3;
return LocalDate.of(date.getYear(), endMonth, 1).with(TemporalAdjusters.lastDayOfMonth());
}
/**
* 获取日期范围内的所有格式字符串
*
* @param reqVO
* @return
*/
private List<String> generateDateRange(OrganFundsStatisticsReqVO reqVO) {
Integer unit = reqVO.getUnit();
// 计算时间跨度
getTimeSpan(reqVO);
// 计算后的开始和结束时间
LocalDate startDate = ObjectUtil.clone(reqVO.getCreateTime()[0]);
LocalDate endDate = ObjectUtil.clone(reqVO.getCreateTime()[1]);
List<String> dates = new ArrayList<>();
while (!startDate.isAfter(endDate)) {
String dateStr;
switch (OrderStatisticsUnit.fromValue(unit)) {
case QUARTER:
dateStr = startDate.format(DateTimeFormatter.ofPattern("yyyy-Q"));
// 加一季度(3个月)
startDate = startDate.plusMonths(3);
break;
case MONTH:
dateStr = startDate.format(DateTimeFormatter.ofPattern(DATE_TIME_FORMATTER_PATTERN_YEAR_MONTH));
// 加一月
startDate = startDate.plusMonths(1);
break;
case WEEK:
dateStr = startDate.format(DateTimeFormatter.ofPattern("yyyy-M-ww"));
// 加一周
startDate = startDate.plusWeeks(1);
break;
case DAY:
dateStr = startDate.format(DateTimeFormatter.ofPattern(DATE_TIME_FORMATTER_PATTERN_YEAR_MONTH_DAY));
// 加一天
startDate = startDate.plusDays(1);
break;
default:
throw new IllegalArgumentException("Unsupported unit: " + unit);
}
dates.add(dateStr);
}
return dates;
}
/**
* 构建日期格式到图标横轴可用格式
* 2024-1 -> 2024年第1季度
* 2024-1-1 -> 2024年1月
* ...
* @param unit
* @return
*/
private String generateDateRangeAxis(String date, Integer unit) {
OrderStatisticsUnit orderStatisticsUnit = OrderStatisticsUnit.fromValue(unit);
StringBuilder newDateStrBuffer = new StringBuilder();
String[] dateSplit = date.split("-");
switch (orderStatisticsUnit) {
case QUARTER:
newDateStrBuffer.append("").append(dateSplit[1]).append("季度");
break;
case MONTH:
newDateStrBuffer.append(dateSplit[1]).append("");
break;
case WEEK:
newDateStrBuffer.append("").append(dateSplit[2]).append("");
break;
case DAY:
newDateStrBuffer.append(dateSplit[2]).append("");
break;
default:
}
return newDateStrBuffer.toString();
}
@Override
public void fixOrganAmount() {
List<OrganizationDO> organizationDOS = organMapper.selectList(new LambdaQueryWrapper<OrganizationDO>().select(OrganizationDO::getId));
@@ -9,6 +9,7 @@ import com.cf.imes.module.system.controller.admin.funds.purchase.vo.PurchaseReco
import com.cf.imes.module.system.controller.admin.funds.purchase.vo.SalesDetailRespVO;
import com.cf.imes.module.system.controller.admin.funds.purchase.vo.SalesDetailsPageReqVO;
import com.cf.imes.module.system.controller.admin.organ.vo.organ.OrganCreateProductPurchaseReqVO;
import com.cf.imes.module.system.controller.admin.statistics.vo.ManageSalesTotalStatisticRespVO;
import com.cf.imes.module.system.dal.dataobject.funds.purchase.PurchaseRecordDO;
import java.math.BigDecimal;
@@ -82,12 +83,20 @@ public interface PurchaseService {
void createOrgInitProductPurchaseRecord(Long organId, List<OrganCreateProductPurchaseReqVO> productPurchaseReqVOS);
/**
* 查询组织下的非首购的产品购买记录
* 更新组织首购记录
*
* @param organId
* @param productPurchaseReqVOS
*/
void updateOrgInitProductPurchaseRecord(Long organId, List<OrganCreateProductPurchaseReqVO> productPurchaseReqVOS);
/**
* 查询组织下产品购买记录
*
* @param organIds
* @return
*/
List<PurchaseRecordDO> getOrgPurchaseNotInitialList(Set<Long> organIds);
List<PurchaseRecordDO> getOrgPurchaseList(Set<Long> organIds);
/**
* 查询销售总额
@@ -148,4 +157,10 @@ public interface PurchaseService {
* @param purchaseRecordId
*/
void activateHistoryOrganProductPurchaseRecord(Long organId, Long purchaseRecordId);
/**
* 管理端获取销售总额统计
* @return
*/
ManageSalesTotalStatisticRespVO getSalesTotalStatistics();
}
@@ -6,6 +6,7 @@ import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.cf.imes.framework.common.exception.ServiceException;
import com.cf.imes.framework.common.exception.util.ServiceExceptionUtil;
import com.cf.imes.framework.common.pojo.PageParam;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.common.util.date.LocalDateTimeUtils;
@@ -20,6 +21,7 @@ import com.cf.imes.module.system.controller.admin.funds.purchase.vo.PurchaseReco
import com.cf.imes.module.system.controller.admin.funds.purchase.vo.SalesDetailRespVO;
import com.cf.imes.module.system.controller.admin.funds.purchase.vo.SalesDetailsPageReqVO;
import com.cf.imes.module.system.controller.admin.organ.vo.organ.OrganCreateProductPurchaseReqVO;
import com.cf.imes.module.system.controller.admin.statistics.vo.ManageSalesTotalStatisticRespVO;
import com.cf.imes.module.system.dal.dataobject.funds.products.ProductsDO;
import com.cf.imes.module.system.dal.dataobject.funds.products.ProductsDetailDO;
import com.cf.imes.module.system.dal.dataobject.funds.purchase.PurchaseRecordDO;
@@ -44,8 +46,13 @@ import java.math.RoundingMode;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.ORG_PRODUCT_PURCHASE_EXIST_ERROR;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.ORG_PRODUCT_PURCHASE_NOT_EXIST_ERROR;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.PRODUCT_PRICE_NULL_ERROR;
import static com.cf.imes.module.system.enums.pay.PayConstants.PAY_PRODUCT_DETAIL_AUTO_GENERATE_MONTH_ID_FORMAT;
@@ -187,10 +194,80 @@ public class PurchaseServiceImpl implements PurchaseService {
}
@Override
public List<PurchaseRecordDO> getOrgPurchaseNotInitialList(Set<Long> organIds) {
public void updateOrgInitProductPurchaseRecord(Long organId, List<OrganCreateProductPurchaseReqVO> productPurchaseReqVOS) {
// 1、查询组织下的产品首购记录
List<PurchaseRecordDO> currOrgProductInitialPurchaseList = purchaseRecordMapper.selectList(new LambdaQueryWrapper<PurchaseRecordDO>()
.eq(PurchaseRecordDO::getOrganId, organId)
.eq(PurchaseRecordDO::getInitial, true)
.eq(PurchaseRecordDO::getDeleted, false));
// 2、入参整理为新增列表和修改列表
List<OrganCreateProductPurchaseReqVO> createList = productPurchaseReqVOS.stream().filter(purchaseReqVO -> ObjectUtil.isNull(purchaseReqVO.getPurchaseId())).collect(Collectors.toList());
List<OrganCreateProductPurchaseReqVO> updateList = productPurchaseReqVOS.stream().filter(purchaseReqVO -> ObjectUtil.isNotNull(purchaseReqVO.getPurchaseId())).collect(Collectors.toList());
// 3、筛选出修改列表和当前记录中有差集的部分提示首购不存在
Set<Long> currPurchaseIds = currOrgProductInitialPurchaseList.stream()
.map(PurchaseRecordDO::getId)
.collect(Collectors.toSet());
boolean updateNotExist = updateList.stream()
.map(OrganCreateProductPurchaseReqVO::getPurchaseId)
.anyMatch(purchaseId -> !currPurchaseIds.contains(purchaseId));
if (updateNotExist) {
throw new ServiceException(ORG_PRODUCT_PURCHASE_NOT_EXIST_ERROR);
}
// 4、筛选出新增列表和当前记录中有产品id重复的提示订购记录已存在
Map<Long, String> currProductMap = currOrgProductInitialPurchaseList.stream()
.collect(Collectors.toMap(PurchaseRecordDO::getProductId, PurchaseRecordDO::getProductName));
Optional<OrganCreateProductPurchaseReqVO> duplicateOpt = createList.stream()
.filter(req -> currProductMap.containsKey(req.getProductId()))
.findFirst();
if (duplicateOpt.isPresent()) {
throw ServiceExceptionUtil.exception(ORG_PRODUCT_PURCHASE_EXIST_ERROR, currProductMap.get(duplicateOpt.get().getProductId()));
}
// 5、删选出当前记录和入参列表中purchaseId不重复的,作为删除的部分
Set<Long> inputPurchaseIds = updateList.stream().map(OrganCreateProductPurchaseReqVO::getPurchaseId).collect(Collectors.toSet());
List<Long> deleteIdList = currOrgProductInitialPurchaseList.stream()
.filter(record -> !inputPurchaseIds.contains(record.getId()))
.map(PurchaseRecordDO::getId)
.collect(Collectors.toList());
// 6、修改
for (OrganCreateProductPurchaseReqVO purchaseReqVO : updateList) {
// 购买记录id
Long purchaseId = purchaseReqVO.getPurchaseId();
// 订购价格
BigDecimal price = purchaseReqVO.getPrice();
// 2、更新购买记录的订购价格
purchaseRecordMapper.update(new LambdaUpdateWrapper<PurchaseRecordDO>()
.eq(PurchaseRecordDO::getId, purchaseId)
.eq(PurchaseRecordDO::getOrganId, organId)
.eq(PurchaseRecordDO::getInitial, true)
.set(PurchaseRecordDO::getTotalAmount, price)
.set(PurchaseRecordDO::getMonthAverageAmount, price.divide(new BigDecimal(10), 2, RoundingMode.DOWN))
.set(PurchaseRecordDO::getOriginalAmount, price));
}
// 7、新增
if (CollUtil.isNotEmpty(createList)) {
createOrgInitProductPurchaseRecord(organId, createList);
}
// 8、删除
if (CollUtil.isNotEmpty(deleteIdList)) {
purchaseRecordMapper.deleteByIds(deleteIdList);
}
}
@Override
public List<PurchaseRecordDO> getOrgPurchaseList(Set<Long> organIds) {
return purchaseRecordMapper.selectList(new LambdaQueryWrapper<PurchaseRecordDO>()
.in(PurchaseRecordDO::getOrganId, organIds)
.eq(PurchaseRecordDO::getStatus, PurchaseRecordStatusEnum.ACTIVE.getStatus())
.eq(PurchaseRecordDO::getDeleted, false));
}
@@ -384,4 +461,12 @@ public class PurchaseServiceImpl implements PurchaseService {
.eq(PurchaseRecordDO::getDeleted, false)
.set(PurchaseRecordDO::getStatus, PurchaseRecordStatusEnum.ACTIVE.getStatus()));
}
@Override
public ManageSalesTotalStatisticRespVO getSalesTotalStatistics() {
ManageSalesTotalStatisticRespVO respVO = new ManageSalesTotalStatisticRespVO();
respVO.setSalesTotal(purchaseRecordMapper.getTotalSales().getAmount());
respVO.setSalesToday(purchaseRecordMapper.getTodaySales());
return respVO;
}
}
@@ -1,20 +1,20 @@
package com.cf.imes.module.system.service.organ;
import com.cf.imes.framework.common.pojo.PageParam;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.organ.core.context.OrganContextHolder;
import com.cf.imes.module.system.api.organ.dto.OrgStatisticsIsLapseRespDTO;
import com.cf.imes.module.system.api.organ.dto.OrgStatisticsReqDTO;
import com.cf.imes.module.system.controller.admin.organ.vo.organ.OrganPageReqVO;
import com.cf.imes.module.system.controller.admin.organ.vo.organ.OrganRespVO;
import com.cf.imes.module.system.controller.admin.organ.vo.organ.OrganSaveReqVO;
import com.cf.imes.module.system.controller.admin.organ.vo.organ.OrganSimpleRespVO;
import com.cf.imes.module.system.controller.admin.statistics.vo.ManageOrgTotalStatisticRespVO;
import com.cf.imes.module.system.controller.admin.statistics.vo.OrgStatusGroupStatisticsReqVO;
import com.cf.imes.module.system.dal.dataobject.organ.OrganizationDO;
import com.cf.imes.module.system.service.organ.handler.OrganInfoHandler;
import com.cf.imes.module.system.service.organ.handler.OrganMenuHandler;
import jakarta.validation.Valid;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -150,23 +150,25 @@ public interface OrganService {
*/
ManageOrgTotalStatisticRespVO getOrgTotal();
/**
* 组织新增统计
*/
List<OrgStatisticsIsLapseRespDTO> orgCountAddByOrderDateAdd(OrgStatisticsReqDTO reqVO);
/**
* 组织注销统计
*/
List<OrgStatisticsIsLapseRespDTO> orgCountLapseByOrderDate(OrgStatisticsReqDTO reqVO);
/**
* 即将过期组织统计
*
* @param param 分页参数
*/
List<OrganRespVO> orgCountExpire(LocalDateTime today, LocalDateTime afterDay);
PageResult<OrganRespVO> getOrgAboutExpire(PageParam param);
/**
* 已过期组织统计
*
* @param param 分页参数
*/
List<OrganRespVO> orgCountExpired(LocalDateTime alertDay);
PageResult<OrganRespVO> getOrgExpired(PageParam param);
/**
* 查询新增、注销组织数量统计
*
* @param reqVO
* @return
*/
Map<String, Object> getOrgStatusGroupStatistics(OrgStatusGroupStatisticsReqVO reqVO);
}
@@ -6,9 +6,10 @@ import cn.hutool.core.lang.Assert;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.cf.imes.framework.common.enums.CommonStatusEnum;
import com.cf.imes.framework.common.pojo.PageParam;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.common.util.Assert.AssertUtils;
import com.cf.imes.framework.common.util.collection.CollectionUtils;
import com.cf.imes.framework.common.util.date.DateUtils;
import com.cf.imes.framework.common.util.json.JsonUtils;
@@ -20,7 +21,6 @@ import com.cf.imes.framework.organ.core.context.OrganContextHolder;
import com.cf.imes.framework.organ.core.util.OrganUtils;
import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils;
import com.cf.imes.module.system.api.organ.dto.OrgStatisticsIsLapseRespDTO;
import com.cf.imes.module.system.api.organ.dto.OrgStatisticsReqDTO;
import com.cf.imes.module.system.constants.permission.InternalRoleConstants;
import com.cf.imes.module.system.controller.admin.organ.vo.organ.OrganCreateProductPurchaseReqVO;
import com.cf.imes.module.system.controller.admin.organ.vo.organ.OrganPageReqVO;
@@ -28,6 +28,7 @@ import com.cf.imes.module.system.controller.admin.organ.vo.organ.OrganRespVO;
import com.cf.imes.module.system.controller.admin.organ.vo.organ.OrganSaveReqVO;
import com.cf.imes.module.system.controller.admin.organ.vo.organ.OrganSimpleRespVO;
import com.cf.imes.module.system.controller.admin.statistics.vo.ManageOrgTotalStatisticRespVO;
import com.cf.imes.module.system.controller.admin.statistics.vo.OrgStatusGroupStatisticsReqVO;
import com.cf.imes.module.system.controller.admin.systemconfig.vo.ProcessSchemeConfig;
import com.cf.imes.module.system.controller.admin.tokenconfig.vo.JwtConfig;
import com.cf.imes.module.system.controller.admin.user.vo.user.UserSaveReqVO;
@@ -72,12 +73,14 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import jakarta.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.cf.imes.framework.common.util.json.JsonUtils.parseArray;
import static com.cf.imes.framework.common.util.time.StatisticsChangeUtils.generateDateRangeAxis;
import static com.cf.imes.framework.common.util.time.StatisticsChangeUtils.getDateList;
import static com.cf.imes.module.system.dal.redis.RedisKeyConstants.OAUTH2_ACCESS_TOKEN;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.*;
import static com.cf.imes.module.system.service.tokenconfig.TokenConfigServiceImpl.generateBaseToken;
@@ -243,7 +246,6 @@ public class OrganServiceImpl implements OrganService {
// 创建产品购买记录
List<OrganCreateProductPurchaseReqVO> productPurchaseReqVOS = createReqVO.getProductPurchaseReqVOS();
AssertUtils.notEmpty(productPurchaseReqVOS, ORGAN_CREATE_PRODUCTLIST_EMPTY_ERROR);
// 根据productId去重,初次订购每个产品只能有一种订购
productPurchaseReqVOS = productPurchaseReqVOS.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(OrganCreateProductPurchaseReqVO::getProductId))), ArrayList::new));
purchaseService.createOrgInitProductPurchaseRecord(organId, productPurchaseReqVOS);
@@ -301,6 +303,9 @@ public class OrganServiceImpl implements OrganService {
OrganizationDO updateObj = BeanUtils.toBean(updateReqVO, OrganizationDO.class);
organMapper.updateById(updateObj);
// 更新产品购买记录
purchaseService.updateOrgInitProductPurchaseRecord(organId, updateReqVO.getProductPurchaseReqVOS());
if (CommonStatusEnum.DISABLE.getStatus().equals(updateReqVO.getStatus())) {
// 移除机构下用户的token
scanAndCompareDeptAndDelToken(String.format(OAUTH2_ACCESS_TOKEN, "*"), organId);
@@ -542,28 +547,17 @@ public class OrganServiceImpl implements OrganService {
}
@Override
public List<OrgStatisticsIsLapseRespDTO> orgCountAddByOrderDateAdd(OrgStatisticsReqDTO reqVO) {
return organMapper.selectOrgCountAddByOrderDate(reqVO);
public PageResult<OrganRespVO> getOrgAboutExpire(PageParam param) {
IPage<OrganizationDO> organPage = organMapper.selectOrgCountExpire(param);
return new PageResult<>(BeanUtils.toBean(organPage.getRecords(), OrganRespVO.class), organPage.getTotal());
}
@Override
public List<OrgStatisticsIsLapseRespDTO> orgCountLapseByOrderDate(OrgStatisticsReqDTO reqVO) {
return organMapper.selectOrgCountLapseByOrderDate(reqVO);
public PageResult<OrganRespVO> getOrgExpired(PageParam param) {
IPage<OrganizationDO> organPage = organMapper.selectOrgCountExpired(param);
return new PageResult<>(BeanUtils.toBean(organPage.getRecords(), OrganRespVO.class), organPage.getTotal());
}
@Override
public List<OrganRespVO> orgCountExpire(LocalDateTime today, LocalDateTime afterDay) {
return BeanUtils.toBean(organMapper.selectOrgCountExpire(today, afterDay), OrganRespVO.class);
}
@Override
public List<OrganRespVO> orgCountExpired(LocalDateTime alertDay) {
return BeanUtils.toBean(organMapper.selectOrgCountExpired(alertDay), OrganRespVO.class);
}
// 系统配置数据复制
private void copySystemConfig(Long organId) {
@@ -747,6 +741,45 @@ public class OrganServiceImpl implements OrganService {
}
}
@Override
public Map<String, Object> getOrgStatusGroupStatistics(OrgStatusGroupStatisticsReqVO reqVO) {
Map<String, Object> resultMap = new LinkedHashMap<>();
// 所有的日期集合
List<String> dateList = getDateList(reqVO);
// 组织有效数量
Map<String, List<OrgStatisticsIsLapseRespDTO>> orderNotLapseRespMap = organMapper.selectOrgCountAddByOrderDate(reqVO).stream()
.sorted(Comparator.naturalOrder())
.collect(Collectors.groupingBy(OrgStatisticsIsLapseRespDTO::getDate, LinkedHashMap::new, Collectors.toList()));
// 组织无效数量
Map<String, List<OrgStatisticsIsLapseRespDTO>> orderLapseRespMap = organMapper.selectOrgCountLapseByOrderDate(reqVO).stream()
.sorted(Comparator.naturalOrder())
.collect(Collectors.groupingBy(OrgStatisticsIsLapseRespDTO::getDate, LinkedHashMap::new, Collectors.toList()));
// 遍历时间跨度列表,匹配数量存入数组,没有补0存入数组
for (String dateStr : dateList) {
int[] countArr = new int[2];
// 组织有效数量
Integer orderNotLapseCount = Optional.ofNullable(orderNotLapseRespMap.get(dateStr))
.map(list -> list.stream().findFirst().orElse(new OrgStatisticsIsLapseRespDTO()))
.map(OrgStatisticsIsLapseRespDTO::getOrgCount)
.orElse(0);
countArr[0] = orderNotLapseCount;
// 组织无效数量
Integer orderLapseCount = Optional.ofNullable(orderLapseRespMap.get(dateStr))
.map(list -> list.stream().findFirst().orElse(new OrgStatisticsIsLapseRespDTO()))
.map(OrgStatisticsIsLapseRespDTO::getOrgCount)
.orElse(0);
countArr[1] = orderLapseCount;
resultMap.put(generateDateRangeAxis(dateStr, reqVO.getUnit()), countArr);
}
return resultMap;
}
}
@@ -18,7 +18,7 @@ import com.cf.imes.framework.common.util.Assert.AssertUtils;
import com.cf.imes.framework.common.util.json.JsonUtils;
import com.cf.imes.framework.common.util.object.BeanUtils;
import com.cf.imes.framework.common.util.validation.ValidationUtils;
import com.cf.imes.framework.id.core.util.SnowflakeIdWorker3rd;
import com.cf.imes.framework.id.core.util.SnowflakeSerialNoWorker3rd;
import com.cf.imes.framework.organ.core.context.OrganContextHolder;
import com.cf.imes.framework.pay.config.ChenfengAlipayConfig;
import com.cf.imes.framework.pay.config.ChenfengPayConfig;
@@ -164,7 +164,7 @@ public class PayOrderServiceImpl implements PayOrderService {
private TransactionTemplate transactionTemplate;
@Resource
private SnowflakeIdWorker3rd snowflakeIdWorker3rd;
private SnowflakeSerialNoWorker3rd snowflakeSerialNoWorker3rd;
@Override
@Transactional(rollbackFor = Exception.class)
@@ -209,7 +209,7 @@ public class PayOrderServiceImpl implements PayOrderService {
PreviouProductDelayRespVO previouProductDelayRespVO = productDelayService.getActiveRecordsByProductId(productId, organId);
// 根据购买类型做价格处理
PayProductProcessor payProductProcessor = new PayProductProcessor(productsDO, productsDetailDO, orgInitialPurchaseRecord, previouProductDelayRespVO, organAmount, organId, payConfig, mybatisIdProperties, snowflakeIdWorker3rd);
PayProductProcessor payProductProcessor = new PayProductProcessor(productsDO, productsDetailDO, orgInitialPurchaseRecord, previouProductDelayRespVO, organAmount, organId, payConfig, mybatisIdProperties, snowflakeSerialNoWorker3rd);
ProductProcessorRespVO productProcessorRespVO = payProductProcessor.processPayment(PayProductChannelCodeEnum.fromType(payProductOrderUnifiedReqVO.getProductChannelCode()));
PayOrderDO payOrder = productProcessorRespVO.getPayOrderDO();
@@ -622,7 +622,7 @@ public class PayOrderServiceImpl implements PayOrderService {
IncomeExpenseDetailsDO incomeExpenseDetailsDO = IncomeExpenseDetailsDO.builder()
.organId(organId)
.orderNo(payNo)
.businessNo(snowflakeIdWorker3rd.nextSerialNo())
.businessNo(snowflakeSerialNoWorker3rd.nextSerialNo())
.tradeType(TradeTypeEnum.RECHARGE.getCode())
.incomeExpenseType(IncomeExpenseTypeEnum.INCOME.getCode())
.cashAmountChange(price)
@@ -757,7 +757,7 @@ public class PayOrderServiceImpl implements PayOrderService {
IncomeExpenseDetailsDO incomeExpenseDetailsDO = IncomeExpenseDetailsDO.builder()
.organId(organId)
.orderNo(String.valueOf(record.getId()))
.businessNo(snowflakeIdWorker3rd.nextSerialNo())
.businessNo(snowflakeSerialNoWorker3rd.nextSerialNo())
.tradeType(TradeTypeEnum.PRODUCT.getCode())
.incomeExpenseType(IncomeExpenseTypeEnum.INCOME.getCode())
.cashAmountChange(accountBalanceSpent)
@@ -8,8 +8,7 @@ import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.cf.imes.framework.common.exception.ServiceException;
import com.cf.imes.framework.common.exception.util.ServiceExceptionUtil;
import com.cf.imes.framework.common.util.date.LocalDateTimeUtils;
import com.cf.imes.framework.id.core.util.SnowflakeIdWorker3rd;
import com.cf.imes.framework.id.core.util.SnowflakeSerialNoWorker3rd;
import com.cf.imes.framework.pay.config.ChenfengPayConfig;
import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils;
import com.cf.imes.module.system.controller.admin.funds.delay.vo.PreviouProductDelayRespVO;
@@ -78,7 +77,7 @@ public class PayProductProcessor {
private MybatisIdProperties mybatisIdProperties;
// id生成器
private SnowflakeIdWorker3rd snowflakeIdWorker3rd;
private SnowflakeSerialNoWorker3rd snowflakeSerialNoWorker3rd;
// 标记本次订购是否首次
private boolean initialized = false;
@@ -102,7 +101,7 @@ public class PayProductProcessor {
private BigDecimal originalPrice;
public PayProductProcessor(ProductsDO productsDO, ProductsDetailDO productsDetailDO, PurchaseRecordDO orgInitialPurchaseRecord, PreviouProductDelayRespVO previouProductDelayRespVO,
OrganAmountDO organAmountDO, Long organId, ChenfengPayConfig payConfig, MybatisIdProperties mybatisIdProperties, SnowflakeIdWorker3rd snowflakeIdWorker3rd) {
OrganAmountDO organAmountDO, Long organId, ChenfengPayConfig payConfig, MybatisIdProperties mybatisIdProperties, SnowflakeSerialNoWorker3rd snowflakeSerialNoWorker3rd) {
this.productsDO = productsDO;
this.productsDetailDO = productsDetailDO;
this.orgInitialPurchaseRecord = orgInitialPurchaseRecord;
@@ -117,7 +116,7 @@ public class PayProductProcessor {
this.organId = organId;
this.payConfig = payConfig;
this.mybatisIdProperties = mybatisIdProperties;
this.snowflakeIdWorker3rd = snowflakeIdWorker3rd;
this.snowflakeSerialNoWorker3rd = snowflakeSerialNoWorker3rd;
}
/**
@@ -210,7 +209,7 @@ public class PayProductProcessor {
BigDecimal giftAmount = organAmountDO.getGiftAmount();
IncomeExpenseDetailsDO incomeExpenseDetailsDO = IncomeExpenseDetailsDO.builder()
.organId(organId)
.businessNo(snowflakeIdWorker3rd.nextSerialNo())
.businessNo(snowflakeSerialNoWorker3rd.nextSerialNo())
.orderNo(String.format(PayConstants.PAY_PRODUCT_DETAIL_BUSINESSNO_PREFIX_FORMAT, organId, purchaseId))
.purchaseId(purchaseRecordDO.getId())
.tradeType(TradeTypeEnum.PRODUCT.getCode())
@@ -268,7 +267,7 @@ public class PayProductProcessor {
BigDecimal amount = organAmountDO.getAmount();
IncomeExpenseDetailsDO incomeExpenseDetailsDO = IncomeExpenseDetailsDO.builder()
.organId(organId)
.businessNo(snowflakeIdWorker3rd.nextSerialNo())
.businessNo(snowflakeSerialNoWorker3rd.nextSerialNo())
.orderNo(String.format(PayConstants.PAY_PRODUCT_DETAIL_BUSINESSNO_PREFIX_FORMAT, organId, purchaseId))
.purchaseId(purchaseRecordDO.getId())
.tradeType(TradeTypeEnum.PRODUCT.getCode())
@@ -421,7 +420,7 @@ public class PayProductProcessor {
BigDecimal newGift = gift.subtract(usedGift);
IncomeExpenseDetailsDO incomeExpenseDetailsDO = IncomeExpenseDetailsDO.builder()
.organId(organId)
.businessNo(snowflakeIdWorker3rd.nextSerialNo())
.businessNo(snowflakeSerialNoWorker3rd.nextSerialNo())
.orderNo(String.format(PayConstants.PAY_PRODUCT_DETAIL_BUSINESSNO_PREFIX_FORMAT, organId, purchaseId))
.purchaseId(purchaseRecordDO.getId())
.tradeType(TradeTypeEnum.PRODUCT.getCode())
@@ -486,7 +485,7 @@ public class PayProductProcessor {
BigDecimal giftAmount = organAmountDO.getGiftAmount();
IncomeExpenseDetailsDO incomeExpenseDetailsDO = IncomeExpenseDetailsDO.builder()
.organId(organId)
.businessNo(snowflakeIdWorker3rd.nextSerialNo())
.businessNo(snowflakeSerialNoWorker3rd.nextSerialNo())
.orderNo(String.format(PayConstants.PAY_PRODUCT_DETAIL_BUSINESSNO_PREFIX_FORMAT, organId, purchaseId))
.purchaseId(purchaseRecordDO.getId())
.tradeType(TradeTypeEnum.PRODUCT.getCode())
@@ -563,7 +562,7 @@ public class PayProductProcessor {
BigDecimal amount = organAmountDO.getAmount();
IncomeExpenseDetailsDO incomeExpenseDetailsDO = IncomeExpenseDetailsDO.builder()
.organId(organId)
.businessNo(snowflakeIdWorker3rd.nextSerialNo())
.businessNo(snowflakeSerialNoWorker3rd.nextSerialNo())
.orderNo(String.format(PayConstants.PAY_PRODUCT_DETAIL_BUSINESSNO_PREFIX_FORMAT, organId, purchaseId))
.purchaseId(purchaseId)
.tradeType(TradeTypeEnum.PRODUCT.getCode())
@@ -649,7 +648,7 @@ public class PayProductProcessor {
BigDecimal newGift = gift.subtract(usedGift);
IncomeExpenseDetailsDO incomeExpenseDetailsDO = IncomeExpenseDetailsDO.builder()
.organId(organId)
.businessNo(snowflakeIdWorker3rd.nextSerialNo())
.businessNo(snowflakeSerialNoWorker3rd.nextSerialNo())
.orderNo(String.format(PayConstants.PAY_PRODUCT_DETAIL_BUSINESSNO_PREFIX_FORMAT, organId, purchaseId))
.purchaseId(purchaseId)
.tradeType(TradeTypeEnum.PRODUCT.getCode())
@@ -61,6 +61,16 @@
where deleted = false and initial != true;
</select>
<select id="getTodaySales"
resultType="java.math.BigDecimal">
select
sum(total_amount - gift_money_spent) as amount
from purchase_record
where deleted = false and initial != true
and create_time &gt;= CURDATE()
and create_time &lt; CURDATE() + INTERVAL 1 DAY;
</select>
<select id="getTotalRechargeUsageAmount" resultType="java.math.BigDecimal">
select sum(account_balance_spent)
from purchase_record