mirror of
http://192.168.1.205:9980/cf_devdept2/cf_imes_server.git
synced 2026-08-12 21:02:08 +08:00
1、收支明细流水号生成方式修正,新增yyyyMMddHHmmss+7位顺序号的流水号的公用生成方式;2、管理端分析页组织总数/用户总数/用户活跃数迁移到system;3、组织管理查询首购记录不展示问题恢复;
This commit is contained in:
+4
@@ -22,4 +22,8 @@ public class MinuteCounter {
|
||||
atom.set(newValue & MASK);
|
||||
}
|
||||
|
||||
public boolean compareAndSet(int expect, int update) {
|
||||
return atom.compareAndSet(expect, update & MASK);
|
||||
}
|
||||
|
||||
}
|
||||
+39
@@ -4,6 +4,9 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* @ClassName: SnowflakeIdWorker3rd
|
||||
@@ -36,6 +39,10 @@ public class SnowflakeIdWorker3rd {
|
||||
private final MinuteCounter counter = new MinuteCounter();
|
||||
/** 预支时间标志 */
|
||||
boolean isAdvance = false;
|
||||
/** 时间格式 */
|
||||
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyMMddHHmmss");
|
||||
/** 上次时间格式 */
|
||||
private final AtomicReference<String> lastTimestampStr = new AtomicReference<>("");
|
||||
|
||||
// ==============================Constructors=====================================
|
||||
|
||||
@@ -127,4 +134,36 @@ public class SnowflakeIdWorker3rd {
|
||||
return Integer.valueOf(timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下一个流水号
|
||||
*
|
||||
* @return SerialNo
|
||||
*/
|
||||
public String nextSerialNo() {
|
||||
String now = LocalDateTime.now().format(FORMATTER);
|
||||
|
||||
// 跨秒重置序列号
|
||||
String last = lastTimestampStr.get();
|
||||
if (!now.equals(last)) {
|
||||
// 仅在跨秒时重置序列号
|
||||
if (lastTimestampStr.compareAndSet(last, now)) {
|
||||
counter.set(0);
|
||||
}
|
||||
}
|
||||
|
||||
// 原子递增序列号
|
||||
int seq = counter.incrementAndGet();
|
||||
|
||||
// 序列号100000(5位)以内
|
||||
if (seq > 9999) {
|
||||
if (counter.compareAndSet(seq, 1)) {
|
||||
seq = 1;
|
||||
} else {
|
||||
seq = counter.incrementAndGet();
|
||||
}
|
||||
}
|
||||
|
||||
// 拼接时间 + 序列号
|
||||
return String.format("%s%05d", now, seq);
|
||||
}
|
||||
}
|
||||
|
||||
-31
@@ -5,7 +5,6 @@ import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderStatisti
|
||||
import com.cf.imes.module.executor.service.order.OrderSupStatisticsService;
|
||||
import com.cf.imes.module.system.api.organ.OrganApi;
|
||||
import com.cf.imes.module.system.api.organ.dto.OrgStatisticsReqDTO;
|
||||
import com.cf.imes.module.system.api.user.AdminUserApi;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -35,30 +34,6 @@ public class OrderSupStatisticsController {
|
||||
@Resource
|
||||
private OrganApi organApi;
|
||||
|
||||
@Resource
|
||||
private AdminUserApi adminUserApi;
|
||||
|
||||
@GetMapping("/total/org")
|
||||
@Operation(summary = "组织总数")
|
||||
@PreAuthorize("@ss.hasPermission('homePage:analysis:org-statistic')")
|
||||
public CommonResult<Map<String, Integer>> getOrgTotal() {
|
||||
return success(organApi.getOrgTotal().getData());
|
||||
}
|
||||
|
||||
@GetMapping("/total/user")
|
||||
@Operation(summary = "用户总数")
|
||||
@PreAuthorize("@ss.hasPermission('homePage:analysis:org-statistic')")
|
||||
public CommonResult<Map<String, Integer>> getUserTotal() {
|
||||
return success(adminUserApi.getUserTotal().getData());
|
||||
}
|
||||
|
||||
@GetMapping("/total/userAct")
|
||||
@Operation(summary = "用户活跃数")
|
||||
@PreAuthorize("@ss.hasPermission('homePage:analysis:org-statistic')")
|
||||
public CommonResult<Map<String, Integer>> getUserActTotal() {
|
||||
return success(adminUserApi.getUserActTotal().getData());
|
||||
}
|
||||
|
||||
@GetMapping("/total/order")
|
||||
@Operation(summary = "生产单总数")
|
||||
@PreAuthorize("@ss.hasPermission('homePage:analysis:org-statistic')")
|
||||
@@ -86,12 +61,6 @@ public class OrderSupStatisticsController {
|
||||
return organApi.getOrgSeparate(reqVO);
|
||||
}
|
||||
|
||||
@GetMapping("/separate/plateArea")
|
||||
@Operation(summary = "有效、无效拆单板件平方统计")
|
||||
public CommonResult<Map<String, Object>> getPlateAreaSeparate(@Valid OrderStatisticsReqVO reqVO) {
|
||||
return success(orderSupStatisticsService.plateAreaSeparate(reqVO));
|
||||
}
|
||||
|
||||
@GetMapping("/warn/org")
|
||||
@Operation(summary = "组织过期日期统计")
|
||||
public CommonResult<Map<String, List<Object>>> getWarnToOrg() {
|
||||
|
||||
-11
@@ -1,7 +1,6 @@
|
||||
package com.cf.imes.module.executor.dal.mysql.order;
|
||||
|
||||
import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderStatisticsAreaRespVO;
|
||||
import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderStatisticsIsLapseRespVO;
|
||||
import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderStatisticsReqVO;
|
||||
import com.cf.imes.module.executor.dal.dataobject.order.OrderDO;
|
||||
@@ -28,14 +27,4 @@ public interface OrderSupStatisticsMapper extends BaseMapperX<OrderDO> {
|
||||
* 生产单按时间分组统计未失效数量
|
||||
*/
|
||||
List<OrderStatisticsIsLapseRespVO> selectOrderCountNotLapseByOrderDate(@Param("req") OrderStatisticsReqVO reqVO);
|
||||
|
||||
/**
|
||||
* 生产单按时间统计无效板件平方数
|
||||
*/
|
||||
List<OrderStatisticsAreaRespVO> selectPlateAreaLapseByOrderDate(@Param("req") OrderStatisticsReqVO reqVO);
|
||||
|
||||
/**
|
||||
* 生产单按时间分组统计有效板件平方数
|
||||
*/
|
||||
List<OrderStatisticsAreaRespVO> selectPlateAreaNotLapseByOrderDate(@Param("req") OrderStatisticsReqVO reqVO);
|
||||
}
|
||||
|
||||
-5
@@ -23,9 +23,4 @@ public interface OrderSupStatisticsService {
|
||||
* 有效、无效生产单数量统计
|
||||
*/
|
||||
Map<String, Object> orderSeparate(OrderStatisticsReqVO reqVO);
|
||||
|
||||
/**
|
||||
* 有效、无效拆单板件平方统计
|
||||
*/
|
||||
Map<String, Object> plateAreaSeparate(OrderStatisticsReqVO reqVO);
|
||||
}
|
||||
|
||||
-50
@@ -3,17 +3,14 @@ package com.cf.imes.module.executor.service.order;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.cf.imes.framework.common.enums.OrderStatisticsUnit;
|
||||
import com.cf.imes.framework.organ.core.aop.OrganIgnore;
|
||||
import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderStatisticsAreaRespVO;
|
||||
import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderStatisticsIsLapseRespVO;
|
||||
import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderStatisticsReqVO;
|
||||
import com.cf.imes.module.executor.dal.mysql.order.OrderStatisticsMapper;
|
||||
import com.cf.imes.module.executor.dal.mysql.order.OrderSupStatisticsMapper;
|
||||
import com.cf.imes.module.system.api.organ.OrganApi;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
@@ -31,9 +28,6 @@ public class OrderSupStatisticsServiceImpl implements OrderSupStatisticsService{
|
||||
@Resource
|
||||
private OrderSupStatisticsMapper orderSupStatisticsMapper;
|
||||
|
||||
@Resource
|
||||
private OrganApi organApi;
|
||||
|
||||
@Override
|
||||
@OrganIgnore
|
||||
public Map<String, Integer> orderTotal() {
|
||||
@@ -110,50 +104,6 @@ public class OrderSupStatisticsServiceImpl implements OrderSupStatisticsService{
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
@OrganIgnore
|
||||
public Map<String, Object> plateAreaSeparate(OrderStatisticsReqVO reqVO) {
|
||||
setOrderStatisticsReqVO(reqVO);
|
||||
|
||||
Map<String, Object> resultMap = new LinkedHashMap<>();
|
||||
|
||||
// 所有的日期集合
|
||||
List<String> dateList = getDateList(reqVO.getCreateTime(),reqVO.getUnit());
|
||||
|
||||
// 生产单有效板件平方数量
|
||||
Map<String, List<OrderStatisticsAreaRespVO>> orderLapseRespMap = orderSupStatisticsMapper.selectPlateAreaNotLapseByOrderDate(reqVO).stream()
|
||||
.sorted(Comparator.naturalOrder())
|
||||
.collect(Collectors.groupingBy(OrderStatisticsAreaRespVO::getDate, LinkedHashMap::new, Collectors.toList()));
|
||||
|
||||
// 生产单无效板件平方数量
|
||||
Map<String, List<OrderStatisticsAreaRespVO>> orderNotLapseRespMap = orderSupStatisticsMapper.selectPlateAreaLapseByOrderDate(reqVO).stream()
|
||||
.sorted(Comparator.naturalOrder())
|
||||
.collect(Collectors.groupingBy(OrderStatisticsAreaRespVO::getDate, LinkedHashMap::new, Collectors.toList()));
|
||||
|
||||
// 遍历时间跨度列表,匹配数量存入数组,没有补0存入数组
|
||||
for (String dateStr : dateList) {
|
||||
BigDecimal[] countArr = new BigDecimal[2];
|
||||
// 生产单有效数量
|
||||
BigDecimal orderNotLapseCount = Optional.ofNullable(orderNotLapseRespMap.get(dateStr))
|
||||
.map(list -> list.stream().findFirst().orElse(new OrderStatisticsAreaRespVO()))
|
||||
.map(OrderStatisticsAreaRespVO::getAreaSum)
|
||||
.orElse(BigDecimal.valueOf(0));
|
||||
countArr[0] = orderNotLapseCount;
|
||||
|
||||
|
||||
// 生产单无效数量
|
||||
BigDecimal orderLapseCount = Optional.ofNullable(orderLapseRespMap.get(dateStr))
|
||||
.map(list -> list.stream().findFirst().orElse(new OrderStatisticsAreaRespVO()))
|
||||
.map(OrderStatisticsAreaRespVO::getAreaSum)
|
||||
.orElse(BigDecimal.valueOf(0));
|
||||
countArr[1] = orderLapseCount;
|
||||
|
||||
resultMap.put(generateDateRangeAxis(dateStr, reqVO.getUnit()), countArr);
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
private void setOrderStatisticsReqVO(OrderStatisticsReqVO reqVO){
|
||||
if (ObjectUtil.isNull(reqVO.getUnit())){
|
||||
reqVO.setUnit(OrderStatisticsUnit.DAY.getValue());
|
||||
|
||||
-22
@@ -44,26 +44,4 @@
|
||||
group by date;
|
||||
</select>
|
||||
|
||||
<select id="selectPlateAreaLapseByOrderDate"
|
||||
resultType="com.cf.imes.module.executor.controller.admin.order.vo.order.OrderStatisticsAreaRespVO">
|
||||
select sum(op.area) as areaSum
|
||||
<include refid="dateFormat"/>
|
||||
from orders o
|
||||
left join order_plate op on op.order_id = o.id and op.deleted = 0
|
||||
where o.order_date between #{req.createTime[0]} and #{req.createTime[1]}
|
||||
and (o.deleted = 1 or o.status = 0)
|
||||
group by date;
|
||||
</select>
|
||||
|
||||
<select id="selectPlateAreaNotLapseByOrderDate"
|
||||
resultType="com.cf.imes.module.executor.controller.admin.order.vo.order.OrderStatisticsAreaRespVO">
|
||||
select sum(op.area) as areaSum
|
||||
<include refid="dateFormat"/>
|
||||
from orders o
|
||||
left join order_plate op on op.order_id = o.id and op.deleted = 0
|
||||
where o.order_date between #{req.createTime[0]} and #{req.createTime[1]}
|
||||
and o.deleted = 0 and o.status != 0
|
||||
group by date;
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
-4
@@ -31,10 +31,6 @@ public interface OrganApi {
|
||||
@Parameter(name = "id", description = "组织编号", required = true, example = "1024")
|
||||
CommonResult<Boolean> validOrgan(@RequestParam("id") Long id);
|
||||
|
||||
@GetMapping(PREFIX + "/total/org")
|
||||
@Operation(summary = "组织总数查询")
|
||||
CommonResult<Map<String, Integer>> getOrgTotal();
|
||||
|
||||
@PostMapping(PREFIX + "/separate/org")
|
||||
@Operation(summary = "新增、注销组织数量统计")
|
||||
CommonResult<Map<String, Object>> getOrgSeparate(@Valid OrgStatisticsReqDTO reqVO);
|
||||
|
||||
-8
@@ -73,12 +73,4 @@ public interface AdminUserApi {
|
||||
@Operation(summary = "通过组织 ID 查询组织管理员用户列表")
|
||||
@Parameter(name = "organIds", description = "组织id列表", example = "1,3", required = true)
|
||||
CommonResult<List<OrganAdminUserRespDTO>> getOrganAdminByOrganIds(@RequestParam("id") Collection<Long> organIds);
|
||||
|
||||
@GetMapping(PREFIX + "/total/user")
|
||||
@Operation(summary = "用户总数")
|
||||
CommonResult<Map<String, Integer>> getUserTotal();
|
||||
|
||||
@GetMapping(PREFIX + "/total/userAct")
|
||||
@Operation(summary = "用户活跃数")
|
||||
CommonResult<Map<String, Integer>> getUserActTotal();
|
||||
}
|
||||
|
||||
-5
@@ -50,11 +50,6 @@ public class OrganApiImpl implements OrganApi {
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<Map<String, Integer>> getOrgTotal() {
|
||||
return success(organService.orgTotal());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<Map<String, Object>> getOrgSeparate(OrgStatisticsReqDTO reqVO) {
|
||||
setOrgStatisticsReqVO(reqVO);
|
||||
|
||||
-11
@@ -12,7 +12,6 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.cf.imes.framework.common.pojo.CommonResult.success;
|
||||
@@ -65,15 +64,5 @@ public class AdminUserApiImpl implements AdminUserApi {
|
||||
return success(userService.getOrganAdminByOrganIds(organIds));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<Map<String, Integer>> getUserTotal() {
|
||||
return success(userService.userTotal());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<Map<String, Integer>> getUserActTotal() {
|
||||
return success(userService.userActTotal());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
package com.cf.imes.module.system.controller.admin.statistics;
|
||||
|
||||
import com.cf.imes.framework.common.pojo.CommonResult;
|
||||
import com.cf.imes.module.system.controller.admin.statistics.vo.ManageOrgTotalStatisticRespVO;
|
||||
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.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 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 static com.cf.imes.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "管理后台 - 管理端分析页管理")
|
||||
@RestController
|
||||
@RequestMapping("/system/manage/statistic")
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class ManageStatisticsController {
|
||||
|
||||
// @Resource
|
||||
// private OrderSupStatisticsService orderSupStatisticsService;
|
||||
|
||||
@Resource
|
||||
private OrganService organService;
|
||||
|
||||
@Resource
|
||||
private AdminUserService userService;
|
||||
|
||||
@GetMapping("/total/org")
|
||||
@Operation(summary = "组织总数")
|
||||
public CommonResult<ManageOrgTotalStatisticRespVO> getOrgTotal() {
|
||||
return success(organService.getOrgTotal());
|
||||
}
|
||||
|
||||
@GetMapping("/total/user")
|
||||
@Operation(summary = "用户总数")
|
||||
public CommonResult<ManageUserTotalStatisticRespVO> getUserTotal() {
|
||||
return success(userService.getUserTotal());
|
||||
}
|
||||
|
||||
@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();
|
||||
// }
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
package com.cf.imes.module.system.controller.admin.statistics.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author Gqr
|
||||
* @since 2025/9/29 14:37
|
||||
*/
|
||||
@Schema(description = "管理后台 - 管理端组织总数统计 Response VO")
|
||||
@Data
|
||||
public class ManageOrgTotalStatisticRespVO {
|
||||
|
||||
@Schema(description = "组织总数")
|
||||
private Integer orgTotal;
|
||||
|
||||
@Schema(description = "当日新增组织数")
|
||||
private Integer orgAdd;
|
||||
|
||||
@Schema(description = "当日删除组织数")
|
||||
private Integer orgDel;
|
||||
|
||||
@Schema(description = "组织沉寂数")
|
||||
private Integer orgSilent;
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package com.cf.imes.module.system.controller.admin.statistics.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author Gqr
|
||||
* @since 2025/9/29 14:37
|
||||
*/
|
||||
@Schema(description = "管理后台 - 管理端用户活跃数统计 Response VO")
|
||||
@Data
|
||||
public class ManageUserActTotalStatisticRespVO {
|
||||
|
||||
@Schema(description = "用户月活跃数")
|
||||
private Integer userMonthAct;
|
||||
|
||||
@Schema(description = "用户日活跃数")
|
||||
private Integer userDayAct;
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
package com.cf.imes.module.system.controller.admin.statistics.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author Gqr
|
||||
* @since 2025/9/29 14:37
|
||||
*/
|
||||
@Schema(description = "管理后台 - 管理端用户总数统计 Response VO")
|
||||
@Data
|
||||
public class ManageUserTotalStatisticRespVO {
|
||||
|
||||
@Schema(description = "用户总数")
|
||||
private Integer userTotal;
|
||||
|
||||
@Schema(description = "当日新增用户数")
|
||||
private Integer userTodayAdd;
|
||||
|
||||
@Schema(description = "当日删除用户数")
|
||||
private Integer userTodayDel;
|
||||
|
||||
@Schema(description = "用户沉寂数")
|
||||
private Integer userTodaySilent;
|
||||
}
|
||||
+5
-2
@@ -5,8 +5,8 @@ import cn.hutool.core.util.ObjectUtil;
|
||||
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.date.LocalDateTimeUtils;
|
||||
import com.cf.imes.framework.common.util.object.BeanUtils;
|
||||
import com.cf.imes.framework.id.core.util.SnowflakeIdWorker3rd;
|
||||
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;
|
||||
@@ -72,6 +72,9 @@ public class ManualAdjustAccountBalanceServiceImpl implements ManualAdjustAccoun
|
||||
@Resource
|
||||
private IncomeExpenseDetailsMapper incomeExpenseDetailsMapper;
|
||||
|
||||
@Resource
|
||||
private SnowflakeIdWorker3rd snowflakeIdWorker3rd;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Long createAjustment(ManualAdjustAccountBalanceSaveReqVO saveReqVO) {
|
||||
@@ -125,7 +128,7 @@ public class ManualAdjustAccountBalanceServiceImpl implements ManualAdjustAccoun
|
||||
IncomeExpenseDetailsDO incomeExpenseDetailsDO = IncomeExpenseDetailsDO.builder()
|
||||
.organId(organId)
|
||||
.orderNo(payOrderDO.getPayNo())
|
||||
.businessNo(LocalDateTimeUtils.formatNow())
|
||||
.businessNo(snowflakeIdWorker3rd.nextSerialNo())
|
||||
.tradeType(TradeTypeEnum.MANUAL_ADJUST.getCode())
|
||||
.incomeExpenseType(incomeExpenseType)
|
||||
.cashAmountChange(rechargeAmount)
|
||||
|
||||
-1
@@ -191,7 +191,6 @@ public class PurchaseServiceImpl implements PurchaseService {
|
||||
return purchaseRecordMapper.selectList(new LambdaQueryWrapper<PurchaseRecordDO>()
|
||||
.in(PurchaseRecordDO::getOrganId, organIds)
|
||||
.eq(PurchaseRecordDO::getStatus, PurchaseRecordStatusEnum.ACTIVE.getStatus())
|
||||
.ne(PurchaseRecordDO::getInitial, true)
|
||||
.eq(PurchaseRecordDO::getDeleted, false));
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -8,6 +8,7 @@ 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.dal.dataobject.organ.OrganizationDO;
|
||||
import com.cf.imes.module.system.service.organ.handler.OrganInfoHandler;
|
||||
import com.cf.imes.module.system.service.organ.handler.OrganMenuHandler;
|
||||
@@ -147,7 +148,7 @@ public interface OrganService {
|
||||
/**
|
||||
* 组织总数统计
|
||||
*/
|
||||
Map<String, Integer> orgTotal();
|
||||
ManageOrgTotalStatisticRespVO getOrgTotal();
|
||||
|
||||
/**
|
||||
* 组织新增统计
|
||||
|
||||
+8
-11
@@ -27,6 +27,7 @@ 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.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;
|
||||
@@ -524,24 +525,20 @@ public class OrganServiceImpl implements OrganService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Integer> orgTotal() {
|
||||
Map<String, Integer> map = new HashMap<>();
|
||||
public ManageOrgTotalStatisticRespVO getOrgTotal() {
|
||||
ManageOrgTotalStatisticRespVO respVO = new ManageOrgTotalStatisticRespVO();
|
||||
|
||||
// 组织总数
|
||||
Integer orgTotal = organMapper.selectOrgCount();
|
||||
map.put("orgTotal", orgTotal);
|
||||
respVO.setOrgTotal(organMapper.selectOrgCount());
|
||||
// 当日新增数
|
||||
Integer orgAdd = organMapper.selectOrgCountAdd();
|
||||
map.put("orgAdd", orgAdd);
|
||||
respVO.setOrgAdd(organMapper.selectOrgCountAdd());
|
||||
// 当日状态-删除
|
||||
Integer orgDel = organMapper.selectOrgCountDel();
|
||||
map.put("orgDel", orgDel);
|
||||
respVO.setOrgDel(organMapper.selectOrgCountDel());
|
||||
// 当日沉寂数 (组织中所有用户30天未登录)
|
||||
// 获得30天前的时间,赋值时间为0:00:00
|
||||
Date date = DateUtil.offsetDay(new Date(), -30);
|
||||
Integer orgSilent = organMapper.selectOrgSilentCount(DateUtil.beginOfDay(date).toLocalDateTime());
|
||||
map.put("orgSilent", orgSilent);
|
||||
return map;
|
||||
respVO.setOrgSilent(organMapper.selectOrgSilentCount(DateUtil.beginOfDay(date).toLocalDateTime()));
|
||||
return respVO;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+7
-4
@@ -15,10 +15,10 @@ import com.cf.imes.framework.common.exception.enums.GlobalErrorCodeConstants;
|
||||
import com.cf.imes.framework.common.exception.util.ServiceExceptionUtil;
|
||||
import com.cf.imes.framework.common.pojo.PageResult;
|
||||
import com.cf.imes.framework.common.util.Assert.AssertUtils;
|
||||
import com.cf.imes.framework.common.util.date.LocalDateTimeUtils;
|
||||
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.organ.core.context.OrganContextHolder;
|
||||
import com.cf.imes.framework.pay.config.ChenfengAlipayConfig;
|
||||
import com.cf.imes.framework.pay.config.ChenfengPayConfig;
|
||||
@@ -163,6 +163,9 @@ public class PayOrderServiceImpl implements PayOrderService {
|
||||
@Resource
|
||||
private TransactionTemplate transactionTemplate;
|
||||
|
||||
@Resource
|
||||
private SnowflakeIdWorker3rd snowflakeIdWorker3rd;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public PayOrderRespDTO productPay(PayProductOrderUnifiedReqVO payProductOrderUnifiedReqVO) {
|
||||
@@ -206,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);
|
||||
PayProductProcessor payProductProcessor = new PayProductProcessor(productsDO, productsDetailDO, orgInitialPurchaseRecord, previouProductDelayRespVO, organAmount, organId, payConfig, mybatisIdProperties, snowflakeIdWorker3rd);
|
||||
ProductProcessorRespVO productProcessorRespVO = payProductProcessor.processPayment(PayProductChannelCodeEnum.fromType(payProductOrderUnifiedReqVO.getProductChannelCode()));
|
||||
PayOrderDO payOrder = productProcessorRespVO.getPayOrderDO();
|
||||
|
||||
@@ -619,7 +622,7 @@ public class PayOrderServiceImpl implements PayOrderService {
|
||||
IncomeExpenseDetailsDO incomeExpenseDetailsDO = IncomeExpenseDetailsDO.builder()
|
||||
.organId(organId)
|
||||
.orderNo(payNo)
|
||||
.businessNo(LocalDateTimeUtils.formatNow())
|
||||
.businessNo(snowflakeIdWorker3rd.nextSerialNo())
|
||||
.tradeType(TradeTypeEnum.RECHARGE.getCode())
|
||||
.incomeExpenseType(IncomeExpenseTypeEnum.INCOME.getCode())
|
||||
.cashAmountChange(price)
|
||||
@@ -754,7 +757,7 @@ public class PayOrderServiceImpl implements PayOrderService {
|
||||
IncomeExpenseDetailsDO incomeExpenseDetailsDO = IncomeExpenseDetailsDO.builder()
|
||||
.organId(organId)
|
||||
.orderNo(String.valueOf(record.getId()))
|
||||
.businessNo(LocalDateTimeUtils.formatNow())
|
||||
.businessNo(snowflakeIdWorker3rd.nextSerialNo())
|
||||
.tradeType(TradeTypeEnum.PRODUCT.getCode())
|
||||
.incomeExpenseType(IncomeExpenseTypeEnum.INCOME.getCode())
|
||||
.cashAmountChange(accountBalanceSpent)
|
||||
|
||||
+12
-7
@@ -9,6 +9,7 @@ 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.pay.config.ChenfengPayConfig;
|
||||
import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils;
|
||||
import com.cf.imes.module.system.controller.admin.funds.delay.vo.PreviouProductDelayRespVO;
|
||||
@@ -76,6 +77,9 @@ public class PayProductProcessor {
|
||||
// id生成规则配置
|
||||
private MybatisIdProperties mybatisIdProperties;
|
||||
|
||||
// id生成器
|
||||
private SnowflakeIdWorker3rd snowflakeIdWorker3rd;
|
||||
|
||||
// 标记本次订购是否首次
|
||||
private boolean initialized = false;
|
||||
|
||||
@@ -98,7 +102,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) {
|
||||
OrganAmountDO organAmountDO, Long organId, ChenfengPayConfig payConfig, MybatisIdProperties mybatisIdProperties, SnowflakeIdWorker3rd snowflakeIdWorker3rd) {
|
||||
this.productsDO = productsDO;
|
||||
this.productsDetailDO = productsDetailDO;
|
||||
this.orgInitialPurchaseRecord = orgInitialPurchaseRecord;
|
||||
@@ -113,6 +117,7 @@ public class PayProductProcessor {
|
||||
this.organId = organId;
|
||||
this.payConfig = payConfig;
|
||||
this.mybatisIdProperties = mybatisIdProperties;
|
||||
this.snowflakeIdWorker3rd = snowflakeIdWorker3rd;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -205,8 +210,8 @@ public class PayProductProcessor {
|
||||
BigDecimal giftAmount = organAmountDO.getGiftAmount();
|
||||
IncomeExpenseDetailsDO incomeExpenseDetailsDO = IncomeExpenseDetailsDO.builder()
|
||||
.organId(organId)
|
||||
.businessNo(snowflakeIdWorker3rd.nextSerialNo())
|
||||
.orderNo(String.format(PayConstants.PAY_PRODUCT_DETAIL_BUSINESSNO_PREFIX_FORMAT, organId, purchaseId))
|
||||
.businessNo(LocalDateTimeUtils.formatNow())
|
||||
.purchaseId(purchaseRecordDO.getId())
|
||||
.tradeType(TradeTypeEnum.PRODUCT.getCode())
|
||||
.incomeExpenseType(IncomeExpenseTypeEnum.EXPENSES.getCode())
|
||||
@@ -263,7 +268,7 @@ public class PayProductProcessor {
|
||||
BigDecimal amount = organAmountDO.getAmount();
|
||||
IncomeExpenseDetailsDO incomeExpenseDetailsDO = IncomeExpenseDetailsDO.builder()
|
||||
.organId(organId)
|
||||
.businessNo(LocalDateTimeUtils.formatNow())
|
||||
.businessNo(snowflakeIdWorker3rd.nextSerialNo())
|
||||
.orderNo(String.format(PayConstants.PAY_PRODUCT_DETAIL_BUSINESSNO_PREFIX_FORMAT, organId, purchaseId))
|
||||
.purchaseId(purchaseRecordDO.getId())
|
||||
.tradeType(TradeTypeEnum.PRODUCT.getCode())
|
||||
@@ -416,7 +421,7 @@ public class PayProductProcessor {
|
||||
BigDecimal newGift = gift.subtract(usedGift);
|
||||
IncomeExpenseDetailsDO incomeExpenseDetailsDO = IncomeExpenseDetailsDO.builder()
|
||||
.organId(organId)
|
||||
.businessNo(LocalDateTimeUtils.formatNow())
|
||||
.businessNo(snowflakeIdWorker3rd.nextSerialNo())
|
||||
.orderNo(String.format(PayConstants.PAY_PRODUCT_DETAIL_BUSINESSNO_PREFIX_FORMAT, organId, purchaseId))
|
||||
.purchaseId(purchaseRecordDO.getId())
|
||||
.tradeType(TradeTypeEnum.PRODUCT.getCode())
|
||||
@@ -481,7 +486,7 @@ public class PayProductProcessor {
|
||||
BigDecimal giftAmount = organAmountDO.getGiftAmount();
|
||||
IncomeExpenseDetailsDO incomeExpenseDetailsDO = IncomeExpenseDetailsDO.builder()
|
||||
.organId(organId)
|
||||
.businessNo(LocalDateTimeUtils.formatNow())
|
||||
.businessNo(snowflakeIdWorker3rd.nextSerialNo())
|
||||
.orderNo(String.format(PayConstants.PAY_PRODUCT_DETAIL_BUSINESSNO_PREFIX_FORMAT, organId, purchaseId))
|
||||
.purchaseId(purchaseRecordDO.getId())
|
||||
.tradeType(TradeTypeEnum.PRODUCT.getCode())
|
||||
@@ -558,7 +563,7 @@ public class PayProductProcessor {
|
||||
BigDecimal amount = organAmountDO.getAmount();
|
||||
IncomeExpenseDetailsDO incomeExpenseDetailsDO = IncomeExpenseDetailsDO.builder()
|
||||
.organId(organId)
|
||||
.businessNo(LocalDateTimeUtils.formatNow())
|
||||
.businessNo(snowflakeIdWorker3rd.nextSerialNo())
|
||||
.orderNo(String.format(PayConstants.PAY_PRODUCT_DETAIL_BUSINESSNO_PREFIX_FORMAT, organId, purchaseId))
|
||||
.purchaseId(purchaseId)
|
||||
.tradeType(TradeTypeEnum.PRODUCT.getCode())
|
||||
@@ -644,7 +649,7 @@ public class PayProductProcessor {
|
||||
BigDecimal newGift = gift.subtract(usedGift);
|
||||
IncomeExpenseDetailsDO incomeExpenseDetailsDO = IncomeExpenseDetailsDO.builder()
|
||||
.organId(organId)
|
||||
.businessNo(LocalDateTimeUtils.formatNow())
|
||||
.businessNo(snowflakeIdWorker3rd.nextSerialNo())
|
||||
.orderNo(String.format(PayConstants.PAY_PRODUCT_DETAIL_BUSINESSNO_PREFIX_FORMAT, organId, purchaseId))
|
||||
.purchaseId(purchaseId)
|
||||
.tradeType(TradeTypeEnum.PRODUCT.getCode())
|
||||
|
||||
+4
-2
@@ -4,6 +4,8 @@ import cn.hutool.core.collection.CollUtil;
|
||||
import com.cf.imes.framework.common.pojo.PageResult;
|
||||
import com.cf.imes.framework.common.util.collection.CollectionUtils;
|
||||
import com.cf.imes.module.system.api.user.dto.OrganAdminUserRespDTO;
|
||||
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.user.vo.profile.UserMobileUpdateReqVO;
|
||||
import com.cf.imes.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO;
|
||||
import com.cf.imes.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO;
|
||||
@@ -267,12 +269,12 @@ public interface AdminUserService {
|
||||
/**
|
||||
* 用户总数统计
|
||||
*/
|
||||
Map<String, Integer> userTotal();
|
||||
ManageUserTotalStatisticRespVO getUserTotal();
|
||||
|
||||
/**
|
||||
* 用户活跃数统计
|
||||
*/
|
||||
Map<String, Integer> userActTotal();
|
||||
ManageUserActTotalStatisticRespVO getUserActTotal();
|
||||
|
||||
/**
|
||||
* 修改密保手机
|
||||
|
||||
+15
-18
@@ -28,6 +28,8 @@ import com.cf.imes.module.system.api.logger.dto.LoginLogCreateReqDTO;
|
||||
import com.cf.imes.module.system.api.sms.dto.code.SmsCodeUseReqDTO;
|
||||
import com.cf.imes.module.system.api.user.dto.OrganAdminUserRespDTO;
|
||||
import com.cf.imes.module.system.constants.permission.InternalRoleConstants;
|
||||
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.user.vo.profile.UserMobileUpdateReqVO;
|
||||
import com.cf.imes.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO;
|
||||
import com.cf.imes.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO;
|
||||
@@ -753,39 +755,34 @@ public class AdminUserServiceImpl implements AdminUserService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Integer> userTotal() {
|
||||
Map<String, Integer> map = new HashMap<>();
|
||||
public ManageUserTotalStatisticRespVO getUserTotal() {
|
||||
ManageUserTotalStatisticRespVO respVO = new ManageUserTotalStatisticRespVO();
|
||||
|
||||
// 用户总数
|
||||
Integer userTotal = userMapper.selectUserCount();
|
||||
map.put("userTotal", userTotal);
|
||||
respVO.setUserTotal(userMapper.selectUserCount());
|
||||
// 当日新增数
|
||||
Integer userTodayAdd = userMapper.selectUserCountAdd();
|
||||
map.put("userTodayAdd", userTodayAdd);
|
||||
respVO.setUserTodayAdd(userMapper.selectUserCountAdd());
|
||||
// 当日状态-停止数
|
||||
Integer userTodayDel = userMapper.selectUserCountDel();
|
||||
map.put("userTodayDel", userTodayDel);
|
||||
respVO.setUserTodayAdd(userMapper.selectUserCountDel());
|
||||
// 当日沉寂数 (30天未登录)
|
||||
Date date = DateUtil.offsetDay(new Date(), -30);
|
||||
Integer userTodaySilent = userMapper.selectUserCountSilent(DateUtil.beginOfDay(date).toLocalDateTime());
|
||||
map.put("userTodaySilent", userTodaySilent);
|
||||
respVO.setUserTodayAdd(userMapper.selectUserCountSilent(DateUtil.beginOfDay(date).toLocalDateTime()));
|
||||
|
||||
return map;
|
||||
return respVO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Integer> userActTotal() {
|
||||
Map<String, Integer> map = new HashMap<>();
|
||||
public ManageUserActTotalStatisticRespVO getUserActTotal() {
|
||||
ManageUserActTotalStatisticRespVO respVO = new ManageUserActTotalStatisticRespVO();
|
||||
|
||||
LocalDateTime startTime = getFirstDayOfMonth();
|
||||
LocalDateTime endTIme = LocalDateTime.of(LocalDate.now(), LocalTime.of(23, 59, 59));
|
||||
// 用户月活跃数
|
||||
Integer userMonthAct = userMapper.selectUserActCountTime(startTime, endTIme);
|
||||
map.put("userMonthAct", userMonthAct);
|
||||
respVO.setUserMonthAct(userMapper.selectUserActCountTime(startTime, endTIme));
|
||||
// 用户日活跃数
|
||||
Integer userDayAct = userMapper.selectUserActCountTime(LocalDateTime.of(LocalDate.now(), LocalTime.of(0, 0, 0)), endTIme);
|
||||
map.put("userDayAct", userDayAct);
|
||||
return map;
|
||||
respVO.setUserDayAct(userMapper.selectUserActCountTime(LocalDateTime.of(LocalDate.now(), LocalTime.of(0, 0, 0)), endTIme));
|
||||
|
||||
return respVO;
|
||||
}
|
||||
|
||||
// 获得此月第一天日期
|
||||
|
||||
+7
-12
@@ -3,19 +3,14 @@
|
||||
<mapper namespace="com.cf.imes.module.system.dal.mysql.organ.OrganMapper">
|
||||
|
||||
<select id="selectOrgSilentCount" resultType="java.lang.Integer">
|
||||
WITH NoLoginOrgs AS (
|
||||
SELECT DISTINCT o.id
|
||||
FROM system_organization o
|
||||
LEFT JOIN system_users ul ON o.id = ul.organ_id
|
||||
AND Date (#{dateTime}) > ul.login_date
|
||||
AND ul.deleted = 0
|
||||
WHERE o.deleted =0
|
||||
|
||||
)
|
||||
|
||||
-- 查询这些沉寂组织的数量
|
||||
SELECT COUNT(*) AS count
|
||||
FROM NoLoginOrgs;
|
||||
FROM system_organization o
|
||||
LEFT JOIN system_users ul
|
||||
ON o.id = ul.organ_id
|
||||
AND ul.deleted = 0
|
||||
AND DATE(#{dateTime}) <= ul.login_date
|
||||
WHERE o.deleted = 0
|
||||
AND ul.id IS NULL;
|
||||
</select>
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user