Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2a35793baf | ||
|
|
4a157e9578 | ||
|
|
eabb4c6aa6 | ||
|
|
d22df698b6 | ||
|
|
cb6051cc41 | ||
|
|
1d1009b121 | ||
|
|
94f3fbb867 | ||
|
|
1771bf9909 | ||
|
|
fc4d55517b | ||
|
|
ec72a99d74 | ||
|
|
a431db6e6e | ||
|
|
9cfb31b015 | ||
|
|
15d69f9361 | ||
|
|
b000390a75 | ||
|
|
1b9f92caf5 | ||
|
|
7b08641acc | ||
|
|
66c13062b2 | ||
|
|
2b4089ef59 | ||
|
|
cdf8a426e9 | ||
|
|
a2d69fe721 | ||
|
|
19db357b44 | ||
|
|
07ffef3e2a |
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
<groupId>com.imyeyu.timiserverapi</groupId>
|
<groupId>com.imyeyu.timiserverapi</groupId>
|
||||||
<artifactId>TimiServerAPI</artifactId>
|
<artifactId>TimiServerAPI</artifactId>
|
||||||
<version>1.0.37</version>
|
<version>1.0.42</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<name>TimiServerAPI</name>
|
<name>TimiServerAPI</name>
|
||||||
<description>imyeyu.com API</description>
|
<description>imyeyu.com API</description>
|
||||||
@@ -215,6 +215,11 @@
|
|||||||
<artifactId>tinypinyin</artifactId>
|
<artifactId>tinypinyin</artifactId>
|
||||||
<version>2.0.3</version>
|
<version>2.0.3</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.hankcs</groupId>
|
||||||
|
<artifactId>hanlp</artifactId>
|
||||||
|
<version>portable-1.8.4</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.imyeyu.font.icon</groupId>
|
<groupId>com.imyeyu.font.icon</groupId>
|
||||||
<artifactId>timi-icon-font</artifactId>
|
<artifactId>timi-icon-font</artifactId>
|
||||||
|
|||||||
@@ -45,6 +45,11 @@ public enum CorePermissionCode implements BuiltinPermissionCode {
|
|||||||
TAG_UPDATE("TAG:UPDATE", "标签修改", false, true),
|
TAG_UPDATE("TAG:UPDATE", "标签修改", false, true),
|
||||||
TAG_DELETE("TAG:DELETE", "标签删除", false, true),
|
TAG_DELETE("TAG:DELETE", "标签删除", false, true),
|
||||||
|
|
||||||
|
ARTICLE_CREATE("ARTICLE:CREATE", "文章创建", false, true),
|
||||||
|
ARTICLE_READ("ARTICLE:READ", "文章读取", false, true),
|
||||||
|
ARTICLE_UPDATE("ARTICLE:UPDATE", "文章修改", false, true),
|
||||||
|
ARTICLE_DELETE("ARTICLE:DELETE", "文章删除", false, true),
|
||||||
|
|
||||||
USER_CREATE("USER:CREATE", "用户创建", false, true),
|
USER_CREATE("USER:CREATE", "用户创建", false, true),
|
||||||
USER_READ("USER:READ", "用户读取", false, true),
|
USER_READ("USER:READ", "用户读取", false, true),
|
||||||
USER_UPDATE("USER:UPDATE", "用户修改", false, true),
|
USER_UPDATE("USER:UPDATE", "用户修改", false, true),
|
||||||
|
|||||||
@@ -0,0 +1,96 @@
|
|||||||
|
package com.imyeyu.api.modules.common.controller;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonView;
|
||||||
|
import com.imyeyu.api.annotation.RequireCorePermission;
|
||||||
|
import com.imyeyu.api.bean.CorePermissionCode;
|
||||||
|
import com.imyeyu.api.modules.common.entity.Article;
|
||||||
|
import com.imyeyu.api.modules.common.entity.Attachment;
|
||||||
|
import com.imyeyu.api.modules.common.service.ArticleService;
|
||||||
|
import com.imyeyu.api.modules.common.service.AttachmentService;
|
||||||
|
import com.imyeyu.spring.annotation.AOPLog;
|
||||||
|
import com.imyeyu.spring.annotation.RequestRateLimit;
|
||||||
|
import com.imyeyu.spring.bean.Page;
|
||||||
|
import com.imyeyu.spring.bean.PageResult;
|
||||||
|
import com.imyeyu.spring.util.ResponseView;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
/// 文章接口
|
||||||
|
///
|
||||||
|
/// @author Codex
|
||||||
|
/// @since 2026-09-09
|
||||||
|
@Slf4j
|
||||||
|
@RestController
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@RequestMapping("/article")
|
||||||
|
public class ArticleController {
|
||||||
|
|
||||||
|
private final ArticleService service;
|
||||||
|
private final AttachmentService attachmentService;
|
||||||
|
|
||||||
|
/// 查询文章列表
|
||||||
|
///
|
||||||
|
/// @param page 分页参数
|
||||||
|
/// @return 文章分页
|
||||||
|
@JsonView(ResponseView.Public.class)
|
||||||
|
@RequestRateLimit
|
||||||
|
@RequireCorePermission(CorePermissionCode.ARTICLE_READ)
|
||||||
|
@PostMapping("/list")
|
||||||
|
public PageResult<Article> list(@RequestBody Page<Article> page) {
|
||||||
|
return service.page(page);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 查询文章详情
|
||||||
|
///
|
||||||
|
/// @param id 文章 ID
|
||||||
|
/// @return 文章详情
|
||||||
|
@JsonView(ResponseView.Public.class)
|
||||||
|
@RequestRateLimit
|
||||||
|
@RequestMapping("/detail")
|
||||||
|
public Article detail(@RequestParam String id) {
|
||||||
|
Article article = service.get(id);
|
||||||
|
article.setAttachmentList(attachmentService.listByBizId(Attachment.BizType.ARTICLE, article.getId()));
|
||||||
|
return article;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 创建文章
|
||||||
|
///
|
||||||
|
/// @param article 文章
|
||||||
|
/// @return 创建后的文章
|
||||||
|
@AOPLog
|
||||||
|
@JsonView(ResponseView.Public.class)
|
||||||
|
@RequestRateLimit
|
||||||
|
@RequireCorePermission(CorePermissionCode.ARTICLE_CREATE)
|
||||||
|
@PostMapping("/create")
|
||||||
|
public Article create(@RequestBody Article article) {
|
||||||
|
service.create(article);
|
||||||
|
return article;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 更新文章
|
||||||
|
///
|
||||||
|
/// @param article 文章
|
||||||
|
@AOPLog
|
||||||
|
@RequestRateLimit
|
||||||
|
@RequireCorePermission(CorePermissionCode.ARTICLE_UPDATE)
|
||||||
|
@PostMapping("/update")
|
||||||
|
public void update(@RequestBody Article article) {
|
||||||
|
service.update(article);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 删除文章
|
||||||
|
///
|
||||||
|
/// @param id 文章 ID
|
||||||
|
@AOPLog
|
||||||
|
@RequestRateLimit
|
||||||
|
@RequireCorePermission(CorePermissionCode.ARTICLE_DELETE)
|
||||||
|
@PostMapping("/delete")
|
||||||
|
public void delete(@RequestParam String id) {
|
||||||
|
service.delete(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,8 +15,12 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
@@ -26,11 +30,30 @@ import org.springframework.web.bind.annotation.RestController;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
@RestController
|
@RestController
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@RequestMapping("/system/setting")
|
@RequestMapping("/setting")
|
||||||
public class SettingController {
|
public class SettingController {
|
||||||
|
|
||||||
private final SettingService service;
|
private final SettingService service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询公开配置映射
|
||||||
|
*
|
||||||
|
* @param bizType 业务类型
|
||||||
|
* @param bizId 业务 ID,可为空
|
||||||
|
* @param code 配置代码列表,可为空
|
||||||
|
* @return 公开配置映射
|
||||||
|
*/
|
||||||
|
@JsonView(ResponseView.Public.class)
|
||||||
|
@RequestRateLimit
|
||||||
|
@RequestMapping("/map")
|
||||||
|
public Map<String, Setting> map(
|
||||||
|
@RequestParam String bizType,
|
||||||
|
@RequestParam(required = false) String bizId,
|
||||||
|
@RequestParam(required = false) List<String> code
|
||||||
|
) {
|
||||||
|
return service.mapPublic(bizType, bizId, code);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询配置列表
|
* 查询配置列表
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ public class Article extends UUIDEntity implements SettingSupport {
|
|||||||
/// GAO 门店日记
|
/// GAO 门店日记
|
||||||
GAO_STORE_DIARY,
|
GAO_STORE_DIARY,
|
||||||
|
|
||||||
|
GAO_SYSTEM,
|
||||||
|
|
||||||
/// 反馈
|
/// 反馈
|
||||||
FEEDBACK
|
FEEDBACK
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,11 +20,11 @@ public class Notify extends UUIDEntity {
|
|||||||
/** 业务类型 */
|
/** 业务类型 */
|
||||||
private String bizType;
|
private String bizType;
|
||||||
|
|
||||||
/** 提醒业务类型 */
|
/** 业务提醒类型 */
|
||||||
private String bizRemindedType;
|
private String bizRemindedType;
|
||||||
|
|
||||||
/** 提醒业务 ID */
|
/** 业务提醒查重键 */
|
||||||
private String bizRemindedId;
|
private String bizRemindedKey;
|
||||||
|
|
||||||
/** 参数 */
|
/** 参数 */
|
||||||
private String args;
|
private String args;
|
||||||
|
|||||||
@@ -2,9 +2,8 @@ package com.imyeyu.api.modules.common.mapper;
|
|||||||
|
|
||||||
import com.imyeyu.api.modules.common.entity.Notify;
|
import com.imyeyu.api.modules.common.entity.Notify;
|
||||||
import com.imyeyu.api.modules.common.vo.NotifyManagementItem;
|
import com.imyeyu.api.modules.common.vo.NotifyManagementItem;
|
||||||
import org.apache.ibatis.annotations.Param;
|
|
||||||
import org.apache.ibatis.annotations.Select;
|
|
||||||
import com.imyeyu.spring.mapper.BaseMapper;
|
import com.imyeyu.spring.mapper.BaseMapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -16,9 +15,8 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public interface NotifyMapper extends BaseMapper<Notify, String> {
|
public interface NotifyMapper extends BaseMapper<Notify, String> {
|
||||||
|
|
||||||
/// 查询业务提醒是否已创建
|
/// 原子创建业务提醒
|
||||||
@Select("SELECT EXISTS (SELECT 1 FROM `notify` WHERE `biz_type` = #{bizType} AND `biz_reminded_type` = #{bizRemindedType} AND `biz_reminded_id` = #{bizRemindedId} AND `deleted_at` IS NULL)")
|
int insertIfAbsent(Notify notify);
|
||||||
boolean existsByBizReminded(@Param("bizType") String bizType, @Param("bizRemindedType") String bizRemindedType, @Param("bizRemindedId") String bizRemindedId);
|
|
||||||
|
|
||||||
/// 分页查询管理端通知
|
/// 分页查询管理端通知
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package com.imyeyu.api.modules.common.mapper;
|
|||||||
import com.imyeyu.api.modules.common.entity.Setting;
|
import com.imyeyu.api.modules.common.entity.Setting;
|
||||||
import com.imyeyu.spring.mapper.BaseMapper;
|
import com.imyeyu.spring.mapper.BaseMapper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 系统配置
|
* 系统配置
|
||||||
*
|
*
|
||||||
@@ -10,4 +12,6 @@ import com.imyeyu.spring.mapper.BaseMapper;
|
|||||||
* @since 2021-07-20 22:26
|
* @since 2021-07-20 22:26
|
||||||
*/
|
*/
|
||||||
public interface SettingMapper extends BaseMapper<Setting, String> {
|
public interface SettingMapper extends BaseMapper<Setting, String> {
|
||||||
|
|
||||||
|
List<Setting> selectPublicByQuery(String bizType, String bizId, List<String> codeList);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,13 +14,10 @@ import com.imyeyu.spring.service.BaseService;
|
|||||||
*/
|
*/
|
||||||
public interface NotifyService extends BaseService<Notify, String> {
|
public interface NotifyService extends BaseService<Notify, String> {
|
||||||
|
|
||||||
/// 查询业务提醒是否已创建
|
/// 原子创建业务提醒,重复查重键不会创建通知详情
|
||||||
///
|
///
|
||||||
/// @param bizType 业务类型
|
/// @param notify 通知
|
||||||
/// @param bizRemindedType 被提醒业务类型
|
void createIfAbsent(Notify notify);
|
||||||
/// @param bizRemindedId 被提醒业务 ID
|
|
||||||
/// @return true 为已创建
|
|
||||||
boolean existsByBizReminded(String bizType, String bizRemindedType, String bizRemindedId);
|
|
||||||
|
|
||||||
/// 分页查询当前用户创建的通知
|
/// 分页查询当前用户创建的通知
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import com.imyeyu.java.TimiJava;
|
|||||||
import com.imyeyu.spring.service.BaseService;
|
import com.imyeyu.spring.service.BaseService;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 配置服务
|
* 配置服务
|
||||||
@@ -24,6 +25,16 @@ public interface SettingService extends BaseService<Setting, String> {
|
|||||||
|
|
||||||
List<Setting> listByBizId(String bizType, String bizId);
|
List<Setting> listByBizId(String bizType, String bizId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询公开配置映射
|
||||||
|
*
|
||||||
|
* @param bizType 业务类型
|
||||||
|
* @param bizId 业务 ID,可为空
|
||||||
|
* @param code 配置代码列表,可为空
|
||||||
|
* @return 公开配置映射
|
||||||
|
*/
|
||||||
|
Map<String, Setting> mapPublic(String bizType, String bizId, List<String> code);
|
||||||
|
|
||||||
default List<Setting> listBySettingSupport(SettingSupport settingSupport) {
|
default List<Setting> listBySettingSupport(SettingSupport settingSupport) {
|
||||||
String bizType = settingSupport.getClass().getSimpleName().toUpperCase();
|
String bizType = settingSupport.getClass().getSimpleName().toUpperCase();
|
||||||
return listByBizId(bizType, settingSupport.getId());
|
return listByBizId(bizType, settingSupport.getId());
|
||||||
|
|||||||
+41
-46
@@ -7,9 +7,8 @@ import com.imyeyu.api.modules.common.mapper.NotifyMapper;
|
|||||||
import com.imyeyu.api.modules.common.service.NotifyDetailService;
|
import com.imyeyu.api.modules.common.service.NotifyDetailService;
|
||||||
import com.imyeyu.api.modules.common.service.NotifyService;
|
import com.imyeyu.api.modules.common.service.NotifyService;
|
||||||
import com.imyeyu.api.modules.common.vo.NotifyManagementItem;
|
import com.imyeyu.api.modules.common.vo.NotifyManagementItem;
|
||||||
import com.imyeyu.api.modules.system.entity.Logger;
|
import com.imyeyu.api.modules.system.audit.AuditOperation;
|
||||||
import com.imyeyu.api.modules.system.service.LoggerService;
|
import com.imyeyu.api.modules.system.audit.OperationAudit;
|
||||||
import com.imyeyu.api.modules.user.service.UserLoginService;
|
|
||||||
import com.imyeyu.java.TimiJava;
|
import com.imyeyu.java.TimiJava;
|
||||||
import com.imyeyu.java.bean.timi.TimiCode;
|
import com.imyeyu.java.bean.timi.TimiCode;
|
||||||
import com.imyeyu.java.bean.timi.TimiException;
|
import com.imyeyu.java.bean.timi.TimiException;
|
||||||
@@ -17,12 +16,13 @@ import com.imyeyu.spring.bean.Page;
|
|||||||
import com.imyeyu.spring.bean.PageResult;
|
import com.imyeyu.spring.bean.PageResult;
|
||||||
import com.imyeyu.spring.mapper.BaseMapper;
|
import com.imyeyu.spring.mapper.BaseMapper;
|
||||||
import com.imyeyu.spring.service.AbstractEntityService;
|
import com.imyeyu.spring.service.AbstractEntityService;
|
||||||
|
import com.imyeyu.utils.Time;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通知服务实现
|
* 通知服务实现
|
||||||
@@ -30,13 +30,10 @@ import java.util.List;
|
|||||||
* @author 夜雨
|
* @author 夜雨
|
||||||
* @since 2026-05-13 14:46
|
* @since 2026-05-13 14:46
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
|
||||||
@Service
|
@Service
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class NotifyServiceImplement extends AbstractEntityService<Notify, String> implements NotifyService {
|
public class NotifyServiceImplement extends AbstractEntityService<Notify, String> implements NotifyService {
|
||||||
|
|
||||||
private final LoggerService loggerService;
|
|
||||||
private final UserLoginService userLoginService;
|
|
||||||
private final NotifyDetailService detailService;
|
private final NotifyDetailService detailService;
|
||||||
|
|
||||||
private final NotifyMapper mapper;
|
private final NotifyMapper mapper;
|
||||||
@@ -46,44 +43,54 @@ public class NotifyServiceImplement extends AbstractEntityService<Notify, String
|
|||||||
return mapper;
|
return mapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean existsByBizReminded(String bizType, String bizRemindedType, String bizRemindedId) {
|
|
||||||
return mapper.existsByBizReminded(bizType, bizRemindedType, bizRemindedId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 创建通知并级联创建通知详情
|
/// 创建通知并级联创建通知详情
|
||||||
///
|
///
|
||||||
/// @param notify 通知
|
/// @param notify 通知
|
||||||
|
@OperationAudit(AuditOperation.COMMON_NOTIFY_CREATE)
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
@Override
|
@Override
|
||||||
public void create(Notify notify) {
|
public void create(Notify notify) {
|
||||||
Logger logger = new Logger(Logger.Module.COMMON, "COMMON_NOTIFY_CREATE");
|
prepareCreate(notify);
|
||||||
try {
|
super.create(notify);
|
||||||
|
createDetails(notify);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 原子创建业务提醒并级联创建通知详情
|
||||||
|
///
|
||||||
|
/// @param notify 通知
|
||||||
|
@OperationAudit(AuditOperation.COMMON_NOTIFY_CREATE)
|
||||||
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
|
@Override
|
||||||
|
public void createIfAbsent(Notify notify) {
|
||||||
|
prepareCreate(notify);
|
||||||
|
if (mapper.insertIfAbsent(notify) == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
createDetails(notify);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 校验并补全通知创建字段
|
||||||
|
///
|
||||||
|
/// @param notify 通知
|
||||||
|
private void prepareCreate(Notify notify) {
|
||||||
TimiException.required(notify, "未找到通知");
|
TimiException.required(notify, "未找到通知");
|
||||||
TimiException.required(notify.getDetailList(), "未找到通知详情列表");
|
TimiException.required(notify.getDetailList(), "未找到通知详情列表");
|
||||||
|
notify.setId(TimiJava.defaultIfEmpty(notify.getId(), UUID.randomUUID().toString()));
|
||||||
notify.setCreatedBy(TimiJava.defaultIfEmpty(notify.getCreatedBy(), TimiJava.ZERO_UUID));
|
notify.setCreatedBy(TimiJava.defaultIfEmpty(notify.getCreatedBy(), TimiJava.ZERO_UUID));
|
||||||
super.create(notify);
|
notify.setCreatedAt(TimiJava.defaultIfNull(notify.getCreatedAt(), Time.now()));
|
||||||
|
notify.setUpdatedAt(null);
|
||||||
|
notify.setDeletedAt(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 创建通知详情
|
||||||
|
///
|
||||||
|
/// @param notify 通知
|
||||||
|
private void createDetails(Notify notify) {
|
||||||
for (NotifyDetail detail : notify.getDetailList()) {
|
for (NotifyDetail detail : notify.getDetailList()) {
|
||||||
detail.setNotifyId(notify.getId());
|
detail.setNotifyId(notify.getId());
|
||||||
detail.setSendFrom(TimiJava.defaultIfEmpty(detail.getSendFrom(), TimiJava.ZERO_UUID));
|
detail.setSendFrom(TimiJava.defaultIfEmpty(detail.getSendFrom(), TimiJava.ZERO_UUID));
|
||||||
detailService.create(detail);
|
detailService.create(detail);
|
||||||
}
|
}
|
||||||
logger.setLevel(Logger.Level.INFO);
|
|
||||||
logger.setResult(notify.getId());
|
|
||||||
} catch (TimiException e) {
|
|
||||||
logger.setLevel(Logger.Level.WARN);
|
|
||||||
logger.setException(e.getMessage());
|
|
||||||
throw e;
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.setLevel(Logger.Level.ERROR);
|
|
||||||
logger.setException(TimiJava.serializeThrowable(e));
|
|
||||||
log.error("创建通知失败", e);
|
|
||||||
throw new TimiException(TimiCode.ERROR, "创建通知失败", e);
|
|
||||||
} finally {
|
|
||||||
loggerService.create(logger);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 分页查询当前用户创建的通知
|
/// 分页查询当前用户创建的通知
|
||||||
@@ -120,6 +127,8 @@ public class NotifyServiceImplement extends AbstractEntityService<Notify, String
|
|||||||
/// @param notifyId 通知 ID
|
/// @param notifyId 通知 ID
|
||||||
/// @param userId 用户 ID
|
/// @param userId 用户 ID
|
||||||
@Override
|
@Override
|
||||||
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
|
@OperationAudit(AuditOperation.COMMON_NOTIFY_DELETE)
|
||||||
public void deleteManagement(String notifyId, String userId) {
|
public void deleteManagement(String notifyId, String userId) {
|
||||||
getManagement(notifyId, userId);
|
getManagement(notifyId, userId);
|
||||||
delete(notifyId);
|
delete(notifyId);
|
||||||
@@ -130,6 +139,7 @@ public class NotifyServiceImplement extends AbstractEntityService<Notify, String
|
|||||||
/// @param notifyId 通知 ID
|
/// @param notifyId 通知 ID
|
||||||
/// @param userId 用户 ID
|
/// @param userId 用户 ID
|
||||||
@Override
|
@Override
|
||||||
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
public void cancelManagement(String notifyId, String userId) {
|
public void cancelManagement(String notifyId, String userId) {
|
||||||
getManagement(notifyId, userId);
|
getManagement(notifyId, userId);
|
||||||
cancel(notifyId);
|
cancel(notifyId);
|
||||||
@@ -138,11 +148,10 @@ public class NotifyServiceImplement extends AbstractEntityService<Notify, String
|
|||||||
/// 删除通知并级联软删除通知详情
|
/// 删除通知并级联软删除通知详情
|
||||||
///
|
///
|
||||||
/// @param notifyId 通知 ID
|
/// @param notifyId 通知 ID
|
||||||
|
@OperationAudit(AuditOperation.COMMON_NOTIFY_DELETE)
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
@Override
|
@Override
|
||||||
public void delete(String notifyId) {
|
public void delete(String notifyId) {
|
||||||
Logger logger = new Logger(Logger.Module.COMMON, "COMMON_NOTIFY_DELETE");
|
|
||||||
try {
|
|
||||||
TimiException.required(notifyId, "未找到通知 ID");
|
TimiException.required(notifyId, "未找到通知 ID");
|
||||||
TimiException.required(get(notifyId), "未找到通知");
|
TimiException.required(get(notifyId), "未找到通知");
|
||||||
List<NotifyDetail> detailList = detailService.listByNotifyId(notifyId);
|
List<NotifyDetail> detailList = detailService.listByNotifyId(notifyId);
|
||||||
@@ -150,20 +159,6 @@ public class NotifyServiceImplement extends AbstractEntityService<Notify, String
|
|||||||
detailService.delete(detail.getId());
|
detailService.delete(detail.getId());
|
||||||
}
|
}
|
||||||
super.delete(notifyId);
|
super.delete(notifyId);
|
||||||
logger.setLevel(Logger.Level.INFO);
|
|
||||||
logger.setResult(notifyId);
|
|
||||||
} catch (TimiException e) {
|
|
||||||
logger.setLevel(Logger.Level.WARN);
|
|
||||||
logger.setException(e.getMessage());
|
|
||||||
throw e;
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.setLevel(Logger.Level.ERROR);
|
|
||||||
logger.setException(TimiJava.serializeThrowable(e));
|
|
||||||
log.error("删除通知失败", e);
|
|
||||||
throw new TimiException(TimiCode.ERROR, "删除通知失败", e);
|
|
||||||
} finally {
|
|
||||||
loggerService.create(logger);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 取消通知中尚未成功发送的通知详情
|
/// 取消通知中尚未成功发送的通知详情
|
||||||
|
|||||||
+8
@@ -17,6 +17,8 @@ import java.util.ArrayList;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 系统配置服务实现
|
* 系统配置服务实现
|
||||||
@@ -53,6 +55,12 @@ public class SettingServiceImplement extends AbstractEntityService<Setting, Stri
|
|||||||
return mapper.selectAllByExample(example);
|
return mapper.selectAllByExample(example);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Setting> mapPublic(String bizType, String bizId, List<String> code) {
|
||||||
|
TimiException.required(bizType, "not found bizType");
|
||||||
|
return mapper.selectPublicByQuery(bizType, bizId, code).stream().collect(Collectors.toMap(Setting::getCode, Function.identity()));
|
||||||
|
}
|
||||||
|
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
@Override
|
@Override
|
||||||
public void updateByBizId(String bizType, String bizId, List<Setting> list) {
|
public void updateByBizId(String bizType, String bizId, List<Setting> list) {
|
||||||
|
|||||||
@@ -111,6 +111,8 @@ public enum GaoPermissionCode implements BuiltinPermissionCode {
|
|||||||
|
|
||||||
CUSTOMER_PACKAGE_PRICE_OVERRIDE("CUSTOMER_PACKAGE:PRICE_OVERRIDE", "客户套餐成交价和权益配额调整", true, true),
|
CUSTOMER_PACKAGE_PRICE_OVERRIDE("CUSTOMER_PACKAGE:PRICE_OVERRIDE", "客户套餐成交价和权益配额调整", true, true),
|
||||||
|
|
||||||
|
CUSTOMER_PACKAGE_GIFT_CREATE("CUSTOMER_PACKAGE:GIFT_CREATE", "客户套餐创建赠送", true, true),
|
||||||
|
|
||||||
FUND_RECORD_READ("FUND_RECORD:READ", "资金流水读取", true, true),
|
FUND_RECORD_READ("FUND_RECORD:READ", "资金流水读取", true, true),
|
||||||
|
|
||||||
FUND_RECEIVE_CREATE("FUND_RECEIVE:CREATE", "线下收款创建", true, true),
|
FUND_RECEIVE_CREATE("FUND_RECEIVE:CREATE", "线下收款创建", true, true),
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package com.imyeyu.api.modules.gao.bean;
|
||||||
|
|
||||||
|
import com.imyeyu.api.annotation.SettingBizType;
|
||||||
|
import com.imyeyu.api.bean.SettingEnum;
|
||||||
|
import com.imyeyu.api.modules.common.entity.Setting;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// @author 夜雨
|
||||||
|
/// @since 2026-09-09 16:11
|
||||||
|
@Getter
|
||||||
|
@SettingBizType("GAO_SYSTEM")
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum GaoSystemSetting implements SettingEnum {
|
||||||
|
|
||||||
|
SERVICE_LICENSE(null, Setting.ValueType.STRING),
|
||||||
|
|
||||||
|
PRIVACY_LICENSE(null, Setting.ValueType.STRING),
|
||||||
|
|
||||||
|
OPEN_SOURCE_LICENSE(null, Setting.ValueType.STRING);
|
||||||
|
|
||||||
|
final String defaultValue;
|
||||||
|
|
||||||
|
final Setting.ValueType valueType;
|
||||||
|
}
|
||||||
@@ -5,6 +5,8 @@ import com.imyeyu.api.modules.gao.bean.GaoPermissionCode;
|
|||||||
import com.imyeyu.api.modules.gao.service.GaoCustomerChartService;
|
import com.imyeyu.api.modules.gao.service.GaoCustomerChartService;
|
||||||
import com.imyeyu.api.modules.gao.service.GaoStoreScopeService;
|
import com.imyeyu.api.modules.gao.service.GaoStoreScopeService;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoCustomerChartReq;
|
import com.imyeyu.api.modules.gao.vo.GaoCustomerChartReq;
|
||||||
|
import com.imyeyu.api.modules.gao.vo.GaoCustomerDiseaseWordReq;
|
||||||
|
import com.imyeyu.api.modules.gao.vo.GaoCustomerDiseaseWordView;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoEventRecordCalendarView;
|
import com.imyeyu.api.modules.gao.vo.GaoEventRecordCalendarView;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoEventRecordDailyStatView;
|
import com.imyeyu.api.modules.gao.vo.GaoEventRecordDailyStatView;
|
||||||
import com.imyeyu.java.bean.timi.TimiException;
|
import com.imyeyu.java.bean.timi.TimiException;
|
||||||
@@ -51,4 +53,15 @@ public class GaoCustomerChartController {
|
|||||||
req.setStoreId(storeScopeService.resolveStoreId(req.getStoreId()));
|
req.setStoreId(storeScopeService.resolveStoreId(req.getStoreId()));
|
||||||
return service.eventRecordCalendar(req);
|
return service.eventRecordCalendar(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 查询客户病症词频
|
||||||
|
@AOPLog
|
||||||
|
@RequestRateLimit
|
||||||
|
@RequireGaoPermission(GaoPermissionCode.STAT_READ)
|
||||||
|
@PostMapping("/customer/disease/word")
|
||||||
|
public List<GaoCustomerDiseaseWordView> customerDiseaseWord(@RequestBody GaoCustomerDiseaseWordReq req) {
|
||||||
|
TimiException.required(req, "not found req");
|
||||||
|
req.setStoreId(storeScopeService.resolveStoreId(req.getStoreId()));
|
||||||
|
return service.customerDiseaseWord(req);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package com.imyeyu.api.modules.gao.controller;
|
package com.imyeyu.api.modules.gao.controller;
|
||||||
|
|
||||||
|
import com.imyeyu.api.bean.PermissionMatchMode;
|
||||||
import com.imyeyu.api.modules.gao.annotation.RequireGaoPermission;
|
import com.imyeyu.api.modules.gao.annotation.RequireGaoPermission;
|
||||||
import com.imyeyu.api.modules.gao.bean.GaoPermissionCode;
|
import com.imyeyu.api.modules.gao.bean.GaoPermissionCode;
|
||||||
import com.imyeyu.api.bean.PermissionMatchMode;
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoFundRecord;
|
import com.imyeyu.api.modules.gao.entity.GaoFundRecord;
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoSalesOrder;
|
import com.imyeyu.api.modules.gao.entity.GaoSalesOrder;
|
||||||
import com.imyeyu.api.modules.gao.service.GaoOrderPaymentService;
|
import com.imyeyu.api.modules.gao.service.GaoOrderPaymentService;
|
||||||
@@ -17,6 +17,8 @@ import com.imyeyu.api.modules.gao.vo.GaoOrderPaymentRevokeRequest;
|
|||||||
import com.imyeyu.api.modules.gao.vo.GaoSalesOrderCancelRequest;
|
import com.imyeyu.api.modules.gao.vo.GaoSalesOrderCancelRequest;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoSalesOrderPage;
|
import com.imyeyu.api.modules.gao.vo.GaoSalesOrderPage;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoSalesOrderUpdateRequest;
|
import com.imyeyu.api.modules.gao.vo.GaoSalesOrderUpdateRequest;
|
||||||
|
import com.imyeyu.api.modules.user.service.UserService;
|
||||||
|
import com.imyeyu.java.TimiJava;
|
||||||
import com.imyeyu.java.bean.timi.TimiException;
|
import com.imyeyu.java.bean.timi.TimiException;
|
||||||
import com.imyeyu.spring.annotation.AOPLog;
|
import com.imyeyu.spring.annotation.AOPLog;
|
||||||
import com.imyeyu.spring.annotation.RequestRateLimit;
|
import com.imyeyu.spring.annotation.RequestRateLimit;
|
||||||
@@ -40,6 +42,7 @@ public class GaoSalesOrderController {
|
|||||||
private final GaoSalesOrderService service;
|
private final GaoSalesOrderService service;
|
||||||
private final GaoOrderPaymentService paymentService;
|
private final GaoOrderPaymentService paymentService;
|
||||||
private final GaoStoreScopeService storeScopeService;
|
private final GaoStoreScopeService storeScopeService;
|
||||||
|
private final UserService userService;
|
||||||
|
|
||||||
@AOPLog
|
@AOPLog
|
||||||
@RequestRateLimit
|
@RequestRateLimit
|
||||||
@@ -56,7 +59,11 @@ public class GaoSalesOrderController {
|
|||||||
@RequireGaoPermission(GaoPermissionCode.SALES_ORDER_READ)
|
@RequireGaoPermission(GaoPermissionCode.SALES_ORDER_READ)
|
||||||
@PostMapping("/detail")
|
@PostMapping("/detail")
|
||||||
public GaoSalesOrder detail(@RequestParam String id) {
|
public GaoSalesOrder detail(@RequestParam String id) {
|
||||||
return service.detail(id);
|
GaoSalesOrder result = service.detail(id);
|
||||||
|
if (TimiJava.isNotEmpty(result.getCancelOperatorUserId())) {
|
||||||
|
result.setCancelOperator(userService.get(result.getCancelOperatorUserId()));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@AOPLog
|
@AOPLog
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import com.imyeyu.api.modules.gao.annotation.RequireGaoPermission;
|
|||||||
import com.imyeyu.api.modules.gao.bean.GaoPermissionCode;
|
import com.imyeyu.api.modules.gao.bean.GaoPermissionCode;
|
||||||
import com.imyeyu.api.modules.gao.service.GaoStoreChartService;
|
import com.imyeyu.api.modules.gao.service.GaoStoreChartService;
|
||||||
import com.imyeyu.api.modules.gao.service.GaoStoreScopeService;
|
import com.imyeyu.api.modules.gao.service.GaoStoreScopeService;
|
||||||
|
import com.imyeyu.api.modules.gao.vo.GaoCustomerAgeStatView;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoCustomerDailyStateView;
|
import com.imyeyu.api.modules.gao.vo.GaoCustomerDailyStateView;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoCustomerGenderStatView;
|
import com.imyeyu.api.modules.gao.vo.GaoCustomerGenderStatView;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoEventRecordCalendarView;
|
import com.imyeyu.api.modules.gao.vo.GaoEventRecordCalendarView;
|
||||||
@@ -54,6 +55,15 @@ public class GaoStoreChartController {
|
|||||||
return service.customerGender(storeScopeService.resolveStoreId(storeId));
|
return service.customerGender(storeScopeService.resolveStoreId(storeId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 查询客户年龄分布
|
||||||
|
@AOPLog
|
||||||
|
@RequestRateLimit
|
||||||
|
@RequireGaoPermission(GaoPermissionCode.STAT_READ)
|
||||||
|
@PostMapping("/customer/age")
|
||||||
|
public List<GaoCustomerAgeStatView> customerAge(@RequestParam String storeId) {
|
||||||
|
return service.customerAge(storeScopeService.resolveStoreId(storeId));
|
||||||
|
}
|
||||||
|
|
||||||
/// 查询登记事件每日统计,可同时支撑登记趋势和事件结构图表
|
/// 查询登记事件每日统计,可同时支撑登记趋势和事件结构图表
|
||||||
@AOPLog
|
@AOPLog
|
||||||
@RequestRateLimit
|
@RequestRateLimit
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import com.imyeyu.api.modules.common.entity.Attachment;
|
|||||||
import com.imyeyu.api.modules.common.entity.TagApply;
|
import com.imyeyu.api.modules.common.entity.TagApply;
|
||||||
import com.imyeyu.api.modules.user.bean.Gender;
|
import com.imyeyu.api.modules.user.bean.Gender;
|
||||||
import com.imyeyu.api.modules.user.entity.User;
|
import com.imyeyu.api.modules.user.entity.User;
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
|
||||||
import com.imyeyu.java.TimiJava;
|
import com.imyeyu.java.TimiJava;
|
||||||
import com.imyeyu.spring.annotation.table.Column;
|
import com.imyeyu.spring.annotation.table.Column;
|
||||||
import com.imyeyu.spring.annotation.table.Transient;
|
import com.imyeyu.spring.annotation.table.Transient;
|
||||||
@@ -62,15 +61,12 @@ public class GaoCustomer extends UUIDEntity {
|
|||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@Column("name_pinyin_full")
|
@Column("name_pinyin_full")
|
||||||
@JsonIgnore
|
|
||||||
private String namePinyinFull;
|
private String namePinyinFull;
|
||||||
|
|
||||||
@Column("name_pinyin_initial")
|
@Column("name_pinyin_initial")
|
||||||
@JsonIgnore
|
|
||||||
private String namePinyinInitial;
|
private String namePinyinInitial;
|
||||||
|
|
||||||
@Column("name_pinyin_mixed")
|
@Column("name_pinyin_mixed")
|
||||||
@JsonIgnore
|
|
||||||
private String namePinyinMixed;
|
private String namePinyinMixed;
|
||||||
|
|
||||||
/// 性别
|
/// 性别
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package com.imyeyu.api.modules.gao.entity;
|
package com.imyeyu.api.modules.gao.entity;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import com.imyeyu.api.modules.common.entity.Attachment;
|
import com.imyeyu.api.modules.common.entity.Attachment;
|
||||||
|
import com.imyeyu.spring.annotation.table.Column;
|
||||||
import com.imyeyu.spring.annotation.table.Transient;
|
import com.imyeyu.spring.annotation.table.Transient;
|
||||||
import com.imyeyu.spring.entity.UUIDEntity;
|
import com.imyeyu.spring.entity.UUIDEntity;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -61,6 +63,18 @@ public class GaoProduct extends UUIDEntity {
|
|||||||
/// 产品名称
|
/// 产品名称
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
|
@Column("name_pinyin_full")
|
||||||
|
@JsonIgnore
|
||||||
|
private String namePinyinFull;
|
||||||
|
|
||||||
|
@Column("name_pinyin_initial")
|
||||||
|
@JsonIgnore
|
||||||
|
private String namePinyinInitial;
|
||||||
|
|
||||||
|
@Column("name_pinyin_mixed")
|
||||||
|
@JsonIgnore
|
||||||
|
private String namePinyinMixed;
|
||||||
|
|
||||||
/// 产品类型
|
/// 产品类型
|
||||||
private ProductType productType;
|
private ProductType productType;
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,9 @@ public class GaoSalesOrderItem extends UUIDEntity {
|
|||||||
/// 订单项类型
|
/// 订单项类型
|
||||||
private ItemType itemType;
|
private ItemType itemType;
|
||||||
|
|
||||||
|
/// true 为赠送权益
|
||||||
|
private Boolean gifted;
|
||||||
|
|
||||||
/// SKU ID
|
/// SKU ID
|
||||||
private String skuId;
|
private String skuId;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
package com.imyeyu.api.modules.gao.mapper;
|
package com.imyeyu.api.modules.gao.mapper;
|
||||||
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoCustomer;
|
import com.imyeyu.api.modules.gao.entity.GaoCustomer;
|
||||||
|
import com.imyeyu.api.modules.gao.vo.GaoCustomerAgeStatView;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoCustomerDailyStateView;
|
import com.imyeyu.api.modules.gao.vo.GaoCustomerDailyStateView;
|
||||||
|
import com.imyeyu.api.modules.gao.vo.GaoCustomerDailyStateCustomerView;
|
||||||
|
import com.imyeyu.api.modules.gao.vo.GaoCustomerDiseaseTextView;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoCustomerGenderStatView;
|
import com.imyeyu.api.modules.gao.vo.GaoCustomerGenderStatView;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoCustomerPage;
|
import com.imyeyu.api.modules.gao.vo.GaoCustomerPage;
|
||||||
import com.imyeyu.spring.mapper.BaseMapper;
|
import com.imyeyu.spring.mapper.BaseMapper;
|
||||||
@@ -27,6 +30,14 @@ public interface GaoCustomerMapper extends BaseMapper<GaoCustomer, String> {
|
|||||||
/// @return 每日新增客户数
|
/// @return 每日新增客户数
|
||||||
List<GaoCustomerDailyStateView> stateDailyNewCustomer(@Param("storeId") String storeId, @Param("beginCreatedAt") Long beginCreatedAt, @Param("endCreatedAt") Long endCreatedAt);
|
List<GaoCustomerDailyStateView> stateDailyNewCustomer(@Param("storeId") String storeId, @Param("beginCreatedAt") Long beginCreatedAt, @Param("endCreatedAt") Long endCreatedAt);
|
||||||
|
|
||||||
|
/// 查询每日新增客户摘要
|
||||||
|
///
|
||||||
|
/// @param storeId 门店 ID
|
||||||
|
/// @param beginCreatedAt 开始创建时间
|
||||||
|
/// @param endCreatedAt 结束创建时间
|
||||||
|
/// @return 每日新增客户摘要
|
||||||
|
List<GaoCustomerDailyStateCustomerView> selectDailyNewCustomer(@Param("storeId") String storeId, @Param("beginCreatedAt") Long beginCreatedAt, @Param("endCreatedAt") Long endCreatedAt);
|
||||||
|
|
||||||
/// 统计开始时间前客户总数
|
/// 统计开始时间前客户总数
|
||||||
///
|
///
|
||||||
/// @param beginCreatedAt 开始创建时间
|
/// @param beginCreatedAt 开始创建时间
|
||||||
@@ -38,6 +49,18 @@ public interface GaoCustomerMapper extends BaseMapper<GaoCustomer, String> {
|
|||||||
/// @return 性别统计列表
|
/// @return 性别统计列表
|
||||||
List<GaoCustomerGenderStatView> stateGender(@Param("storeId") String storeId);
|
List<GaoCustomerGenderStatView> stateGender(@Param("storeId") String storeId);
|
||||||
|
|
||||||
|
/// 统计客户年龄分布
|
||||||
|
///
|
||||||
|
/// @param storeId 门店 ID
|
||||||
|
/// @return 客户年龄列表
|
||||||
|
List<GaoCustomerAgeStatView> stateAge(@Param("storeId") String storeId);
|
||||||
|
|
||||||
|
/// 查询客户病症原始文本
|
||||||
|
///
|
||||||
|
/// @param storeId 门店 ID
|
||||||
|
/// @return 客户备注和病症
|
||||||
|
List<GaoCustomerDiseaseTextView> selectDiseaseTextByStoreId(@Param("storeId") String storeId);
|
||||||
|
|
||||||
/// 查询客户总数
|
/// 查询客户总数
|
||||||
///
|
///
|
||||||
/// @param page 查询条件
|
/// @param page 查询条件
|
||||||
@@ -55,5 +78,5 @@ public interface GaoCustomerMapper extends BaseMapper<GaoCustomer, String> {
|
|||||||
/// @param customerId 客户 ID
|
/// @param customerId 客户 ID
|
||||||
/// @param delta 变化量
|
/// @param delta 变化量
|
||||||
@Update("UPDATE `gao_customer` SET `invited_count` = GREATEST(IFNULL(`invited_count`, 0) + #{delta}, 0), `updated_at` = " + UNIX_TIME + " WHERE `id` = #{customerId}" + NOT_DELETE)
|
@Update("UPDATE `gao_customer` SET `invited_count` = GREATEST(IFNULL(`invited_count`, 0) + #{delta}, 0), `updated_at` = " + UNIX_TIME + " WHERE `id` = #{customerId}" + NOT_DELETE)
|
||||||
void updateInvitedCountDelta(@Param("customerId") String customerId, @Param("delta") Long delta);
|
void updateInvitedCountDelta(String customerId, Long delta);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package com.imyeyu.api.modules.gao.service;
|
package com.imyeyu.api.modules.gao.service;
|
||||||
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoCustomerChartReq;
|
import com.imyeyu.api.modules.gao.vo.GaoCustomerChartReq;
|
||||||
|
import com.imyeyu.api.modules.gao.vo.GaoCustomerDiseaseWordReq;
|
||||||
|
import com.imyeyu.api.modules.gao.vo.GaoCustomerDiseaseWordView;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoEventRecordCalendarView;
|
import com.imyeyu.api.modules.gao.vo.GaoEventRecordCalendarView;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoEventRecordDailyStatView;
|
import com.imyeyu.api.modules.gao.vo.GaoEventRecordDailyStatView;
|
||||||
|
|
||||||
@@ -17,4 +19,7 @@ public interface GaoCustomerChartService {
|
|||||||
|
|
||||||
/// 查询客户登记日历记录
|
/// 查询客户登记日历记录
|
||||||
List<GaoEventRecordCalendarView> eventRecordCalendar(GaoCustomerChartReq req);
|
List<GaoEventRecordCalendarView> eventRecordCalendar(GaoCustomerChartReq req);
|
||||||
|
|
||||||
|
/// 查询客户病症词频
|
||||||
|
List<GaoCustomerDiseaseWordView> customerDiseaseWord(GaoCustomerDiseaseWordReq req);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.imyeyu.api.modules.gao.service;
|
package com.imyeyu.api.modules.gao.service;
|
||||||
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoCustomer;
|
import com.imyeyu.api.modules.gao.entity.GaoCustomer;
|
||||||
|
import com.imyeyu.api.modules.gao.vo.GaoCustomerAgeStatView;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoCustomerDailyStateView;
|
import com.imyeyu.api.modules.gao.vo.GaoCustomerDailyStateView;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoCustomerGenderStatView;
|
import com.imyeyu.api.modules.gao.vo.GaoCustomerGenderStatView;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoCustomerPage;
|
import com.imyeyu.api.modules.gao.vo.GaoCustomerPage;
|
||||||
@@ -87,4 +88,10 @@ public interface GaoCustomerService extends BaseService<GaoCustomer, String> {
|
|||||||
/// @param storeId 门店 ID
|
/// @param storeId 门店 ID
|
||||||
/// @return 性别统计列表
|
/// @return 性别统计列表
|
||||||
List<GaoCustomerGenderStatView> stateGender(String storeId);
|
List<GaoCustomerGenderStatView> stateGender(String storeId);
|
||||||
|
|
||||||
|
/// 统计客户年龄分布
|
||||||
|
///
|
||||||
|
/// @param storeId 门店 ID
|
||||||
|
/// @return 客户年龄列表
|
||||||
|
List<GaoCustomerAgeStatView> stateAge(String storeId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.imyeyu.api.modules.gao.service;
|
package com.imyeyu.api.modules.gao.service;
|
||||||
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoCustomerDailyStateView;
|
import com.imyeyu.api.modules.gao.vo.GaoCustomerDailyStateView;
|
||||||
|
import com.imyeyu.api.modules.gao.vo.GaoCustomerAgeStatView;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoCustomerGenderStatView;
|
import com.imyeyu.api.modules.gao.vo.GaoCustomerGenderStatView;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoEventRecordCalendarView;
|
import com.imyeyu.api.modules.gao.vo.GaoEventRecordCalendarView;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoEventRecordDailyStatView;
|
import com.imyeyu.api.modules.gao.vo.GaoEventRecordDailyStatView;
|
||||||
@@ -21,6 +22,9 @@ public interface GaoStoreChartService {
|
|||||||
/// 查询客户性别统计
|
/// 查询客户性别统计
|
||||||
List<GaoCustomerGenderStatView> customerGender(String storeId);
|
List<GaoCustomerGenderStatView> customerGender(String storeId);
|
||||||
|
|
||||||
|
/// 查询客户年龄分布
|
||||||
|
List<GaoCustomerAgeStatView> customerAge(String storeId);
|
||||||
|
|
||||||
/// 查询登记事件每日统计
|
/// 查询登记事件每日统计
|
||||||
List<GaoEventRecordDailyStatView> eventRecordDailyStat(GaoStoreChartReq req);
|
List<GaoEventRecordDailyStatView> eventRecordDailyStat(GaoStoreChartReq req);
|
||||||
|
|
||||||
|
|||||||
+45
@@ -1,15 +1,23 @@
|
|||||||
package com.imyeyu.api.modules.gao.service.implement;
|
package com.imyeyu.api.modules.gao.service.implement;
|
||||||
|
|
||||||
|
import com.hankcs.hanlp.seg.common.Term;
|
||||||
|
import com.hankcs.hanlp.tokenizer.StandardTokenizer;
|
||||||
|
import com.imyeyu.api.modules.gao.mapper.GaoCustomerMapper;
|
||||||
import com.imyeyu.api.modules.gao.service.GaoCustomerChartService;
|
import com.imyeyu.api.modules.gao.service.GaoCustomerChartService;
|
||||||
import com.imyeyu.api.modules.gao.service.GaoEventRecordService;
|
import com.imyeyu.api.modules.gao.service.GaoEventRecordService;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoCustomerChartReq;
|
import com.imyeyu.api.modules.gao.vo.GaoCustomerChartReq;
|
||||||
|
import com.imyeyu.api.modules.gao.vo.GaoCustomerDiseaseTextView;
|
||||||
|
import com.imyeyu.api.modules.gao.vo.GaoCustomerDiseaseWordReq;
|
||||||
|
import com.imyeyu.api.modules.gao.vo.GaoCustomerDiseaseWordView;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoEventRecordCalendarView;
|
import com.imyeyu.api.modules.gao.vo.GaoEventRecordCalendarView;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoEventRecordDailyStatView;
|
import com.imyeyu.api.modules.gao.vo.GaoEventRecordDailyStatView;
|
||||||
import com.imyeyu.java.bean.timi.TimiException;
|
import com.imyeyu.java.bean.timi.TimiException;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/// 客户报表服务实现
|
/// 客户报表服务实现
|
||||||
///
|
///
|
||||||
@@ -20,6 +28,7 @@ import java.util.List;
|
|||||||
public class GaoCustomerChartServiceImplement implements GaoCustomerChartService {
|
public class GaoCustomerChartServiceImplement implements GaoCustomerChartService {
|
||||||
|
|
||||||
private final GaoEventRecordService eventRecordService;
|
private final GaoEventRecordService eventRecordService;
|
||||||
|
private final GaoCustomerMapper customerMapper;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<GaoEventRecordDailyStatView> eventRecordDailyStat(GaoCustomerChartReq req) {
|
public List<GaoEventRecordDailyStatView> eventRecordDailyStat(GaoCustomerChartReq req) {
|
||||||
@@ -33,6 +42,42 @@ public class GaoCustomerChartServiceImplement implements GaoCustomerChartService
|
|||||||
return eventRecordService.calendarByCustomerRange(req);
|
return eventRecordService.calendarByCustomerRange(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<GaoCustomerDiseaseWordView> customerDiseaseWord(GaoCustomerDiseaseWordReq req) {
|
||||||
|
TimiException.required(req, "not found req");
|
||||||
|
TimiException.required(req.getStoreId(), "not found req.storeId");
|
||||||
|
|
||||||
|
int topN = normalizeTopN(req.getTopN());
|
||||||
|
Map<String, Long> wordCountMap = new HashMap<>();
|
||||||
|
for (GaoCustomerDiseaseTextView customer : customerMapper.selectDiseaseTextByStoreId(req.getStoreId())) {
|
||||||
|
countNounWord(customer.getDisease(), wordCountMap);
|
||||||
|
countNounWord(customer.getRemark(), wordCountMap);
|
||||||
|
}
|
||||||
|
return wordCountMap.entrySet().stream()
|
||||||
|
.sorted(Map.Entry.<String, Long>comparingByValue().reversed().thenComparing(Map.Entry.comparingByKey()))
|
||||||
|
.limit(topN)
|
||||||
|
.map(item -> new GaoCustomerDiseaseWordView(item.getKey(), item.getValue()))
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void countNounWord(String text, Map<String, Long> wordCountMap) {
|
||||||
|
if (text == null || text.isBlank()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (Term term : StandardTokenizer.segment(text)) {
|
||||||
|
if (term.nature != null && term.nature.toString().startsWith("n")) {
|
||||||
|
wordCountMap.merge(term.word, 1L, Long::sum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int normalizeTopN(Integer topN) {
|
||||||
|
if (topN == null) {
|
||||||
|
return 60;
|
||||||
|
}
|
||||||
|
return Math.clamp(topN, 1, 100);
|
||||||
|
}
|
||||||
|
|
||||||
private void checkRangeReq(GaoCustomerChartReq req) {
|
private void checkRangeReq(GaoCustomerChartReq req) {
|
||||||
TimiException.required(req, "not found req");
|
TimiException.required(req, "not found req");
|
||||||
TimiException.required(req.getStoreId(), "not found req.storeId");
|
TimiException.required(req.getStoreId(), "not found req.storeId");
|
||||||
|
|||||||
+57
-7
@@ -4,6 +4,7 @@ import com.imyeyu.api.bean.ModuleCode;
|
|||||||
import com.imyeyu.api.config.dbsource.TimiServerDBConfig;
|
import com.imyeyu.api.config.dbsource.TimiServerDBConfig;
|
||||||
import com.imyeyu.api.modules.common.entity.Attachment;
|
import com.imyeyu.api.modules.common.entity.Attachment;
|
||||||
import com.imyeyu.api.modules.common.service.AttachmentService;
|
import com.imyeyu.api.modules.common.service.AttachmentService;
|
||||||
|
import com.imyeyu.api.modules.gao.bean.GaoPermissionCode;
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoCustomer;
|
import com.imyeyu.api.modules.gao.entity.GaoCustomer;
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoCustomerPackage;
|
import com.imyeyu.api.modules.gao.entity.GaoCustomerPackage;
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoPackageConfig;
|
import com.imyeyu.api.modules.gao.entity.GaoPackageConfig;
|
||||||
@@ -44,6 +45,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -151,10 +153,13 @@ public class GaoCustomerPackageServiceImplement extends AbstractEntityService<Ga
|
|||||||
request.setItemList(defaultPurchaseItems(configItemList));
|
request.setItemList(defaultPurchaseItems(configItemList));
|
||||||
}
|
}
|
||||||
List<GaoCustomerPackagePurchaseItem> requestItemList = new ArrayList<>(request.getItemList());
|
List<GaoCustomerPackagePurchaseItem> requestItemList = new ArrayList<>(request.getItemList());
|
||||||
|
normalizePurchaseItems(requestItemList);
|
||||||
verifyPurchaseItems(requestItemList);
|
verifyPurchaseItems(requestItemList);
|
||||||
boolean canOverridePriceAndQuantity = permissionChecker.hasAny(ModuleCode.GAO,
|
boolean canOverridePriceAndQuantity = permissionChecker.hasAny(ModuleCode.GAO,
|
||||||
com.imyeyu.api.modules.gao.bean.GaoPermissionCode.CUSTOMER_PACKAGE_PRICE_OVERRIDE.getValue());
|
GaoPermissionCode.CUSTOMER_PACKAGE_PRICE_OVERRIDE.getValue());
|
||||||
List<GaoCustomerPackagePurchaseItem> itemList = resolvePurchaseItems(config.getStoreId(), requestItemList, configItemList, canOverridePriceAndQuantity);
|
boolean canCreateGift = permissionChecker.hasAny(ModuleCode.GAO, GaoPermissionCode.CUSTOMER_PACKAGE_GIFT_CREATE.getValue());
|
||||||
|
List<GaoCustomerPackagePurchaseItem> itemList = resolvePurchaseItems(config.getStoreId(), requestItemList, configItemList,
|
||||||
|
canOverridePriceAndQuantity, canCreateGift);
|
||||||
itemList.sort(Comparator.comparing(GaoCustomerPackagePurchaseItem::getSort).thenComparing(GaoCustomerPackagePurchaseItem::getSkuId)
|
itemList.sort(Comparator.comparing(GaoCustomerPackagePurchaseItem::getSort).thenComparing(GaoCustomerPackagePurchaseItem::getSkuId)
|
||||||
.thenComparing(GaoCustomerPackagePurchaseItem::getSkuUnitId));
|
.thenComparing(GaoCustomerPackagePurchaseItem::getSkuUnitId));
|
||||||
request.setItemList(itemList);
|
request.setItemList(itemList);
|
||||||
@@ -246,6 +251,7 @@ public class GaoCustomerPackageServiceImplement extends AbstractEntityService<Ga
|
|||||||
GaoCustomerPackagePurchaseItem item = new GaoCustomerPackagePurchaseItem();
|
GaoCustomerPackagePurchaseItem item = new GaoCustomerPackagePurchaseItem();
|
||||||
item.setSkuId(configItem.getSkuId());
|
item.setSkuId(configItem.getSkuId());
|
||||||
item.setSkuUnitId(configItem.getSkuUnitId());
|
item.setSkuUnitId(configItem.getSkuUnitId());
|
||||||
|
item.setGifted(false);
|
||||||
item.setProductNameSnapshot(configItem.getProductNameSnapshot());
|
item.setProductNameSnapshot(configItem.getProductNameSnapshot());
|
||||||
item.setProductIdSnapshot(configItem.getProductIdSnapshot());
|
item.setProductIdSnapshot(configItem.getProductIdSnapshot());
|
||||||
item.setSkuCodeSnapshot(configItem.getSkuCodeSnapshot());
|
item.setSkuCodeSnapshot(configItem.getSkuCodeSnapshot());
|
||||||
@@ -265,6 +271,7 @@ public class GaoCustomerPackageServiceImplement extends AbstractEntityService<Ga
|
|||||||
item.setItemType(GaoSalesOrderItem.ItemType.PACKAGE_ENTITLEMENT);
|
item.setItemType(GaoSalesOrderItem.ItemType.PACKAGE_ENTITLEMENT);
|
||||||
item.setSkuId(source.getSkuId());
|
item.setSkuId(source.getSkuId());
|
||||||
item.setSkuUnitId(source.getSkuUnitId());
|
item.setSkuUnitId(source.getSkuUnitId());
|
||||||
|
item.setGifted(Boolean.TRUE.equals(source.getGifted()));
|
||||||
item.setProductNameSnapshot(source.getProductNameSnapshot());
|
item.setProductNameSnapshot(source.getProductNameSnapshot());
|
||||||
item.setProductIdSnapshot(source.getProductIdSnapshot());
|
item.setProductIdSnapshot(source.getProductIdSnapshot());
|
||||||
item.setSkuCodeSnapshot(source.getSkuCodeSnapshot());
|
item.setSkuCodeSnapshot(source.getSkuCodeSnapshot());
|
||||||
@@ -284,6 +291,32 @@ public class GaoCustomerPackageServiceImplement extends AbstractEntityService<Ga
|
|||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void normalizePurchaseItems(List<GaoCustomerPackagePurchaseItem> itemList) {
|
||||||
|
Map<String, Integer> indexMap = new LinkedHashMap<>();
|
||||||
|
for (int i = 0; i < itemList.size(); i++) {
|
||||||
|
GaoCustomerPackagePurchaseItem item = itemList.get(i);
|
||||||
|
if (item == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
item.setGifted(Boolean.TRUE.equals(item.getGifted()));
|
||||||
|
if (item.getSkuId() == null || item.getSkuUnitId() == null || item.getTotalQuantity() == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String key = item.getSkuId() + "|" + item.getSkuUnitId() + "|" + item.getGifted();
|
||||||
|
Integer existingIndex = indexMap.putIfAbsent(key, i);
|
||||||
|
if (existingIndex == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
GaoCustomerPackagePurchaseItem existingItem = itemList.get(existingIndex);
|
||||||
|
if (existingItem == null || existingItem.getTotalQuantity() == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
existingItem.setTotalQuantity(existingItem.getTotalQuantity().add(item.getTotalQuantity()));
|
||||||
|
itemList.set(i, null);
|
||||||
|
}
|
||||||
|
itemList.removeIf(item -> item == null);
|
||||||
|
}
|
||||||
|
|
||||||
private void verifyPurchaseItems(List<GaoCustomerPackagePurchaseItem> itemList) {
|
private void verifyPurchaseItems(List<GaoCustomerPackagePurchaseItem> itemList) {
|
||||||
Set<String> keySet = new HashSet<>();
|
Set<String> keySet = new HashSet<>();
|
||||||
for (int i = 0; i < itemList.size(); i++) {
|
for (int i = 0; i < itemList.size(); i++) {
|
||||||
@@ -294,14 +327,15 @@ public class GaoCustomerPackageServiceImplement extends AbstractEntityService<Ga
|
|||||||
TimiException.required(item.getTotalQuantity(), "购买产品数量不能为空");
|
TimiException.required(item.getTotalQuantity(), "购买产品数量不能为空");
|
||||||
TimiException.requiredTrue(0 <= item.getTotalQuantity().signum(), "购买产品数量不能为负数");
|
TimiException.requiredTrue(0 <= item.getTotalQuantity().signum(), "购买产品数量不能为负数");
|
||||||
TimiException.requiredTrue(3 >= item.getTotalQuantity().stripTrailingZeros().scale(), "购买产品数量最多保留三位小数");
|
TimiException.requiredTrue(3 >= item.getTotalQuantity().stripTrailingZeros().scale(), "购买产品数量最多保留三位小数");
|
||||||
String key = item.getSkuId() + "|" + item.getSkuUnitId();
|
item.setGifted(Boolean.TRUE.equals(item.getGifted()));
|
||||||
|
String key = item.getSkuId() + "|" + item.getSkuUnitId() + "|" + item.getGifted();
|
||||||
TimiException.requiredTrue(keySet.add(key), "购买套餐内 SKU 和单位不能重复");
|
TimiException.requiredTrue(keySet.add(key), "购买套餐内 SKU 和单位不能重复");
|
||||||
item.setSort(TimiJava.defaultIfNull(item.getSort(), i));
|
item.setSort(TimiJava.defaultIfNull(item.getSort(), i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<GaoCustomerPackagePurchaseItem> resolvePurchaseItems(String storeId, List<GaoCustomerPackagePurchaseItem> requestItemList,
|
private List<GaoCustomerPackagePurchaseItem> resolvePurchaseItems(String storeId, List<GaoCustomerPackagePurchaseItem> requestItemList,
|
||||||
List<GaoPackageConfigItem> configItemList, boolean canOverridePriceAndQuantity) {
|
List<GaoPackageConfigItem> configItemList, boolean canOverridePriceAndQuantity, boolean canCreateGift) {
|
||||||
Map<String, List<GaoPackageConfigItem>> configItemMap = configItemList.stream()
|
Map<String, List<GaoPackageConfigItem>> configItemMap = configItemList.stream()
|
||||||
.collect(Collectors.groupingBy(GaoPackageConfigItem::getSkuId));
|
.collect(Collectors.groupingBy(GaoPackageConfigItem::getSkuId));
|
||||||
Map<String, BigDecimal> configBaseQuantityMap = new HashMap<>();
|
Map<String, BigDecimal> configBaseQuantityMap = new HashMap<>();
|
||||||
@@ -312,23 +346,32 @@ public class GaoCustomerPackageServiceImplement extends AbstractEntityService<Ga
|
|||||||
Map<String, BigDecimal> requestBaseQuantityMap = new HashMap<>();
|
Map<String, BigDecimal> requestBaseQuantityMap = new HashMap<>();
|
||||||
List<GaoCustomerPackagePurchaseItem> result = new ArrayList<>();
|
List<GaoCustomerPackagePurchaseItem> result = new ArrayList<>();
|
||||||
for (GaoCustomerPackagePurchaseItem requestItem : requestItemList) {
|
for (GaoCustomerPackagePurchaseItem requestItem : requestItemList) {
|
||||||
|
boolean gifted = Boolean.TRUE.equals(requestItem.getGifted());
|
||||||
List<GaoPackageConfigItem> skuConfigItemList = configItemMap.get(requestItem.getSkuId());
|
List<GaoPackageConfigItem> skuConfigItemList = configItemMap.get(requestItem.getSkuId());
|
||||||
|
if (gifted) {
|
||||||
|
TimiException.requiredTrue(canCreateGift, "没有客户套餐创建赠送权限");
|
||||||
|
} else {
|
||||||
TimiException.requiredTrue(skuConfigItemList != null && !skuConfigItemList.isEmpty(), "购买 SKU 不属于套餐配置");
|
TimiException.requiredTrue(skuConfigItemList != null && !skuConfigItemList.isEmpty(), "购买 SKU 不属于套餐配置");
|
||||||
|
}
|
||||||
GaoProductSkuUnitSelection selection = skuService.getSellableSkuUnit(storeId, requestItem.getSkuId(), requestItem.getSkuUnitId());
|
GaoProductSkuUnitSelection selection = skuService.getSellableSkuUnit(storeId, requestItem.getSkuId(), requestItem.getSkuUnitId());
|
||||||
|
if (!gifted) {
|
||||||
TimiException.requiredTrue(skuConfigItemList.stream().anyMatch(configItem -> 0 <= configItem.getBaseQuantityPerUnitSnapshot()
|
TimiException.requiredTrue(skuConfigItemList.stream().anyMatch(configItem -> 0 <= configItem.getBaseQuantityPerUnitSnapshot()
|
||||||
.compareTo(selection.getUnit().getBaseQuantityPerUnit())), "套餐权益单位不能高于配置单位");
|
.compareTo(selection.getUnit().getBaseQuantityPerUnit())), "套餐权益单位不能高于配置单位");
|
||||||
|
}
|
||||||
BigDecimal requestBaseQuantity = toBaseQuantity(requestItem.getTotalQuantity(), selection.getUnit().getBaseQuantityPerUnit(), "套餐权益基础数量最多保留三位小数");
|
BigDecimal requestBaseQuantity = toBaseQuantity(requestItem.getTotalQuantity(), selection.getUnit().getBaseQuantityPerUnit(), "套餐权益基础数量最多保留三位小数");
|
||||||
|
if (!gifted) {
|
||||||
requestBaseQuantityMap.merge(requestItem.getSkuId(), requestBaseQuantity, BigDecimal::add);
|
requestBaseQuantityMap.merge(requestItem.getSkuId(), requestBaseQuantity, BigDecimal::add);
|
||||||
|
}
|
||||||
if (requestItem.getTotalQuantity().signum() == 0) {
|
if (requestItem.getTotalQuantity().signum() == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!Boolean.TRUE.equals(selection.getSku().getAllowDecimalQuantity())) {
|
if (!Boolean.TRUE.equals(selection.getSku().getAllowDecimalQuantity())) {
|
||||||
TimiException.requiredTrue(requestItem.getTotalQuantity().stripTrailingZeros().scale() <= 0, "该 SKU 不允许小数数量");
|
TimiException.requiredTrue(requestItem.getTotalQuantity().stripTrailingZeros().scale() <= 0, "该 SKU 不允许小数数量");
|
||||||
}
|
}
|
||||||
GaoPackageConfigItem template = resolveItemTemplate(skuConfigItemList, selection.getUnit().getId());
|
|
||||||
GaoCustomerPackagePurchaseItem item = new GaoCustomerPackagePurchaseItem();
|
GaoCustomerPackagePurchaseItem item = new GaoCustomerPackagePurchaseItem();
|
||||||
item.setSkuId(selection.getSku().getId());
|
item.setSkuId(selection.getSku().getId());
|
||||||
item.setSkuUnitId(selection.getUnit().getId());
|
item.setSkuUnitId(selection.getUnit().getId());
|
||||||
|
item.setGifted(gifted);
|
||||||
item.setProductNameSnapshot(selection.getProduct().getName());
|
item.setProductNameSnapshot(selection.getProduct().getName());
|
||||||
item.setProductIdSnapshot(selection.getProduct().getId());
|
item.setProductIdSnapshot(selection.getProduct().getId());
|
||||||
item.setSkuCodeSnapshot(selection.getSku().getCode());
|
item.setSkuCodeSnapshot(selection.getSku().getCode());
|
||||||
@@ -337,8 +380,14 @@ public class GaoCustomerPackageServiceImplement extends AbstractEntityService<Ga
|
|||||||
item.setUnitSnapshot(selection.getUnit().getName());
|
item.setUnitSnapshot(selection.getUnit().getName());
|
||||||
item.setBaseQuantityPerUnitSnapshot(selection.getUnit().getBaseQuantityPerUnit());
|
item.setBaseQuantityPerUnitSnapshot(selection.getUnit().getBaseQuantityPerUnit());
|
||||||
item.setTotalQuantity(requestItem.getTotalQuantity());
|
item.setTotalQuantity(requestItem.getTotalQuantity());
|
||||||
|
if (gifted) {
|
||||||
|
item.setSort(requestItem.getSort());
|
||||||
|
item.setRemark(requestItem.getRemark());
|
||||||
|
} else {
|
||||||
|
GaoPackageConfigItem template = resolveItemTemplate(skuConfigItemList, selection.getUnit().getId());
|
||||||
item.setSort(template.getSort());
|
item.setSort(template.getSort());
|
||||||
item.setRemark(template.getRemark());
|
item.setRemark(template.getRemark());
|
||||||
|
}
|
||||||
result.add(item);
|
result.add(item);
|
||||||
}
|
}
|
||||||
TimiException.requiredTrue(!result.isEmpty(), "购买套餐至少需要一个产品");
|
TimiException.requiredTrue(!result.isEmpty(), "购买套餐至少需要一个产品");
|
||||||
@@ -378,9 +427,10 @@ public class GaoCustomerPackageServiceImplement extends AbstractEntityService<Ga
|
|||||||
List<GaoCustomerPackagePurchaseItem> requestItemList = TimiJava.defaultIfNull(request.getItemList(), List.of());
|
List<GaoCustomerPackagePurchaseItem> requestItemList = TimiJava.defaultIfNull(request.getItemList(), List.of());
|
||||||
verifyPurchaseItems(requestItemList);
|
verifyPurchaseItems(requestItemList);
|
||||||
TimiException.requiredTrue(existingItemList.size() == requestItemList.size(), "requestNo 对应购买请求内容不一致");
|
TimiException.requiredTrue(existingItemList.size() == requestItemList.size(), "requestNo 对应购买请求内容不一致");
|
||||||
Map<String, GaoSalesOrderItem> existingItemMap = existingItemList.stream().collect(Collectors.toMap(item -> item.getSkuId() + "|" + item.getSkuUnitId(), Function.identity()));
|
Map<String, GaoSalesOrderItem> existingItemMap = existingItemList.stream().collect(Collectors.toMap(item -> item.getSkuId() + "|" + item.getSkuUnitId() + "|"
|
||||||
|
+ Boolean.TRUE.equals(item.getGifted()), Function.identity()));
|
||||||
for (GaoCustomerPackagePurchaseItem item : requestItemList) {
|
for (GaoCustomerPackagePurchaseItem item : requestItemList) {
|
||||||
GaoSalesOrderItem existingItem = existingItemMap.get(item.getSkuId() + "|" + item.getSkuUnitId());
|
GaoSalesOrderItem existingItem = existingItemMap.get(item.getSkuId() + "|" + item.getSkuUnitId() + "|" + Boolean.TRUE.equals(item.getGifted()));
|
||||||
TimiException.required(existingItem, "requestNo 对应购买请求内容不一致");
|
TimiException.required(existingItem, "requestNo 对应购买请求内容不一致");
|
||||||
TimiException.requiredTrue(existingItem.getItemType() == GaoSalesOrderItem.ItemType.PACKAGE_ENTITLEMENT
|
TimiException.requiredTrue(existingItem.getItemType() == GaoSalesOrderItem.ItemType.PACKAGE_ENTITLEMENT
|
||||||
&& existingItem.getQuantity().compareTo(item.getTotalQuantity()) == 0
|
&& existingItem.getQuantity().compareTo(item.getTotalQuantity()) == 0
|
||||||
|
|||||||
+13
@@ -14,7 +14,9 @@ import com.imyeyu.api.modules.gao.service.GaoCustomerService;
|
|||||||
import com.imyeyu.api.modules.gao.service.GaoEventRecordService;
|
import com.imyeyu.api.modules.gao.service.GaoEventRecordService;
|
||||||
import com.imyeyu.api.modules.gao.service.GaoPointAccountService;
|
import com.imyeyu.api.modules.gao.service.GaoPointAccountService;
|
||||||
import com.imyeyu.api.modules.gao.util.CustomerXSSFBuilder;
|
import com.imyeyu.api.modules.gao.util.CustomerXSSFBuilder;
|
||||||
|
import com.imyeyu.api.modules.gao.vo.GaoCustomerAgeStatView;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoCustomerDailyStateView;
|
import com.imyeyu.api.modules.gao.vo.GaoCustomerDailyStateView;
|
||||||
|
import com.imyeyu.api.modules.gao.vo.GaoCustomerDailyStateCustomerView;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoCustomerGenderStatView;
|
import com.imyeyu.api.modules.gao.vo.GaoCustomerGenderStatView;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoCustomerPage;
|
import com.imyeyu.api.modules.gao.vo.GaoCustomerPage;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoCustomerTrendStateReq;
|
import com.imyeyu.api.modules.gao.vo.GaoCustomerTrendStateReq;
|
||||||
@@ -410,6 +412,10 @@ public class GaoCustomerServiceImplement extends AbstractEntityService<GaoCustom
|
|||||||
for (GaoCustomerDailyStateView view : mapper.stateDailyNewCustomer(req.getStoreId(), beginCreatedAt, endCreatedAt)) {
|
for (GaoCustomerDailyStateView view : mapper.stateDailyNewCustomer(req.getStoreId(), beginCreatedAt, endCreatedAt)) {
|
||||||
newCustomerCountMap.put(view.getDateValue(), TimiJava.defaultIfNull(view.getNewCustomerCount(), 0L));
|
newCustomerCountMap.put(view.getDateValue(), TimiJava.defaultIfNull(view.getNewCustomerCount(), 0L));
|
||||||
}
|
}
|
||||||
|
Map<Integer, List<GaoCustomerDailyStateCustomerView>> customerListMap = new HashMap<>();
|
||||||
|
for (GaoCustomerDailyStateCustomerView customer : mapper.selectDailyNewCustomer(req.getStoreId(), beginCreatedAt, endCreatedAt)) {
|
||||||
|
customerListMap.computeIfAbsent(customer.getDateValue(), key -> new ArrayList<>()).add(customer);
|
||||||
|
}
|
||||||
long totalCustomerCount = TimiJava.defaultIfNull(mapper.countCreatedBefore(req.getStoreId(), beginCreatedAt), 0L);
|
long totalCustomerCount = TimiJava.defaultIfNull(mapper.countCreatedBefore(req.getStoreId(), beginCreatedAt), 0L);
|
||||||
List<GaoCustomerDailyStateView> list = new ArrayList<>();
|
List<GaoCustomerDailyStateView> list = new ArrayList<>();
|
||||||
for (LocalDate date = beginDate; !date.isAfter(endDate); date = date.plusDays(1)) {
|
for (LocalDate date = beginDate; !date.isAfter(endDate); date = date.plusDays(1)) {
|
||||||
@@ -420,6 +426,7 @@ public class GaoCustomerServiceImplement extends AbstractEntityService<GaoCustom
|
|||||||
view.setDateValue(dateValue);
|
view.setDateValue(dateValue);
|
||||||
view.setNewCustomerCount(newCustomerCount);
|
view.setNewCustomerCount(newCustomerCount);
|
||||||
view.setTotalCustomerCount(totalCustomerCount);
|
view.setTotalCustomerCount(totalCustomerCount);
|
||||||
|
view.setCustomerList(customerListMap.getOrDefault(dateValue, List.of()));
|
||||||
list.add(view);
|
list.add(view);
|
||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
@@ -431,6 +438,12 @@ public class GaoCustomerServiceImplement extends AbstractEntityService<GaoCustom
|
|||||||
return mapper.stateGender(storeId);
|
return mapper.stateGender(storeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<GaoCustomerAgeStatView> stateAge(String storeId) {
|
||||||
|
TimiException.required(storeId, "not found storeId");
|
||||||
|
return mapper.stateAge(storeId);
|
||||||
|
}
|
||||||
|
|
||||||
private void changeInvitedCount(String customerId, long delta) {
|
private void changeInvitedCount(String customerId, long delta) {
|
||||||
if (TimiJava.isEmpty(customerId) || delta == 0) {
|
if (TimiJava.isEmpty(customerId) || delta == 0) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
+3
-6
@@ -103,20 +103,17 @@ public class GaoOrderReminderServiceImplement implements GaoOrderReminderService
|
|||||||
log.warn("GAO 订单提醒跳过不存在的店长用户: storeId[{}], userId[{}]", storeId, manager.getUserId());
|
log.warn("GAO 订单提醒跳过不存在的店长用户: storeId[{}], userId[{}]", storeId, manager.getUserId());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
String remindedId = "%s:%s:%s:%s".formatted(LocalDate.now(ZoneId.of(ZONE_ID)), storeId, manager.getUserId(), reminderType);
|
String remindedKey = "%s:%s:%s:%s".formatted(LocalDate.now(ZoneId.of(ZONE_ID)), storeId, manager.getUserId(), reminderType);
|
||||||
if (notifyService.existsByBizReminded(NOTIFY_BIZ_TYPE, reminderType, remindedId)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
long sendAt = Time.now();
|
long sendAt = Time.now();
|
||||||
Notify notify = new Notify();
|
Notify notify = new Notify();
|
||||||
notify.setBizType(NOTIFY_BIZ_TYPE);
|
notify.setBizType(NOTIFY_BIZ_TYPE);
|
||||||
notify.setBizRemindedType(reminderType);
|
notify.setBizRemindedType(reminderType);
|
||||||
notify.setBizRemindedId(remindedId);
|
notify.setBizRemindedKey(remindedKey);
|
||||||
notify.setDetailList(List.of(
|
notify.setDetailList(List.of(
|
||||||
createInternalDetail(manager.getUserId(), content, sendAt),
|
createInternalDetail(manager.getUserId(), content, sendAt),
|
||||||
createSmsDetail(user.getPhoneNo(), customerNames, action, content, sendAt)
|
createSmsDetail(user.getPhoneNo(), customerNames, action, content, sendAt)
|
||||||
));
|
));
|
||||||
notifyService.create(notify);
|
notifyService.createIfAbsent(notify);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("GAO 订单提醒发送失败: storeId[{}], userId[{}], reminderType[{}]", storeId, manager.getUserId(), reminderType, e);
|
log.error("GAO 订单提醒发送失败: storeId[{}], userId[{}], reminderType[{}]", storeId, manager.getUserId(), reminderType, e);
|
||||||
}
|
}
|
||||||
|
|||||||
+12
@@ -17,6 +17,7 @@ import com.imyeyu.api.modules.gao.vo.GaoProductPage;
|
|||||||
import com.imyeyu.api.modules.system.audit.AuditOperation;
|
import com.imyeyu.api.modules.system.audit.AuditOperation;
|
||||||
import com.imyeyu.api.modules.system.audit.OperationAudit;
|
import com.imyeyu.api.modules.system.audit.OperationAudit;
|
||||||
import com.imyeyu.api.modules.user.service.UserLoginService;
|
import com.imyeyu.api.modules.user.service.UserLoginService;
|
||||||
|
import com.imyeyu.api.util.PinyinUtil;
|
||||||
import com.imyeyu.java.TimiJava;
|
import com.imyeyu.java.TimiJava;
|
||||||
import com.imyeyu.java.bean.timi.TimiCode;
|
import com.imyeyu.java.bean.timi.TimiCode;
|
||||||
import com.imyeyu.java.bean.timi.TimiException;
|
import com.imyeyu.java.bean.timi.TimiException;
|
||||||
@@ -166,6 +167,7 @@ public class GaoProductServiceImplement extends AbstractEntityService<GaoProduct
|
|||||||
TimiException.required(product.getStoreId(), "not found product.storeId");
|
TimiException.required(product.getStoreId(), "not found product.storeId");
|
||||||
product.setCode(requiredText(product.getCode(), "产品编码不能为空"));
|
product.setCode(requiredText(product.getCode(), "产品编码不能为空"));
|
||||||
product.setName(requiredText(product.getName(), "产品名称不能为空"));
|
product.setName(requiredText(product.getName(), "产品名称不能为空"));
|
||||||
|
fillPinyin(product);
|
||||||
product.setProductType(TimiJava.defaultIfNull(product.getProductType(), GaoProduct.ProductType.GOODS));
|
product.setProductType(TimiJava.defaultIfNull(product.getProductType(), GaoProduct.ProductType.GOODS));
|
||||||
product.setStockEnabled(TimiJava.defaultIfNull(product.getStockEnabled(), product.getProductType() != GaoProduct.ProductType.SERVICE));
|
product.setStockEnabled(TimiJava.defaultIfNull(product.getStockEnabled(), product.getProductType() != GaoProduct.ProductType.SERVICE));
|
||||||
TimiException.requiredTrue(product.getProductType() != GaoProduct.ProductType.SERVICE || !product.getStockEnabled(), "SERVICE 产品不能启用库存");
|
TimiException.requiredTrue(product.getProductType() != GaoProduct.ProductType.SERVICE || !product.getStockEnabled(), "SERVICE 产品不能启用库存");
|
||||||
@@ -261,4 +263,14 @@ public class GaoProductServiceImplement extends AbstractEntityService<GaoProduct
|
|||||||
TimiException.requiredTrue(!result.isEmpty(), message);
|
TimiException.requiredTrue(!result.isEmpty(), message);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 填充产品名称拼音搜索字段
|
||||||
|
///
|
||||||
|
/// @param product 产品
|
||||||
|
private void fillPinyin(GaoProduct product) {
|
||||||
|
String name = product.getName();
|
||||||
|
product.setNamePinyinFull(PinyinUtil.full(name));
|
||||||
|
product.setNamePinyinInitial(PinyinUtil.initial(name));
|
||||||
|
product.setNamePinyinMixed(PinyinUtil.mixed(name));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-3
@@ -453,9 +453,11 @@ public class GaoSalesOrderServiceImplement extends AbstractEntityService<GaoSale
|
|||||||
for (GaoSalesOrderItem item : itemList) {
|
for (GaoSalesOrderItem item : itemList) {
|
||||||
TimiException.required(item, "销售订单明细不能为空");
|
TimiException.required(item, "销售订单明细不能为空");
|
||||||
TimiException.requiredTrue(item.getItemType() == expectedItemType, "订单项类型与订单类型不匹配");
|
TimiException.requiredTrue(item.getItemType() == expectedItemType, "订单项类型与订单类型不匹配");
|
||||||
|
item.setGifted(Boolean.TRUE.equals(item.getGifted()));
|
||||||
TimiException.required(item.getSkuId(), "订单项 SKU 不能为空");
|
TimiException.required(item.getSkuId(), "订单项 SKU 不能为空");
|
||||||
TimiException.required(item.getSkuUnitId(), "订单项 SKU 单位不能为空");
|
TimiException.required(item.getSkuUnitId(), "订单项 SKU 单位不能为空");
|
||||||
TimiException.requiredTrue(skuUnitKeySet.add(item.getSkuId() + "|" + item.getSkuUnitId()),
|
String skuUnitKey = item.getSkuId() + "|" + item.getSkuUnitId() + "|" + item.getGifted();
|
||||||
|
TimiException.requiredTrue(skuUnitKeySet.add(skuUnitKey),
|
||||||
"同一订单不能重复 SKU 和单位");
|
"同一订单不能重复 SKU 和单位");
|
||||||
TimiException.required(item.getQuantity(), "订单项数量不能为空");
|
TimiException.required(item.getQuantity(), "订单项数量不能为空");
|
||||||
TimiException.requiredTrue(0 < item.getQuantity().signum(), "订单项数量必须大于 0");
|
TimiException.requiredTrue(0 < item.getQuantity().signum(), "订单项数量必须大于 0");
|
||||||
@@ -511,11 +513,14 @@ public class GaoSalesOrderServiceImplement extends AbstractEntityService<GaoSale
|
|||||||
List<GaoSalesOrderItem> existingItemList = itemMapper.selectBySalesOrderId(existing.getId());
|
List<GaoSalesOrderItem> existingItemList = itemMapper.selectBySalesOrderId(existing.getId());
|
||||||
TimiException.requiredTrue(existingItemList.size() == requestItemList.size(), "requestNo 对应订单内容不一致");
|
TimiException.requiredTrue(existingItemList.size() == requestItemList.size(), "requestNo 对应订单内容不一致");
|
||||||
Map<String, GaoSalesOrderItem> existingItemMap = existingItemList.stream()
|
Map<String, GaoSalesOrderItem> existingItemMap = existingItemList.stream()
|
||||||
.collect(java.util.stream.Collectors.toMap(item -> item.getSkuId() + "|" + item.getSkuUnitId(), java.util.function.Function.identity()));
|
.collect(java.util.stream.Collectors.toMap(item -> item.getSkuId() + "|" + item.getSkuUnitId() + "|" + Boolean.TRUE.equals(item.getGifted()),
|
||||||
|
java.util.function.Function.identity()));
|
||||||
for (GaoSalesOrderItem requestItem : requestItemList) {
|
for (GaoSalesOrderItem requestItem : requestItemList) {
|
||||||
GaoSalesOrderItem existingItem = existingItemMap.get(requestItem.getSkuId() + "|" + requestItem.getSkuUnitId());
|
GaoSalesOrderItem existingItem = existingItemMap.get(requestItem.getSkuId() + "|" + requestItem.getSkuUnitId() + "|"
|
||||||
|
+ Boolean.TRUE.equals(requestItem.getGifted()));
|
||||||
TimiException.required(existingItem, "requestNo 对应订单内容不一致");
|
TimiException.required(existingItem, "requestNo 对应订单内容不一致");
|
||||||
TimiException.requiredTrue(existingItem.getItemType() == GaoSalesOrderItem.ItemType.PACKAGE_ENTITLEMENT
|
TimiException.requiredTrue(existingItem.getItemType() == GaoSalesOrderItem.ItemType.PACKAGE_ENTITLEMENT
|
||||||
|
&& Boolean.TRUE.equals(existingItem.getGifted()) == Boolean.TRUE.equals(requestItem.getGifted())
|
||||||
&& existingItem.getQuantity().compareTo(requestItem.getQuantity()) == 0
|
&& existingItem.getQuantity().compareTo(requestItem.getQuantity()) == 0
|
||||||
&& existingItem.getSort().equals(requestItem.getSort())
|
&& existingItem.getSort().equals(requestItem.getSort())
|
||||||
&& sameText(existingItem.getRemark(), requestItem.getRemark()), "requestNo 对应订单内容不一致");
|
&& sameText(existingItem.getRemark(), requestItem.getRemark()), "requestNo 对应订单内容不一致");
|
||||||
|
|||||||
+7
@@ -3,6 +3,7 @@ package com.imyeyu.api.modules.gao.service.implement;
|
|||||||
import com.imyeyu.api.modules.gao.service.GaoCustomerService;
|
import com.imyeyu.api.modules.gao.service.GaoCustomerService;
|
||||||
import com.imyeyu.api.modules.gao.service.GaoEventRecordService;
|
import com.imyeyu.api.modules.gao.service.GaoEventRecordService;
|
||||||
import com.imyeyu.api.modules.gao.service.GaoStoreChartService;
|
import com.imyeyu.api.modules.gao.service.GaoStoreChartService;
|
||||||
|
import com.imyeyu.api.modules.gao.vo.GaoCustomerAgeStatView;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoCustomerDailyStateView;
|
import com.imyeyu.api.modules.gao.vo.GaoCustomerDailyStateView;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoCustomerGenderStatView;
|
import com.imyeyu.api.modules.gao.vo.GaoCustomerGenderStatView;
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoCustomerTrendStateReq;
|
import com.imyeyu.api.modules.gao.vo.GaoCustomerTrendStateReq;
|
||||||
@@ -43,6 +44,12 @@ public class GaoStoreChartServiceImplement implements GaoStoreChartService {
|
|||||||
return customerService.stateGender(storeId);
|
return customerService.stateGender(storeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<GaoCustomerAgeStatView> customerAge(String storeId) {
|
||||||
|
TimiException.required(storeId, "not found storeId");
|
||||||
|
return customerService.stateAge(storeId);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<GaoEventRecordDailyStatView> eventRecordDailyStat(GaoStoreChartReq req) {
|
public List<GaoEventRecordDailyStatView> eventRecordDailyStat(GaoStoreChartReq req) {
|
||||||
checkRangeReq(req);
|
checkRangeReq(req);
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.imyeyu.api.modules.gao.vo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// 客户年龄统计视图
|
||||||
|
///
|
||||||
|
/// @author Codex
|
||||||
|
/// @since 2026-09-11
|
||||||
|
@Data
|
||||||
|
public class GaoCustomerAgeStatView {
|
||||||
|
|
||||||
|
/// 客户年龄
|
||||||
|
private Long age;
|
||||||
|
|
||||||
|
/// 该年龄的客户数量
|
||||||
|
private Long count;
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package com.imyeyu.api.modules.gao.vo;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// 客户每日统计中的客户摘要
|
||||||
|
///
|
||||||
|
/// @author Codex
|
||||||
|
/// @since 2026-09-11
|
||||||
|
@Data
|
||||||
|
public class GaoCustomerDailyStateCustomerView {
|
||||||
|
|
||||||
|
/// 用于服务层按日期分组,不返回给前端
|
||||||
|
@JsonIgnore
|
||||||
|
private Integer dateValue;
|
||||||
|
|
||||||
|
/// 客户姓名
|
||||||
|
private String name;
|
||||||
|
}
|
||||||
@@ -2,6 +2,8 @@ package com.imyeyu.api.modules.gao.vo;
|
|||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// 客户每日统计视图
|
/// 客户每日统计视图
|
||||||
///
|
///
|
||||||
@@ -18,4 +20,7 @@ public class GaoCustomerDailyStateView {
|
|||||||
|
|
||||||
/// 截止当日客户总数
|
/// 截止当日客户总数
|
||||||
private Long totalCustomerCount;
|
private Long totalCustomerCount;
|
||||||
|
|
||||||
|
/// 当日新增客户列表
|
||||||
|
private List<GaoCustomerDailyStateCustomerView> customerList;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package com.imyeyu.api.modules.gao.vo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/// 客户病症原始文本
|
||||||
|
///
|
||||||
|
/// 只用于后端分词,不对外返回。
|
||||||
|
///
|
||||||
|
/// @author Codex
|
||||||
|
/// @since 2026-09-11
|
||||||
|
@Data
|
||||||
|
public class GaoCustomerDiseaseTextView {
|
||||||
|
|
||||||
|
/// 备注
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
/// 病症
|
||||||
|
private String disease;
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package com.imyeyu.api.modules.gao.vo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/// 客户病症词频查询请求
|
||||||
|
///
|
||||||
|
/// @author Codex
|
||||||
|
/// @since 2026-09-11
|
||||||
|
@Data
|
||||||
|
public class GaoCustomerDiseaseWordReq {
|
||||||
|
|
||||||
|
/// 门店 ID
|
||||||
|
private String storeId;
|
||||||
|
|
||||||
|
/// 返回词语数量
|
||||||
|
private Integer topN;
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package com.imyeyu.api.modules.gao.vo;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/// 客户病症词频
|
||||||
|
///
|
||||||
|
/// @author Codex
|
||||||
|
/// @since 2026-09-11
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class GaoCustomerDiseaseWordView {
|
||||||
|
|
||||||
|
/// 词语
|
||||||
|
private String word;
|
||||||
|
|
||||||
|
/// 词语出现次数
|
||||||
|
private Long value;
|
||||||
|
}
|
||||||
@@ -17,6 +17,9 @@ public class GaoCustomerPackagePurchaseItem {
|
|||||||
/// SKU 单位 ID
|
/// SKU 单位 ID
|
||||||
private String skuUnitId;
|
private String skuUnitId;
|
||||||
|
|
||||||
|
/// true 表示请求将该明细作为赠送权益创建
|
||||||
|
private Boolean gifted;
|
||||||
|
|
||||||
/// 产品名称快照,由后端生成
|
/// 产品名称快照,由后端生成
|
||||||
private String productNameSnapshot;
|
private String productNameSnapshot;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.imyeyu.api.modules.gao.vo;
|
package com.imyeyu.api.modules.gao.vo;
|
||||||
|
|
||||||
import com.imyeyu.java.bean.BasePage;
|
import com.imyeyu.api.modules.gao.entity.GaoCustomer;
|
||||||
|
import com.imyeyu.spring.bean.Page;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
@@ -12,7 +13,7 @@ import java.util.List;
|
|||||||
/// @since 2026-08-13
|
/// @since 2026-08-13
|
||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
public class GaoCustomerPage extends BasePage {
|
public class GaoCustomerPage extends Page<GaoCustomer> {
|
||||||
|
|
||||||
/// 门店 ID
|
/// 门店 ID
|
||||||
private String storeId;
|
private String storeId;
|
||||||
@@ -22,4 +23,10 @@ public class GaoCustomerPage extends BasePage {
|
|||||||
|
|
||||||
/// 标签 ID 列表,客户必须同时拥有列表内全部标签
|
/// 标签 ID 列表,客户必须同时拥有列表内全部标签
|
||||||
private List<String> tagIdList;
|
private List<String> tagIdList;
|
||||||
|
|
||||||
|
/// 录入时间起始,包含,Unix 毫秒时间戳
|
||||||
|
private Long beginCreatedAt;
|
||||||
|
|
||||||
|
/// 录入时间结束,包含,Unix 毫秒时间戳
|
||||||
|
private Long endCreatedAt;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,6 @@ public class GaoProductPage extends BasePage {
|
|||||||
/// 产品类型
|
/// 产品类型
|
||||||
private GaoProduct.ProductType productType;
|
private GaoProduct.ProductType productType;
|
||||||
|
|
||||||
/// 名称或编码关键词
|
/// 名称、拼音或编码关键词
|
||||||
private String keyword;
|
private String keyword;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,6 @@ public class GaoProductStockPage extends BasePage {
|
|||||||
/// 产品 ID
|
/// 产品 ID
|
||||||
private String productId;
|
private String productId;
|
||||||
|
|
||||||
/// 产品或 SKU 名称、编码、规格摘要关键词
|
/// 产品或 SKU 名称、拼音、编码、规格摘要关键词
|
||||||
private String keyword;
|
private String keyword;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ public class GaoProductStockRecordPage extends BasePage {
|
|||||||
/// 产品 ID
|
/// 产品 ID
|
||||||
private String productId;
|
private String productId;
|
||||||
|
|
||||||
/// 产品名称或编码关键词
|
/// 产品名称、拼音或编码关键词
|
||||||
private String keyword;
|
private String keyword;
|
||||||
|
|
||||||
/// 来源业务类型
|
/// 来源业务类型
|
||||||
|
|||||||
@@ -1,66 +1,51 @@
|
|||||||
package com.imyeyu.api.modules.system.audit;
|
package com.imyeyu.api.modules.system.audit;
|
||||||
|
|
||||||
import com.imyeyu.api.modules.system.entity.Logger;
|
import com.imyeyu.api.modules.system.entity.Logger;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
/// 操作审计编码
|
/// 操作审计编码
|
||||||
///
|
///
|
||||||
/// @author Codex
|
/// @author Codex
|
||||||
/// @since 2026-09-09
|
/// @since 2026-09-09
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
public enum AuditOperation {
|
public enum AuditOperation {
|
||||||
|
|
||||||
GAO_CUSTOMER_PACKAGE_PURCHASE(Logger.Module.GAO, "GAO_CUSTOMER_PACKAGE_PURCHASE"),
|
COMMON_NOTIFY_CREATE(Logger.Module.COMMON),
|
||||||
GAO_CUSTOMER_PACKAGE_CANCEL(Logger.Module.GAO, "GAO_CUSTOMER_PACKAGE_CANCEL"),
|
COMMON_NOTIFY_DELETE(Logger.Module.COMMON),
|
||||||
GAO_SALES_ORDER_PAYMENT_RECEIVE(Logger.Module.GAO, "GAO_SALES_ORDER_PAYMENT_RECEIVE"),
|
GAO_CUSTOMER_PACKAGE_PURCHASE(Logger.Module.GAO),
|
||||||
GAO_SALES_ORDER_PAYMENT_VERIFY(Logger.Module.GAO, "GAO_SALES_ORDER_PAYMENT_VERIFY"),
|
GAO_CUSTOMER_PACKAGE_CANCEL(Logger.Module.GAO),
|
||||||
GAO_SALES_ORDER_REFUND(Logger.Module.GAO, "GAO_SALES_ORDER_REFUND"),
|
GAO_SALES_ORDER_PAYMENT_RECEIVE(Logger.Module.GAO),
|
||||||
GAO_SALES_ORDER_CONFIRM_NO_REFUND(Logger.Module.GAO, "GAO_SALES_ORDER_CONFIRM_NO_REFUND"),
|
GAO_SALES_ORDER_PAYMENT_VERIFY(Logger.Module.GAO),
|
||||||
GAO_SALES_ORDER_FUND_REVOKE(Logger.Module.GAO, "GAO_SALES_ORDER_FUND_REVOKE"),
|
GAO_SALES_ORDER_REFUND(Logger.Module.GAO),
|
||||||
GAO_ORDER_FULFILLMENT_CREATE(Logger.Module.GAO, "GAO_ORDER_FULFILLMENT_CREATE"),
|
GAO_SALES_ORDER_CONFIRM_NO_REFUND(Logger.Module.GAO),
|
||||||
GAO_ORDER_FULFILLMENT_PREPARE_STOCK(Logger.Module.GAO, "GAO_ORDER_FULFILLMENT_PREPARE_STOCK"),
|
GAO_SALES_ORDER_FUND_REVOKE(Logger.Module.GAO),
|
||||||
GAO_ORDER_FULFILLMENT_VERIFY(Logger.Module.GAO, "GAO_ORDER_FULFILLMENT_VERIFY"),
|
GAO_ORDER_FULFILLMENT_CREATE(Logger.Module.GAO),
|
||||||
GAO_ORDER_FULFILLMENT_REJECT(Logger.Module.GAO, "GAO_ORDER_FULFILLMENT_REJECT"),
|
GAO_ORDER_FULFILLMENT_PREPARE_STOCK(Logger.Module.GAO),
|
||||||
GAO_ORDER_FULFILLMENT_CANCEL(Logger.Module.GAO, "GAO_ORDER_FULFILLMENT_CANCEL"),
|
GAO_ORDER_FULFILLMENT_VERIFY(Logger.Module.GAO),
|
||||||
GAO_ORDER_FULFILLMENT_REVOKE(Logger.Module.GAO, "GAO_ORDER_FULFILLMENT_REVOKE"),
|
GAO_ORDER_FULFILLMENT_REJECT(Logger.Module.GAO),
|
||||||
GAO_PACKAGE_CONFIG_CREATE(Logger.Module.GAO, "GAO_PACKAGE_CONFIG_CREATE"),
|
GAO_ORDER_FULFILLMENT_CANCEL(Logger.Module.GAO),
|
||||||
GAO_PACKAGE_CONFIG_UPDATE(Logger.Module.GAO, "GAO_PACKAGE_CONFIG_UPDATE"),
|
GAO_ORDER_FULFILLMENT_REVOKE(Logger.Module.GAO),
|
||||||
GAO_PACKAGE_CONFIG_DELETE(Logger.Module.GAO, "GAO_PACKAGE_CONFIG_DELETE"),
|
GAO_PACKAGE_CONFIG_CREATE(Logger.Module.GAO),
|
||||||
GAO_PRODUCT_CATEGORY_SORT(Logger.Module.GAO, "GAO_PRODUCT_CATEGORY_SORT"),
|
GAO_PACKAGE_CONFIG_UPDATE(Logger.Module.GAO),
|
||||||
GAO_PRODUCT_CATEGORY_CREATE(Logger.Module.GAO, "GAO_PRODUCT_CATEGORY_CREATE"),
|
GAO_PACKAGE_CONFIG_DELETE(Logger.Module.GAO),
|
||||||
GAO_PRODUCT_CATEGORY_UPDATE(Logger.Module.GAO, "GAO_PRODUCT_CATEGORY_UPDATE"),
|
GAO_PRODUCT_CATEGORY_SORT(Logger.Module.GAO),
|
||||||
GAO_PRODUCT_CATEGORY_DISABLE(Logger.Module.GAO, "GAO_PRODUCT_CATEGORY_DISABLE"),
|
GAO_PRODUCT_CATEGORY_CREATE(Logger.Module.GAO),
|
||||||
GAO_PRODUCT_CREATE(Logger.Module.GAO, "GAO_PRODUCT_CREATE"),
|
GAO_PRODUCT_CATEGORY_UPDATE(Logger.Module.GAO),
|
||||||
GAO_PRODUCT_UPDATE(Logger.Module.GAO, "GAO_PRODUCT_UPDATE"),
|
GAO_PRODUCT_CATEGORY_DISABLE(Logger.Module.GAO),
|
||||||
GAO_PRODUCT_DISABLE(Logger.Module.GAO, "GAO_PRODUCT_DISABLE"),
|
GAO_PRODUCT_CREATE(Logger.Module.GAO),
|
||||||
GAO_PRODUCT_STOCK_INITIAL_IN(Logger.Module.GAO, "GAO_PRODUCT_STOCK_INITIAL_IN"),
|
GAO_PRODUCT_UPDATE(Logger.Module.GAO),
|
||||||
GAO_PRODUCT_STOCK_MANUAL_IN(Logger.Module.GAO, "GAO_PRODUCT_STOCK_MANUAL_IN"),
|
GAO_PRODUCT_DISABLE(Logger.Module.GAO),
|
||||||
GAO_PRODUCT_STOCK_MANUAL_OUT(Logger.Module.GAO, "GAO_PRODUCT_STOCK_MANUAL_OUT"),
|
GAO_PRODUCT_STOCK_INITIAL_IN(Logger.Module.GAO),
|
||||||
GAO_PRODUCT_STOCK_MANUAL_REVOKE(Logger.Module.GAO, "GAO_PRODUCT_STOCK_MANUAL_REVOKE"),
|
GAO_PRODUCT_STOCK_MANUAL_IN(Logger.Module.GAO),
|
||||||
GAO_PRODUCT_STOCK_STOCKTAKE_GAIN(Logger.Module.GAO, "GAO_PRODUCT_STOCK_STOCKTAKE_GAIN"),
|
GAO_PRODUCT_STOCK_MANUAL_OUT(Logger.Module.GAO),
|
||||||
GAO_PRODUCT_STOCK_STOCKTAKE_LOSS(Logger.Module.GAO, "GAO_PRODUCT_STOCK_STOCKTAKE_LOSS"),
|
GAO_PRODUCT_STOCK_MANUAL_REVOKE(Logger.Module.GAO),
|
||||||
GAO_SALES_ORDER_DIRECT_PRODUCT_CREATE(Logger.Module.GAO, "GAO_SALES_ORDER_DIRECT_PRODUCT_CREATE"),
|
GAO_PRODUCT_STOCK_STOCKTAKE_GAIN(Logger.Module.GAO),
|
||||||
GAO_SALES_ORDER_UPDATE(Logger.Module.GAO, "GAO_SALES_ORDER_UPDATE"),
|
GAO_PRODUCT_STOCK_STOCKTAKE_LOSS(Logger.Module.GAO),
|
||||||
GAO_SALES_ORDER_CANCEL(Logger.Module.GAO, "GAO_SALES_ORDER_CANCEL");
|
GAO_SALES_ORDER_DIRECT_PRODUCT_CREATE(Logger.Module.GAO),
|
||||||
|
GAO_SALES_ORDER_UPDATE(Logger.Module.GAO),
|
||||||
|
GAO_SALES_ORDER_CANCEL(Logger.Module.GAO);
|
||||||
|
|
||||||
private final Logger.Module module;
|
final Logger.Module module;
|
||||||
|
|
||||||
private final String code;
|
|
||||||
|
|
||||||
AuditOperation(Logger.Module module, String code) {
|
|
||||||
this.module = module;
|
|
||||||
this.code = code;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 获取日志模块
|
|
||||||
///
|
|
||||||
/// @return 日志模块
|
|
||||||
public Logger.Module getModule() {
|
|
||||||
return module;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 获取操作编码
|
|
||||||
///
|
|
||||||
/// @return 操作编码
|
|
||||||
public String getCode() {
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.imyeyu.api.modules.system.audit;
|
package com.imyeyu.api.modules.system.audit;
|
||||||
|
|
||||||
import com.imyeyu.api.modules.system.entity.Logger;
|
import com.imyeyu.api.modules.system.entity.Logger;
|
||||||
|
import com.imyeyu.java.TimiJava;
|
||||||
import com.imyeyu.java.bean.timi.TimiException;
|
import com.imyeyu.java.bean.timi.TimiException;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -38,7 +39,7 @@ public class OperationAuditAspect {
|
|||||||
public Object around(ProceedingJoinPoint joinPoint, OperationAudit operationAudit) throws Throwable {
|
public Object around(ProceedingJoinPoint joinPoint, OperationAudit operationAudit) throws Throwable {
|
||||||
AuditOperation operation = operationAudit.value();
|
AuditOperation operation = operationAudit.value();
|
||||||
Object[] arguments = joinPoint.getArgs();
|
Object[] arguments = joinPoint.getArgs();
|
||||||
Logger logger = new Logger(operation.getModule(), operation.getCode());
|
Logger logger = new Logger(operation.getModule(), operation.name());
|
||||||
logger.setContent(payloadSerializer.serializeArguments(arguments));
|
logger.setContent(payloadSerializer.serializeArguments(arguments));
|
||||||
long startNanos = System.nanoTime();
|
long startNanos = System.nanoTime();
|
||||||
try {
|
try {
|
||||||
@@ -56,9 +57,9 @@ public class OperationAuditAspect {
|
|||||||
throw e;
|
throw e;
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
logger.setLevel(Logger.Level.ERROR);
|
logger.setLevel(Logger.Level.ERROR);
|
||||||
logger.setException(serializeThrowable(e));
|
logger.setException(TimiJava.serializeThrowable(e));
|
||||||
logger.setDuration(duration(startNanos));
|
logger.setDuration(duration(startNanos));
|
||||||
log.error("业务操作失败: {}", operation.getCode(), e);
|
log.error("业务操作失败: {}", operation.name(), e);
|
||||||
record(logger);
|
record(logger);
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
@@ -79,12 +80,4 @@ public class OperationAuditAspect {
|
|||||||
}
|
}
|
||||||
return (int) Math.max(0L, millis);
|
return (int) Math.max(0L, millis);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String serializeThrowable(Throwable throwable) {
|
|
||||||
java.io.StringWriter stringWriter = new java.io.StringWriter();
|
|
||||||
try (java.io.PrintWriter printWriter = new java.io.PrintWriter(stringWriter)) {
|
|
||||||
throwable.printStackTrace(printWriter);
|
|
||||||
}
|
|
||||||
return stringWriter.toString();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.system.controller;
|
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @author 夜雨
|
|
||||||
* @since 2026-04-23 16:31
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
@RequestMapping("/system/setting")
|
|
||||||
public class SettingController {
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
package db.migration.timiserver;
|
||||||
|
|
||||||
|
import com.imyeyu.api.util.PinyinUtil;
|
||||||
|
import org.flywaydb.core.api.migration.BaseJavaMigration;
|
||||||
|
import org.flywaydb.core.api.migration.Context;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
|
||||||
|
/// 回填 GAO 产品名称拼音搜索字段
|
||||||
|
///
|
||||||
|
/// @author Codex
|
||||||
|
/// @since 2026-09-10
|
||||||
|
public class V78__backfill_gao_product_pinyin_search extends BaseJavaMigration {
|
||||||
|
|
||||||
|
private static final int BATCH_SIZE = 500;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void migrate(Context context) throws Exception {
|
||||||
|
Connection connection = context.getConnection();
|
||||||
|
try (
|
||||||
|
PreparedStatement select = connection.prepareStatement("""
|
||||||
|
SELECT `id`, `name`
|
||||||
|
FROM `gao_product`
|
||||||
|
WHERE `name` IS NOT NULL
|
||||||
|
AND (`name_pinyin_full` IS NULL OR `name_pinyin_initial` IS NULL OR `name_pinyin_mixed` IS NULL)
|
||||||
|
""");
|
||||||
|
PreparedStatement update = connection.prepareStatement("""
|
||||||
|
UPDATE `gao_product`
|
||||||
|
SET `name_pinyin_full` = ?, `name_pinyin_initial` = ?, `name_pinyin_mixed` = ?
|
||||||
|
WHERE `id` = ?
|
||||||
|
""")) {
|
||||||
|
try (ResultSet resultSet = select.executeQuery()) {
|
||||||
|
int batchSize = 0;
|
||||||
|
while (resultSet.next()) {
|
||||||
|
String name = resultSet.getString("name");
|
||||||
|
update.setString(1, PinyinUtil.full(name));
|
||||||
|
update.setString(2, PinyinUtil.initial(name));
|
||||||
|
update.setString(3, PinyinUtil.mixed(name));
|
||||||
|
update.setString(4, resultSet.getString("id"));
|
||||||
|
update.addBatch();
|
||||||
|
batchSize++;
|
||||||
|
if (batchSize >= BATCH_SIZE) {
|
||||||
|
update.executeBatch();
|
||||||
|
batchSize = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (0 < batchSize) {
|
||||||
|
update.executeBatch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
ALTER TABLE `gao_sales_order_item`
|
||||||
|
ADD COLUMN `gifted` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'true 为赠送权益' AFTER `item_type`,
|
||||||
|
DROP KEY `uk_gao_sales_order_item_sku_unit`,
|
||||||
|
ADD UNIQUE KEY `uk_gao_sales_order_item_sku_unit_gifted` (`sales_order_id`, `sku_id`, `sku_unit_id`, `gifted`),
|
||||||
|
ADD KEY `idx_gao_sales_order_item_order_gifted` (`sales_order_id`, `gifted`, `sort`, `created_at`);
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
ALTER TABLE `notify`
|
||||||
|
CHANGE COLUMN `biz_reminded_id` `biz_reminded_key` VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT '业务提醒查重键',
|
||||||
|
ADD COLUMN `biz_reminded_active_key` TINYINT(1) GENERATED ALWAYS AS (IF(`deleted_at` IS NULL, 1, NULL)) STORED COMMENT '未删除查重键' INVISIBLE AFTER `deleted_at`,
|
||||||
|
DROP INDEX `idx_biz_reminded_created`,
|
||||||
|
ADD INDEX `idx_biz_reminded_key_created`(`biz_type` ASC, `biz_reminded_type` ASC, `biz_reminded_key` ASC, `created_at` ASC) USING BTREE;
|
||||||
|
|
||||||
|
UPDATE `notify` target
|
||||||
|
INNER JOIN (
|
||||||
|
SELECT
|
||||||
|
id,
|
||||||
|
ROW_NUMBER() OVER (
|
||||||
|
PARTITION BY biz_type, biz_reminded_type, biz_reminded_key
|
||||||
|
ORDER BY created_at DESC, id DESC
|
||||||
|
) AS rn
|
||||||
|
FROM `notify`
|
||||||
|
WHERE deleted_at IS NULL
|
||||||
|
AND biz_type IS NOT NULL
|
||||||
|
AND biz_reminded_type IS NOT NULL
|
||||||
|
AND biz_reminded_key IS NOT NULL
|
||||||
|
) duplicate ON duplicate.id = target.id
|
||||||
|
SET target.deleted_at = UNIX_TIMESTAMP() * 1000
|
||||||
|
WHERE duplicate.rn > 1;
|
||||||
|
|
||||||
|
ALTER TABLE `notify`
|
||||||
|
ADD UNIQUE INDEX `uk_biz_reminded_key_active`(`biz_type` ASC, `biz_reminded_type` ASC, `biz_reminded_key` ASC, `biz_reminded_active_key` ASC) USING BTREE;
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
ALTER TABLE `gao_product`
|
||||||
|
ADD COLUMN `name_pinyin_full` VARCHAR(768) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL COMMENT '产品名称全拼' AFTER `name`,
|
||||||
|
ADD COLUMN `name_pinyin_initial` VARCHAR(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL COMMENT '产品名称拼音首字母' AFTER `name_pinyin_full`,
|
||||||
|
ADD COLUMN `name_pinyin_mixed` VARCHAR(768) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL COMMENT '产品名称混合拼音' AFTER `name_pinyin_initial`,
|
||||||
|
ADD KEY `idx_gao_product_store_name_pinyin_full` (`store_id`, `deleted_at`, `name_pinyin_full`(128)),
|
||||||
|
ADD KEY `idx_gao_product_store_name_pinyin_initial` (`store_id`, `deleted_at`, `name_pinyin_initial`),
|
||||||
|
ADD KEY `idx_gao_product_store_name_pinyin_mixed` (`store_id`, `deleted_at`, `name_pinyin_mixed`(128));
|
||||||
@@ -1,6 +1,31 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
||||||
<mapper namespace="com.imyeyu.api.modules.common.mapper.NotifyMapper">
|
<mapper namespace="com.imyeyu.api.modules.common.mapper.NotifyMapper">
|
||||||
|
<insert id="insertIfAbsent">
|
||||||
|
INSERT INTO `notify` (
|
||||||
|
`id`,
|
||||||
|
`biz_type`,
|
||||||
|
`biz_reminded_type`,
|
||||||
|
`biz_reminded_key`,
|
||||||
|
`args`,
|
||||||
|
`created_by`,
|
||||||
|
`created_at`,
|
||||||
|
`updated_at`,
|
||||||
|
`deleted_at`
|
||||||
|
) VALUES (
|
||||||
|
#{id},
|
||||||
|
#{bizType},
|
||||||
|
#{bizRemindedType},
|
||||||
|
#{bizRemindedKey},
|
||||||
|
#{args},
|
||||||
|
#{createdBy},
|
||||||
|
#{createdAt},
|
||||||
|
#{updatedAt},
|
||||||
|
#{deletedAt}
|
||||||
|
)
|
||||||
|
ON DUPLICATE KEY UPDATE `id` = `id`
|
||||||
|
</insert>
|
||||||
|
|
||||||
<select id="selectManagementPage" resultType="com.imyeyu.api.modules.common.vo.NotifyManagementItem">
|
<select id="selectManagementPage" resultType="com.imyeyu.api.modules.common.vo.NotifyManagementItem">
|
||||||
SELECT
|
SELECT
|
||||||
n.`id`,
|
n.`id`,
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
||||||
|
<mapper namespace="com.imyeyu.api.modules.common.mapper.SettingMapper">
|
||||||
|
<select id="selectPublicByQuery" resultType="com.imyeyu.api.modules.common.entity.Setting">
|
||||||
|
SELECT *
|
||||||
|
FROM `setting`
|
||||||
|
WHERE `biz_type` = #{bizType}
|
||||||
|
AND `is_private` = 0
|
||||||
|
<if test="bizId != null and bizId != ''">
|
||||||
|
AND `biz_id` = #{bizId}
|
||||||
|
</if>
|
||||||
|
<if test="codeList != null and !codeList.isEmpty()">
|
||||||
|
AND `code` IN
|
||||||
|
<foreach collection="codeList" item="code" separator="," open="(" close=")">
|
||||||
|
#{code}
|
||||||
|
</foreach>
|
||||||
|
</if>
|
||||||
|
AND (`deleted_at` IS NULL OR FLOOR(UNIX_TIMESTAMP(NOW(3)) * 1000) < `deleted_at`)
|
||||||
|
</select>
|
||||||
|
</mapper>
|
||||||
@@ -18,7 +18,6 @@
|
|||||||
</if>
|
</if>
|
||||||
AND `deleted_at` IS NULL
|
AND `deleted_at` IS NULL
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<sql id="queryWhere">
|
<sql id="queryWhere">
|
||||||
`c`.`deleted_at` IS NULL
|
`c`.`deleted_at` IS NULL
|
||||||
<if test="storeId != null and storeId != ''">
|
<if test="storeId != null and storeId != ''">
|
||||||
@@ -50,6 +49,12 @@
|
|||||||
HAVING COUNT(DISTINCT `ta`.`tag_id`) = #{tagCount}
|
HAVING COUNT(DISTINCT `ta`.`tag_id`) = #{tagCount}
|
||||||
)
|
)
|
||||||
</if>
|
</if>
|
||||||
|
<if test="beginCreatedAt != null">
|
||||||
|
AND `c`.`created_at` >= #{beginCreatedAt}
|
||||||
|
</if>
|
||||||
|
<if test="endCreatedAt != null">
|
||||||
|
AND `c`.`created_at` <= #{endCreatedAt}
|
||||||
|
</if>
|
||||||
</sql>
|
</sql>
|
||||||
|
|
||||||
<select id="countByQuery" resultType="long">
|
<select id="countByQuery" resultType="long">
|
||||||
@@ -64,7 +69,18 @@
|
|||||||
FROM `gao_customer` `c`
|
FROM `gao_customer` `c`
|
||||||
WHERE
|
WHERE
|
||||||
<include refid="queryWhere"/>
|
<include refid="queryWhere"/>
|
||||||
|
<choose>
|
||||||
|
<when test="orderMap != null and !orderMap.isEmpty()">
|
||||||
|
ORDER BY
|
||||||
|
<foreach collection="orderMap" index="key" item="value" separator=",">
|
||||||
|
<bind name="underscoreKey" value="@com.imyeyu.utils.Text@camelCase2underscore(key)"/>
|
||||||
|
${underscoreKey} ${value}
|
||||||
|
</foreach>
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
ORDER BY `c`.`created_at` DESC, `c`.`id` DESC
|
ORDER BY `c`.`created_at` DESC, `c`.`id` DESC
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
LIMIT #{offset}, #{limit}
|
LIMIT #{offset}, #{limit}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
@@ -82,6 +98,19 @@
|
|||||||
ORDER BY `dateValue` ASC
|
ORDER BY `dateValue` ASC
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="selectDailyNewCustomer" resultType="com.imyeyu.api.modules.gao.vo.GaoCustomerDailyStateCustomerView">
|
||||||
|
SELECT
|
||||||
|
`name`,
|
||||||
|
CAST(DATE_FORMAT(FROM_UNIXTIME(`created_at` / 1000), '%Y%m%d') AS UNSIGNED) AS `dateValue`
|
||||||
|
FROM `gao_customer`
|
||||||
|
WHERE
|
||||||
|
`store_id` = #{storeId}
|
||||||
|
AND `created_at` >= #{beginCreatedAt}
|
||||||
|
AND `created_at` <= #{endCreatedAt}
|
||||||
|
AND `deleted_at` IS NULL
|
||||||
|
ORDER BY `dateValue` ASC, `created_at` ASC, `id` ASC
|
||||||
|
</select>
|
||||||
|
|
||||||
<select id="countCreatedBefore" resultType="java.lang.Long">
|
<select id="countCreatedBefore" resultType="java.lang.Long">
|
||||||
SELECT
|
SELECT
|
||||||
COUNT(1)
|
COUNT(1)
|
||||||
@@ -102,4 +131,31 @@
|
|||||||
AND `deleted_at` IS NULL
|
AND `deleted_at` IS NULL
|
||||||
GROUP BY IFNULL(CAST(`gender` AS CHAR), 'UNKNOWN')
|
GROUP BY IFNULL(CAST(`gender` AS CHAR), 'UNKNOWN')
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="stateAge" resultType="com.imyeyu.api.modules.gao.vo.GaoCustomerAgeStatView">
|
||||||
|
SELECT
|
||||||
|
COALESCE(`age`, TIMESTAMPDIFF(YEAR, `birthdate`, CURDATE())) AS `age`,
|
||||||
|
COUNT(1) AS `count`
|
||||||
|
FROM `gao_customer`
|
||||||
|
WHERE
|
||||||
|
`store_id` = #{storeId}
|
||||||
|
AND `deleted_at` IS NULL
|
||||||
|
AND (`age` IS NOT NULL OR `birthdate` IS NOT NULL)
|
||||||
|
GROUP BY COALESCE(`age`, TIMESTAMPDIFF(YEAR, `birthdate`, CURDATE()))
|
||||||
|
ORDER BY COALESCE(`age`, TIMESTAMPDIFF(YEAR, `birthdate`, CURDATE())) ASC
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectDiseaseTextByStoreId" resultType="com.imyeyu.api.modules.gao.vo.GaoCustomerDiseaseTextView">
|
||||||
|
SELECT
|
||||||
|
`remark`,
|
||||||
|
`disease`
|
||||||
|
FROM `gao_customer`
|
||||||
|
WHERE
|
||||||
|
`store_id` = #{storeId}
|
||||||
|
AND `deleted_at` IS NULL
|
||||||
|
AND (
|
||||||
|
(`remark` IS NOT NULL AND `remark` != '')
|
||||||
|
OR (`disease` IS NOT NULL AND `disease` != '')
|
||||||
|
)
|
||||||
|
</select>
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|||||||
@@ -348,10 +348,23 @@
|
|||||||
FROM `daily_stat` d
|
FROM `daily_stat` d
|
||||||
JOIN `open_calendar` o ON d.`registeredDateValue` = o.`dateValue`
|
JOIN `open_calendar` o ON d.`registeredDateValue` = o.`dateValue`
|
||||||
),
|
),
|
||||||
|
`customer_stat` AS (
|
||||||
|
SELECT
|
||||||
|
d.`customerId`,
|
||||||
|
MAX(CASE WHEN d.`registeredDateValue` = #{todayDateValue} THEN 1 ELSE 0 END) AS `hasToday`
|
||||||
|
FROM `daily_stat` d
|
||||||
|
GROUP BY d.`customerId`
|
||||||
|
),
|
||||||
`anchor_date` AS (
|
`anchor_date` AS (
|
||||||
SELECT
|
SELECT
|
||||||
MAX(`openIndex`) AS `anchorOpenIndex`
|
s.`customerId`,
|
||||||
FROM `open_calendar`
|
CASE
|
||||||
|
WHEN s.`hasToday` = 1 THEN MAX(CASE WHEN c.`dateValue` = #{todayDateValue} THEN c.`openIndex` END)
|
||||||
|
ELSE MAX(CASE WHEN c.`dateValue` < #{todayDateValue} THEN c.`openIndex` END)
|
||||||
|
END AS `anchorOpenIndex`
|
||||||
|
FROM `customer_stat` s
|
||||||
|
CROSS JOIN `open_calendar` c
|
||||||
|
GROUP BY s.`customerId`, s.`hasToday`
|
||||||
),
|
),
|
||||||
`continuous_stat` AS (
|
`continuous_stat` AS (
|
||||||
SELECT
|
SELECT
|
||||||
@@ -361,7 +374,7 @@
|
|||||||
ELSE COUNT(1)
|
ELSE COUNT(1)
|
||||||
END AS `recentContinuousEventDays`
|
END AS `recentContinuousEventDays`
|
||||||
FROM `continuous_ordered` o
|
FROM `continuous_ordered` o
|
||||||
JOIN `anchor_date` a
|
JOIN `anchor_date` a ON o.`customerId` = a.`customerId`
|
||||||
WHERE
|
WHERE
|
||||||
o.`openIndex` + o.`dayIndex` = a.`anchorOpenIndex` + 1
|
o.`openIndex` + o.`dayIndex` = a.`anchorOpenIndex` + 1
|
||||||
<if test="eventIdList == null or eventIdList.size() != 1">
|
<if test="eventIdList == null or eventIdList.size() != 1">
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
</choose>
|
</choose>
|
||||||
<if test="status != null">AND `status` = #{status}</if>
|
<if test="status != null">AND `status` = #{status}</if>
|
||||||
<if test="productType != null">AND `product_type` = #{productType}</if>
|
<if test="productType != null">AND `product_type` = #{productType}</if>
|
||||||
<if test="keyword != null and keyword.trim() != ''">AND (`code` LIKE CONCAT('%', #{keyword}, '%') OR `name` LIKE CONCAT('%', #{keyword}, '%'))</if>
|
<if test="keyword != null and keyword.trim() != ''">AND (`code` LIKE CONCAT('%', #{keyword}, '%') OR `name` LIKE CONCAT('%', #{keyword}, '%') OR `name_pinyin_full` LIKE CONCAT(#{keyword}, '%') OR `name_pinyin_initial` LIKE CONCAT(#{keyword}, '%') OR `name_pinyin_mixed` LIKE CONCAT(#{keyword}, '%'))</if>
|
||||||
</select>
|
</select>
|
||||||
<select id="selectByQuery" resultType="com.imyeyu.api.modules.gao.entity.GaoProduct">
|
<select id="selectByQuery" resultType="com.imyeyu.api.modules.gao.entity.GaoProduct">
|
||||||
SELECT * FROM `gao_product`
|
SELECT * FROM `gao_product`
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
</choose>
|
</choose>
|
||||||
<if test="status != null">AND `status` = #{status}</if>
|
<if test="status != null">AND `status` = #{status}</if>
|
||||||
<if test="productType != null">AND `product_type` = #{productType}</if>
|
<if test="productType != null">AND `product_type` = #{productType}</if>
|
||||||
<if test="keyword != null and keyword.trim() != ''">AND (`code` LIKE CONCAT('%', #{keyword}, '%') OR `name` LIKE CONCAT('%', #{keyword}, '%'))</if>
|
<if test="keyword != null and keyword.trim() != ''">AND (`code` LIKE CONCAT('%', #{keyword}, '%') OR `name` LIKE CONCAT('%', #{keyword}, '%') OR `name_pinyin_full` LIKE CONCAT(#{keyword}, '%') OR `name_pinyin_initial` LIKE CONCAT(#{keyword}, '%') OR `name_pinyin_mixed` LIKE CONCAT(#{keyword}, '%'))</if>
|
||||||
ORDER BY `sort`, `name`, `code`, `created_at` DESC
|
ORDER BY `sort`, `name`, `code`, `created_at` DESC
|
||||||
LIMIT #{offset}, #{limit}
|
LIMIT #{offset}, #{limit}
|
||||||
</select>
|
</select>
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
AND k.`stock_enabled` = 1 AND k.`status` = 'ACTIVE'
|
AND k.`stock_enabled` = 1 AND k.`status` = 'ACTIVE'
|
||||||
<if test="storeId != null and storeId != ''">AND p.`store_id` = #{storeId}</if>
|
<if test="storeId != null and storeId != ''">AND p.`store_id` = #{storeId}</if>
|
||||||
<if test="productId != null and productId != ''">AND k.`product_id` = #{productId}</if>
|
<if test="productId != null and productId != ''">AND k.`product_id` = #{productId}</if>
|
||||||
<if test="keyword != null and keyword.trim() != ''">AND (p.`code` LIKE CONCAT('%', #{keyword}, '%') OR p.`name` LIKE CONCAT('%', #{keyword}, '%') OR k.`code` LIKE CONCAT('%', #{keyword}, '%') OR k.`name` LIKE CONCAT('%', #{keyword}, '%') OR k.`spec_summary` LIKE CONCAT('%', #{keyword}, '%') OR k.`barcode` LIKE CONCAT('%', #{keyword}, '%'))</if>
|
<if test="keyword != null and keyword.trim() != ''">AND (p.`code` LIKE CONCAT('%', #{keyword}, '%') OR p.`name` LIKE CONCAT('%', #{keyword}, '%') OR p.`name_pinyin_full` LIKE CONCAT(#{keyword}, '%') OR p.`name_pinyin_initial` LIKE CONCAT(#{keyword}, '%') OR p.`name_pinyin_mixed` LIKE CONCAT(#{keyword}, '%') OR k.`code` LIKE CONCAT('%', #{keyword}, '%') OR k.`name` LIKE CONCAT('%', #{keyword}, '%') OR k.`spec_summary` LIKE CONCAT('%', #{keyword}, '%') OR k.`barcode` LIKE CONCAT('%', #{keyword}, '%'))</if>
|
||||||
</select>
|
</select>
|
||||||
<select id="selectByQuery" resultType="com.imyeyu.api.modules.gao.entity.GaoProductStock">
|
<select id="selectByQuery" resultType="com.imyeyu.api.modules.gao.entity.GaoProductStock">
|
||||||
SELECT s.`id`,
|
SELECT s.`id`,
|
||||||
@@ -45,7 +45,7 @@
|
|||||||
AND k.`stock_enabled` = 1 AND k.`status` = 'ACTIVE'
|
AND k.`stock_enabled` = 1 AND k.`status` = 'ACTIVE'
|
||||||
<if test="storeId != null and storeId != ''">AND p.`store_id` = #{storeId}</if>
|
<if test="storeId != null and storeId != ''">AND p.`store_id` = #{storeId}</if>
|
||||||
<if test="productId != null and productId != ''">AND k.`product_id` = #{productId}</if>
|
<if test="productId != null and productId != ''">AND k.`product_id` = #{productId}</if>
|
||||||
<if test="keyword != null and keyword.trim() != ''">AND (p.`code` LIKE CONCAT('%', #{keyword}, '%') OR p.`name` LIKE CONCAT('%', #{keyword}, '%') OR k.`code` LIKE CONCAT('%', #{keyword}, '%') OR k.`name` LIKE CONCAT('%', #{keyword}, '%') OR k.`spec_summary` LIKE CONCAT('%', #{keyword}, '%') OR k.`barcode` LIKE CONCAT('%', #{keyword}, '%'))</if>
|
<if test="keyword != null and keyword.trim() != ''">AND (p.`code` LIKE CONCAT('%', #{keyword}, '%') OR p.`name` LIKE CONCAT('%', #{keyword}, '%') OR p.`name_pinyin_full` LIKE CONCAT(#{keyword}, '%') OR p.`name_pinyin_initial` LIKE CONCAT(#{keyword}, '%') OR p.`name_pinyin_mixed` LIKE CONCAT(#{keyword}, '%') OR k.`code` LIKE CONCAT('%', #{keyword}, '%') OR k.`name` LIKE CONCAT('%', #{keyword}, '%') OR k.`spec_summary` LIKE CONCAT('%', #{keyword}, '%') OR k.`barcode` LIKE CONCAT('%', #{keyword}, '%'))</if>
|
||||||
ORDER BY p.`sort`, p.`name`, p.`code`, k.`sort`, k.`name`, k.`code`
|
ORDER BY p.`sort`, p.`name`, p.`code`, k.`sort`, k.`name`, k.`code`
|
||||||
LIMIT #{offset}, #{limit}
|
LIMIT #{offset}, #{limit}
|
||||||
</select>
|
</select>
|
||||||
@@ -57,7 +57,7 @@
|
|||||||
AND p.`stock_enabled` = 1
|
AND p.`stock_enabled` = 1
|
||||||
AND k.`stock_enabled` = 1 AND k.`status` = 'ACTIVE'
|
AND k.`stock_enabled` = 1 AND k.`status` = 'ACTIVE'
|
||||||
<if test="storeId != null and storeId != ''">AND p.`store_id` = #{storeId}</if>
|
<if test="storeId != null and storeId != ''">AND p.`store_id` = #{storeId}</if>
|
||||||
<if test="keyword != null and keyword.trim() != ''">AND (p.`code` LIKE CONCAT('%', #{keyword}, '%') OR p.`name` LIKE CONCAT('%', #{keyword}, '%'))</if>
|
<if test="keyword != null and keyword.trim() != ''">AND (p.`code` LIKE CONCAT('%', #{keyword}, '%') OR p.`name` LIKE CONCAT('%', #{keyword}, '%') OR p.`name_pinyin_full` LIKE CONCAT(#{keyword}, '%') OR p.`name_pinyin_initial` LIKE CONCAT(#{keyword}, '%') OR p.`name_pinyin_mixed` LIKE CONCAT(#{keyword}, '%'))</if>
|
||||||
</select>
|
</select>
|
||||||
<select id="selectProductByQuery" resultType="com.imyeyu.api.modules.gao.vo.GaoProductStockProductView">
|
<select id="selectProductByQuery" resultType="com.imyeyu.api.modules.gao.vo.GaoProductStockProductView">
|
||||||
SELECT p.`id` AS `product_id`,
|
SELECT p.`id` AS `product_id`,
|
||||||
@@ -79,7 +79,7 @@
|
|||||||
AND p.`stock_enabled` = 1
|
AND p.`stock_enabled` = 1
|
||||||
AND k.`stock_enabled` = 1 AND k.`status` = 'ACTIVE'
|
AND k.`stock_enabled` = 1 AND k.`status` = 'ACTIVE'
|
||||||
<if test="storeId != null and storeId != ''">AND p.`store_id` = #{storeId}</if>
|
<if test="storeId != null and storeId != ''">AND p.`store_id` = #{storeId}</if>
|
||||||
<if test="keyword != null and keyword.trim() != ''">AND (p.`code` LIKE CONCAT('%', #{keyword}, '%') OR p.`name` LIKE CONCAT('%', #{keyword}, '%'))</if>
|
<if test="keyword != null and keyword.trim() != ''">AND (p.`code` LIKE CONCAT('%', #{keyword}, '%') OR p.`name` LIKE CONCAT('%', #{keyword}, '%') OR p.`name_pinyin_full` LIKE CONCAT(#{keyword}, '%') OR p.`name_pinyin_initial` LIKE CONCAT(#{keyword}, '%') OR p.`name_pinyin_mixed` LIKE CONCAT(#{keyword}, '%'))</if>
|
||||||
GROUP BY p.`id`, p.`code`, p.`name`, p.`product_type`, p.`sort`
|
GROUP BY p.`id`, p.`code`, p.`name`, p.`product_type`, p.`sort`
|
||||||
ORDER BY p.`sort`, p.`name`, p.`code`
|
ORDER BY p.`sort`, p.`name`, p.`code`
|
||||||
LIMIT #{offset}, #{limit}
|
LIMIT #{offset}, #{limit}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
1 = 1
|
1 = 1
|
||||||
<if test="storeId != null and storeId != ''">AND r.`store_id` = #{storeId}</if>
|
<if test="storeId != null and storeId != ''">AND r.`store_id` = #{storeId}</if>
|
||||||
<if test="productId != null and productId != ''">AND k.`product_id` = #{productId}</if>
|
<if test="productId != null and productId != ''">AND k.`product_id` = #{productId}</if>
|
||||||
<if test="keyword != null and keyword.trim() != ''">AND (r.`product_name_snapshot` LIKE CONCAT('%', #{keyword}, '%') OR p.`name` LIKE CONCAT('%', #{keyword}, '%') OR p.`code` LIKE CONCAT('%', #{keyword}, '%'))</if>
|
<if test="keyword != null and keyword.trim() != ''">AND (r.`product_name_snapshot` LIKE CONCAT('%', #{keyword}, '%') OR p.`name` LIKE CONCAT('%', #{keyword}, '%') OR p.`name_pinyin_full` LIKE CONCAT(#{keyword}, '%') OR p.`name_pinyin_initial` LIKE CONCAT(#{keyword}, '%') OR p.`name_pinyin_mixed` LIKE CONCAT(#{keyword}, '%') OR p.`code` LIKE CONCAT('%', #{keyword}, '%'))</if>
|
||||||
<if test="bizType != null">AND r.`biz_type` = #{bizType}</if>
|
<if test="bizType != null">AND r.`biz_type` = #{bizType}</if>
|
||||||
<if test="bizId != null and bizId != ''">AND r.`biz_id` = #{bizId}</if>
|
<if test="bizId != null and bizId != ''">AND r.`biz_id` = #{bizId}</if>
|
||||||
<if test="operationType != null">AND r.`operation_type` = #{operationType}</if>
|
<if test="operationType != null">AND r.`operation_type` = #{operationType}</if>
|
||||||
|
|||||||
Reference in New Issue
Block a user