Compare commits
50
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
15d69f9361 | ||
|
|
2b4089ef59 | ||
|
|
20c3e1f422 | ||
|
|
3b19d9e930 | ||
|
|
5fd11e9caf | ||
|
|
0b98dcdfe9 | ||
|
|
b373cbbe46 | ||
|
|
acd97c7b9b | ||
|
|
118bdb1666 | ||
|
|
944de228f7 | ||
|
|
25c9cd4dfc | ||
|
|
882cd226ec | ||
|
|
feb4d7af66 | ||
|
|
d75ab1ed5f | ||
|
|
a501eb7443 | ||
|
|
19941d9480 | ||
|
|
cd3d522d4f | ||
|
|
181c5078e9 | ||
|
|
e97f46e6b4 | ||
|
|
c0f89deb83 | ||
|
|
ce695463d3 | ||
|
|
83c683d473 | ||
|
|
9555474b0b | ||
|
|
a150f9e017 | ||
|
|
ecd2fa1c33 | ||
|
|
e3236d262d | ||
|
|
c8e2e16ba5 | ||
|
|
99b44faf09 | ||
|
|
b3e3cbf84b | ||
|
|
0aee11d824 | ||
|
|
fcf358a768 | ||
|
|
619369104c | ||
|
|
4f1408b9d0 | ||
|
|
029eea70cc | ||
|
|
22b1e65385 | ||
|
|
2170c48763 | ||
|
|
c2d1c48aae | ||
|
|
e14958c643 | ||
|
|
da288338cd | ||
|
|
ea430f2468 | ||
|
|
f76f79744a | ||
|
|
19daaff907 | ||
|
|
db94d8f932 | ||
|
|
53618fe362 | ||
|
|
523edffc4e | ||
|
|
c7ddb1a8b0 | ||
|
|
45c9fc814a | ||
|
|
407dc13ac4 | ||
|
|
0c06bf16c2 | ||
|
|
1db39e77d3 |
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
<groupId>com.imyeyu.timiserverapi</groupId>
|
<groupId>com.imyeyu.timiserverapi</groupId>
|
||||||
<artifactId>TimiServerAPI</artifactId>
|
<artifactId>TimiServerAPI</artifactId>
|
||||||
<version>1.0.46</version>
|
<version>1.0.39</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<name>TimiServerAPI</name>
|
<name>TimiServerAPI</name>
|
||||||
<description>imyeyu.com API</description>
|
<description>imyeyu.com API</description>
|
||||||
@@ -215,11 +215,6 @@
|
|||||||
<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>
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ public class ArticleController {
|
|||||||
/// @return 文章分页
|
/// @return 文章分页
|
||||||
@JsonView(ResponseView.Public.class)
|
@JsonView(ResponseView.Public.class)
|
||||||
@RequestRateLimit
|
@RequestRateLimit
|
||||||
@RequireCorePermission(CorePermissionCode.ARTICLE_READ)
|
|
||||||
@PostMapping("/list")
|
@PostMapping("/list")
|
||||||
public PageResult<Article> list(@RequestBody Page<Article> page) {
|
public PageResult<Article> list(@RequestBody Page<Article> page) {
|
||||||
return service.page(page);
|
return service.page(page);
|
||||||
@@ -51,7 +50,7 @@ public class ArticleController {
|
|||||||
/// @return 文章详情
|
/// @return 文章详情
|
||||||
@JsonView(ResponseView.Public.class)
|
@JsonView(ResponseView.Public.class)
|
||||||
@RequestRateLimit
|
@RequestRateLimit
|
||||||
@RequestMapping("/detail")
|
@PostMapping("/detail")
|
||||||
public Article detail(@RequestParam String id) {
|
public Article detail(@RequestParam String id) {
|
||||||
Article article = service.get(id);
|
Article article = service.get(id);
|
||||||
article.setAttachmentList(attachmentService.listByBizId(Attachment.BizType.ARTICLE, article.getId()));
|
article.setAttachmentList(attachmentService.listByBizId(Attachment.BizType.ARTICLE, article.getId()));
|
||||||
|
|||||||
@@ -34,8 +34,6 @@ public class Article extends UUIDEntity implements SettingSupport {
|
|||||||
/// GAO 门店日记
|
/// GAO 门店日记
|
||||||
GAO_STORE_DIARY,
|
GAO_STORE_DIARY,
|
||||||
|
|
||||||
GAO_HELP,
|
|
||||||
|
|
||||||
GAO_SYSTEM,
|
GAO_SYSTEM,
|
||||||
|
|
||||||
/// 反馈
|
/// 反馈
|
||||||
|
|||||||
@@ -5,8 +5,6 @@ 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;
|
||||||
@@ -53,15 +51,4 @@ 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ 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;
|
||||||
@@ -55,15 +54,6 @@ 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,6 +6,7 @@ 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;
|
||||||
@@ -61,12 +62,15 @@ 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,8 +1,6 @@
|
|||||||
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;
|
||||||
@@ -63,18 +61,6 @@ 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;
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
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;
|
||||||
@@ -30,14 +27,6 @@ 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 开始创建时间
|
||||||
@@ -49,18 +38,6 @@ 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 查询条件
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
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;
|
||||||
|
|
||||||
@@ -19,7 +17,4 @@ public interface GaoCustomerChartService {
|
|||||||
|
|
||||||
/// 查询客户登记日历记录
|
/// 查询客户登记日历记录
|
||||||
List<GaoEventRecordCalendarView> eventRecordCalendar(GaoCustomerChartReq req);
|
List<GaoEventRecordCalendarView> eventRecordCalendar(GaoCustomerChartReq req);
|
||||||
|
|
||||||
/// 查询客户病症词频
|
|
||||||
List<GaoCustomerDiseaseWordView> customerDiseaseWord(GaoCustomerDiseaseWordReq req);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
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;
|
||||||
@@ -88,10 +87,4 @@ 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);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,9 +16,6 @@ public interface GaoOrderPaymentService {
|
|||||||
/// 登记收款
|
/// 登记收款
|
||||||
GaoFundRecord receive(GaoOrderPaymentReceiveRequest request);
|
GaoFundRecord receive(GaoOrderPaymentReceiveRequest request);
|
||||||
|
|
||||||
/// 登记已收款并直接核销
|
|
||||||
GaoFundRecord receiveAndVerify(GaoOrderPaymentReceiveRequest request);
|
|
||||||
|
|
||||||
/// 核销收款
|
/// 核销收款
|
||||||
GaoFundRecord verify(String fundRecordId);
|
GaoFundRecord verify(String fundRecordId);
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.service;
|
|
||||||
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoSalesOrder;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoOrderStraightThroughRequest;
|
|
||||||
|
|
||||||
/// GAO 订单创建直通服务
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-09-13
|
|
||||||
public interface GaoOrderStraightThroughService {
|
|
||||||
|
|
||||||
/// 在订单创建事务内完成可选的全额收款和全部履约
|
|
||||||
///
|
|
||||||
/// @param order 销售订单
|
|
||||||
/// @param straightThrough 直通请求,空为不直通
|
|
||||||
void complete(GaoSalesOrder order, GaoOrderStraightThroughRequest straightThrough);
|
|
||||||
}
|
|
||||||
@@ -33,14 +33,6 @@ public interface GaoProductSkuService extends BaseService<GaoProductSku, String>
|
|||||||
/// 查询并校验可销售 SKU 单位
|
/// 查询并校验可销售 SKU 单位
|
||||||
GaoProductSkuUnitSelection getSellableSkuUnit(String storeId, String skuId, String skuUnitId);
|
GaoProductSkuUnitSelection getSellableSkuUnit(String storeId, String skuId, String skuUnitId);
|
||||||
|
|
||||||
/// 查询并校验可用于历史订单履约的 SKU 单位
|
|
||||||
///
|
|
||||||
/// @param storeId 门店 ID
|
|
||||||
/// @param skuId SKU ID
|
|
||||||
/// @param skuUnitId SKU 单位 ID
|
|
||||||
/// @return SKU 单位选择结果
|
|
||||||
GaoProductSkuUnitSelection getFulfillableSkuUnit(String storeId, String skuId, String skuUnitId);
|
|
||||||
|
|
||||||
/// 查询并校验 SKU 单位
|
/// 查询并校验 SKU 单位
|
||||||
GaoProductSkuUnitSelection getSkuUnit(String storeId, String skuId, String skuUnitId, boolean purchase);
|
GaoProductSkuUnitSelection getSkuUnit(String storeId, String skuId, String skuUnitId, boolean purchase);
|
||||||
|
|
||||||
|
|||||||
@@ -46,9 +46,6 @@ public interface GaoProductStockService {
|
|||||||
/// 为履约预占库存
|
/// 为履约预占库存
|
||||||
boolean hasSufficientForFulfillment(String storeId, List<GaoStockChangeItem> items);
|
boolean hasSufficientForFulfillment(String storeId, List<GaoStockChangeItem> items);
|
||||||
|
|
||||||
/// 获取履约库存缺口提示,无缺口时返回 null
|
|
||||||
String getFulfillmentStockShortageMessage(String storeId, List<GaoStockChangeItem> items);
|
|
||||||
|
|
||||||
/// 为履约预占库存
|
/// 为履约预占库存
|
||||||
List<GaoProductStock> reserveForFulfillment(String storeId, String bizId, List<GaoStockChangeItem> items, String requestNo, String operatorUserId);
|
List<GaoProductStock> reserveForFulfillment(String storeId, String bizId, List<GaoStockChangeItem> items, String requestNo, String operatorUserId);
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
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;
|
||||||
@@ -22,9 +21,6 @@ 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,23 +1,15 @@
|
|||||||
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;
|
|
||||||
|
|
||||||
/// 客户报表服务实现
|
/// 客户报表服务实现
|
||||||
///
|
///
|
||||||
@@ -28,7 +20,6 @@ import java.util.Map;
|
|||||||
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) {
|
||||||
@@ -42,42 +33,6 @@ 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");
|
||||||
|
|||||||
-5
@@ -13,7 +13,6 @@ import com.imyeyu.api.modules.gao.entity.GaoSalesOrder;
|
|||||||
import com.imyeyu.api.modules.gao.entity.GaoSalesOrderItem;
|
import com.imyeyu.api.modules.gao.entity.GaoSalesOrderItem;
|
||||||
import com.imyeyu.api.modules.gao.mapper.GaoCustomerPackageMapper;
|
import com.imyeyu.api.modules.gao.mapper.GaoCustomerPackageMapper;
|
||||||
import com.imyeyu.api.modules.gao.service.GaoSalesOrderService;
|
import com.imyeyu.api.modules.gao.service.GaoSalesOrderService;
|
||||||
import com.imyeyu.api.modules.gao.service.GaoOrderStraightThroughService;
|
|
||||||
import com.imyeyu.api.modules.gao.service.GaoCustomerService;
|
import com.imyeyu.api.modules.gao.service.GaoCustomerService;
|
||||||
import com.imyeyu.api.modules.gao.service.GaoCustomerPackageService;
|
import com.imyeyu.api.modules.gao.service.GaoCustomerPackageService;
|
||||||
import com.imyeyu.api.modules.gao.service.GaoPackageConfigService;
|
import com.imyeyu.api.modules.gao.service.GaoPackageConfigService;
|
||||||
@@ -68,7 +67,6 @@ public class GaoCustomerPackageServiceImplement extends AbstractEntityService<Ga
|
|||||||
private final GaoProductSkuService skuService;
|
private final GaoProductSkuService skuService;
|
||||||
private final GaoCustomerService customerService;
|
private final GaoCustomerService customerService;
|
||||||
private final GaoSalesOrderService salesOrderService;
|
private final GaoSalesOrderService salesOrderService;
|
||||||
private final GaoOrderStraightThroughService straightThroughService;
|
|
||||||
private final GaoStoreScopeService storeScopeService;
|
private final GaoStoreScopeService storeScopeService;
|
||||||
private final AttachmentService attachmentService;
|
private final AttachmentService attachmentService;
|
||||||
private final UserLoginService userLoginService;
|
private final UserLoginService userLoginService;
|
||||||
@@ -170,7 +168,6 @@ public class GaoCustomerPackageServiceImplement extends AbstractEntityService<Ga
|
|||||||
if (existingOrder != null) {
|
if (existingOrder != null) {
|
||||||
GaoCustomerPackage existingPackage = getBySalesOrderId(existingOrder.getId());
|
GaoCustomerPackage existingPackage = getBySalesOrderId(existingOrder.getId());
|
||||||
verifyPurchaseIdempotency(existingOrder, existingPackage, request);
|
verifyPurchaseIdempotency(existingOrder, existingPackage, request);
|
||||||
straightThroughService.complete(salesOrderService.detail(existingOrder.getId()), request.getStraightThrough());
|
|
||||||
return existingPackage;
|
return existingPackage;
|
||||||
}
|
}
|
||||||
Long purchasedAt = TimiJava.defaultIfNull(request.getPurchasedAt(), Time.now());
|
Long purchasedAt = TimiJava.defaultIfNull(request.getPurchasedAt(), Time.now());
|
||||||
@@ -208,8 +205,6 @@ public class GaoCustomerPackageServiceImplement extends AbstractEntityService<Ga
|
|||||||
result.setStandardAmountSnapshot(config.getStandardAmount());
|
result.setStandardAmountSnapshot(config.getStandardAmount());
|
||||||
result.setRemark(request.getRemark());
|
result.setRemark(request.getRemark());
|
||||||
super.create(result);
|
super.create(result);
|
||||||
straightThroughService.complete(salesOrder, request.getStraightThrough());
|
|
||||||
salesOrder = salesOrderService.detail(salesOrder.getId());
|
|
||||||
result.setSalesOrder(salesOrder);
|
result.setSalesOrder(salesOrder);
|
||||||
result.setItemList(salesOrder.getItemList());
|
result.setItemList(salesOrder.getItemList());
|
||||||
result.setStatus(salesOrder.getStatus());
|
result.setStatus(salesOrder.getStatus());
|
||||||
|
|||||||
-13
@@ -14,9 +14,7 @@ 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;
|
||||||
@@ -412,10 +410,6 @@ 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)) {
|
||||||
@@ -426,7 +420,6 @@ 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;
|
||||||
@@ -438,12 +431,6 @@ 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;
|
||||||
|
|||||||
+2
-23
@@ -207,8 +207,7 @@ public class GaoOrderFulfillmentServiceImplement extends AbstractEntityService<G
|
|||||||
List<GaoStockChangeItem> stockItems = buildStockItems(order.getStoreId(), sourceList);
|
List<GaoStockChangeItem> stockItems = buildStockItems(order.getStoreId(), sourceList);
|
||||||
applySkuSpecSnapshots(stockItems, fulfillmentItemList);
|
applySkuSpecSnapshots(stockItems, fulfillmentItemList);
|
||||||
TimiException.requiredTrue(!stockItems.isEmpty(), "履约单没有需要占用的实物库存");
|
TimiException.requiredTrue(!stockItems.isEmpty(), "履约单没有需要占用的实物库存");
|
||||||
String stockShortageMessage = productStockService.getFulfillmentStockShortageMessage(order.getStoreId(), stockItems);
|
TimiException.requiredTrue(productStockService.hasSufficientForFulfillment(order.getStoreId(), stockItems), "库存仍然不足,不能准备履约");
|
||||||
TimiException.requiredTrue(stockShortageMessage == null, stockShortageMessage);
|
|
||||||
String operatorUserId = userLoginService.getRequireLoginUserId();
|
String operatorUserId = userLoginService.getRequireLoginUserId();
|
||||||
productStockService.reserveForFulfillment(order.getStoreId(), fulfillment.getId(), stockItems,
|
productStockService.reserveForFulfillment(order.getStoreId(), fulfillment.getId(), stockItems,
|
||||||
stockRequestNo(fulfillment, "RESERVE"), operatorUserId);
|
stockRequestNo(fulfillment, "RESERVE"), operatorUserId);
|
||||||
@@ -451,32 +450,12 @@ public class GaoOrderFulfillmentServiceImplement extends AbstractEntityService<G
|
|||||||
GaoSalesOrderItem.ItemType expectedItemType = order.getOrderType() == GaoSalesOrder.OrderType.PACKAGE
|
GaoSalesOrderItem.ItemType expectedItemType = order.getOrderType() == GaoSalesOrder.OrderType.PACKAGE
|
||||||
? GaoSalesOrderItem.ItemType.PACKAGE_ENTITLEMENT : GaoSalesOrderItem.ItemType.DIRECT_PRODUCT;
|
? GaoSalesOrderItem.ItemType.PACKAGE_ENTITLEMENT : GaoSalesOrderItem.ItemType.DIRECT_PRODUCT;
|
||||||
TimiException.requiredTrue(source.getItemType() == expectedItemType, "订单项类型与订单类型不匹配");
|
TimiException.requiredTrue(source.getItemType() == expectedItemType, "订单项类型与订单类型不匹配");
|
||||||
if (requestItem.getSkuUnitId().equals(source.getSkuUnitId())) {
|
GaoProductSkuUnitSelection selection = skuService.getSellableSkuUnit(order.getStoreId(), source.getSkuId(), requestItem.getSkuUnitId());
|
||||||
result.add(toSourceByOrderSnapshot(order, source, requestItem.getQuantity(), checkAvailable));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
GaoProductSkuUnitSelection selection = skuService.getFulfillableSkuUnit(order.getStoreId(), source.getSkuId(), requestItem.getSkuUnitId());
|
|
||||||
result.add(toSource(order, source, selection.getProduct(), selection.getSku(), selection.getUnit(), requestItem.getQuantity(), checkAvailable));
|
result.add(toSource(order, source, selection.getProduct(), selection.getSku(), selection.getUnit(), requestItem.getQuantity(), checkAvailable));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private SourceEntry toSourceByOrderSnapshot(GaoSalesOrder order, GaoSalesOrderItem source, BigDecimal quantity, boolean checkAvailable) {
|
|
||||||
GaoProductSku sku = skuService.get(source.getSkuId());
|
|
||||||
TimiException.required(sku, "履约来源 SKU 不存在");
|
|
||||||
GaoProduct product = productService.get(sku.getProductId());
|
|
||||||
TimiException.required(product, "履约来源产品不存在");
|
|
||||||
TimiException.requiredTrue(order.getStoreId().equals(product.getStoreId()), "履约来源产品不属于当前门店");
|
|
||||||
quantity = requiredPositiveQuantity(quantity, "履约数量");
|
|
||||||
if (!Boolean.TRUE.equals(sku.getAllowDecimalQuantity())) {
|
|
||||||
TimiException.requiredTrue(quantity.stripTrailingZeros().scale() <= 0, "该产品不允许小数数量");
|
|
||||||
}
|
|
||||||
BigDecimal baseQuantityPerUnit = requiredBaseQuantityPerUnit(source.getBaseQuantityPerUnitSnapshot());
|
|
||||||
BigDecimal baseQuantity = toBaseQuantity(quantity, baseQuantityPerUnit, "履约基础数量最多保留三位小数");
|
|
||||||
return buildSource(order, source, source.getSkuUnitId(), source.getUnitSnapshot(), baseQuantityPerUnit, quantity,
|
|
||||||
baseQuantity, product, sku, checkAvailable);
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<SourceEntry> loadPersistedSources(GaoSalesOrder order, List<GaoOrderFulfillmentItem> itemList) {
|
private List<SourceEntry> loadPersistedSources(GaoSalesOrder order, List<GaoOrderFulfillmentItem> itemList) {
|
||||||
TimiException.requiredTrue(itemList != null && !itemList.isEmpty(), "履约单没有明细");
|
TimiException.requiredTrue(itemList != null && !itemList.isEmpty(), "履约单没有明细");
|
||||||
List<GaoOrderFulfillmentItem> sortedItemList = new ArrayList<>(itemList);
|
List<GaoOrderFulfillmentItem> sortedItemList = new ArrayList<>(itemList);
|
||||||
|
|||||||
+4
-29
@@ -49,17 +49,10 @@ public class GaoOrderPaymentServiceImplement implements GaoOrderPaymentService {
|
|||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
@Override
|
@Override
|
||||||
public GaoFundRecord receive(GaoOrderPaymentReceiveRequest request) {
|
public GaoFundRecord receive(GaoOrderPaymentReceiveRequest request) {
|
||||||
return receiveInternal(request, false);
|
return receiveInternal(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@OperationAudit(AuditOperation.GAO_SALES_ORDER_PAYMENT_RECEIVE)
|
private GaoFundRecord receiveInternal(GaoOrderPaymentReceiveRequest request) {
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
|
||||||
@Override
|
|
||||||
public GaoFundRecord receiveAndVerify(GaoOrderPaymentReceiveRequest request) {
|
|
||||||
return receiveInternal(request, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private GaoFundRecord receiveInternal(GaoOrderPaymentReceiveRequest request, boolean verified) {
|
|
||||||
TimiException.required(request, "not found order payment request");
|
TimiException.required(request, "not found order payment request");
|
||||||
TimiException.required(request.getSalesOrderId(), "not found salesOrderId");
|
TimiException.required(request.getSalesOrderId(), "not found salesOrderId");
|
||||||
TimiException.required(request.getAmount(), "收款金额不能为空");
|
TimiException.required(request.getAmount(), "收款金额不能为空");
|
||||||
@@ -69,7 +62,7 @@ public class GaoOrderPaymentServiceImplement implements GaoOrderPaymentService {
|
|||||||
GaoFundRecord existing = fundRecordService.getByRequestNo(order.getStoreId(), requestNo);
|
GaoFundRecord existing = fundRecordService.getByRequestNo(order.getStoreId(), requestNo);
|
||||||
if (existing != null) {
|
if (existing != null) {
|
||||||
verifySameReceive(existing, order, request);
|
verifySameReceive(existing, order, request);
|
||||||
return verified && existing.getStatus() == GaoFundRecord.Status.PENDING ? verify(existing.getId()) : existing;
|
return existing;
|
||||||
}
|
}
|
||||||
TimiException.requiredTrue(order.getStatus() != GaoSalesOrder.Status.CANCELLED, "已取消订单不能收款");
|
TimiException.requiredTrue(order.getStatus() != GaoSalesOrder.Status.CANCELLED, "已取消订单不能收款");
|
||||||
TimiException.requiredTrue(order.getRefundStatus() != GaoSalesOrder.RefundStatus.REFUNDED, "已完成退款订单不能收款");
|
TimiException.requiredTrue(order.getRefundStatus() != GaoSalesOrder.RefundStatus.REFUNDED, "已完成退款订单不能收款");
|
||||||
@@ -78,27 +71,9 @@ public class GaoOrderPaymentServiceImplement implements GaoOrderPaymentService {
|
|||||||
TimiException.requiredTrue(pending + paid + request.getAmount() <= safe(order.getSaleAmount()), "累计收款不能超过成交价");
|
TimiException.requiredTrue(pending + paid + request.getAmount() <= safe(order.getSaleAmount()), "累计收款不能超过成交价");
|
||||||
TimiException.requiredTrue(hasPhoto(request.getAttachmentList()), "收款必须上传照片");
|
TimiException.requiredTrue(hasPhoto(request.getAttachmentList()), "收款必须上传照片");
|
||||||
GaoFundRecord record = newRecord(order, GaoFundRecord.OperationType.RECEIVE, requestNo, request.getAmount(), request.getOccurredAt(), request.getRemark());
|
GaoFundRecord record = newRecord(order, GaoFundRecord.OperationType.RECEIVE, requestNo, request.getAmount(), request.getOccurredAt(), request.getRemark());
|
||||||
record.setStatus(verified ? GaoFundRecord.Status.VERIFIED : GaoFundRecord.Status.PENDING);
|
record.setStatus(GaoFundRecord.Status.PENDING);
|
||||||
String verifierUserId = verified ? userLoginService.getRequireLoginUserId() : null;
|
|
||||||
Long verifiedAt = verified ? Time.now() : null;
|
|
||||||
if (verified) {
|
|
||||||
record.setVerifierUserId(verifierUserId);
|
|
||||||
record.setVerifiedAt(verifiedAt);
|
|
||||||
}
|
|
||||||
fundRecordService.createByOrderPayment(record);
|
fundRecordService.createByOrderPayment(record);
|
||||||
if (!verified) {
|
|
||||||
order.setPendingPaidAmount(pending + request.getAmount());
|
order.setPendingPaidAmount(pending + request.getAmount());
|
||||||
} else {
|
|
||||||
Long paidAtBefore = order.getPaidAt();
|
|
||||||
order.setPaidAmount(paid + request.getAmount());
|
|
||||||
orderService.recomputePaymentStatus(order);
|
|
||||||
orderService.updatePayment(order);
|
|
||||||
if (paidAtBefore == null && order.getPaidAt() != null) {
|
|
||||||
pointTriggerService.onSalesOrderPaid(order);
|
|
||||||
}
|
|
||||||
attachmentService.updateByBizId(Attachment.BizType.GAO_FUND_RECORD, record.getId(), request.getAttachmentList());
|
|
||||||
return record;
|
|
||||||
}
|
|
||||||
orderService.recomputePaymentStatus(order);
|
orderService.recomputePaymentStatus(order);
|
||||||
orderService.updatePayment(order);
|
orderService.updatePayment(order);
|
||||||
attachmentService.updateByBizId(Attachment.BizType.GAO_FUND_RECORD, record.getId(), request.getAttachmentList());
|
attachmentService.updateByBizId(Attachment.BizType.GAO_FUND_RECORD, record.getId(), request.getAttachmentList());
|
||||||
|
|||||||
-155
@@ -1,155 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.service.implement;
|
|
||||||
|
|
||||||
import com.imyeyu.api.bean.ModuleCode;
|
|
||||||
import com.imyeyu.api.config.dbsource.TimiServerDBConfig;
|
|
||||||
import com.imyeyu.api.modules.gao.bean.GaoPermissionCode;
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoFundRecord;
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoOrderFulfillment;
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoSalesOrder;
|
|
||||||
import com.imyeyu.api.modules.gao.entity.GaoSalesOrderItem;
|
|
||||||
import com.imyeyu.api.modules.gao.service.GaoOrderFulfillmentService;
|
|
||||||
import com.imyeyu.api.modules.gao.service.GaoOrderPaymentService;
|
|
||||||
import com.imyeyu.api.modules.gao.service.GaoOrderStraightThroughService;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoOrderFulfillmentCreateRequest;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoOrderFulfillmentActionRequest;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoOrderFulfillmentItemRequest;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoOrderPaymentReceiveRequest;
|
|
||||||
import com.imyeyu.api.modules.gao.vo.GaoOrderStraightThroughRequest;
|
|
||||||
import com.imyeyu.api.modules.user.service.PermissionChecker;
|
|
||||||
import com.imyeyu.java.TimiJava;
|
|
||||||
import com.imyeyu.java.bean.timi.TimiException;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/// GAO 订单创建直通服务实现
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-09-13
|
|
||||||
@Service
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class GaoOrderStraightThroughServiceImplement implements GaoOrderStraightThroughService {
|
|
||||||
|
|
||||||
private final GaoOrderPaymentService paymentService;
|
|
||||||
private final GaoOrderFulfillmentService fulfillmentService;
|
|
||||||
private final PermissionChecker permissionChecker;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
|
||||||
public void complete(GaoSalesOrder order, GaoOrderStraightThroughRequest straightThrough) {
|
|
||||||
if (straightThrough == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
boolean paymentVerified = Boolean.TRUE.equals(straightThrough.getPaymentVerified());
|
|
||||||
boolean receiveFullPayment = Boolean.TRUE.equals(straightThrough.getReceiveFullPayment());
|
|
||||||
boolean fulfillAll = Boolean.TRUE.equals(straightThrough.getFulfillAll());
|
|
||||||
Long paymentAmount = paymentVerified ? straightThrough.getPaymentAmount() : order.getSaleAmount();
|
|
||||||
if (!paymentVerified && !receiveFullPayment && !fulfillAll) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
TimiException.required(order, "not found sales order");
|
|
||||||
TimiException.required(order.getId(), "not found salesOrderId");
|
|
||||||
TimiException.requiredTrue(!(paymentVerified && receiveFullPayment), "已核销收款和已全额收款和核销不能同时启用");
|
|
||||||
if (paymentVerified) {
|
|
||||||
TimiException.required(paymentAmount, "已核销收款金额不能为空");
|
|
||||||
TimiException.requiredTrue(0 < paymentAmount && paymentAmount <= safe(order.getSaleAmount()), "已核销收款金额不能超过订单金额");
|
|
||||||
}
|
|
||||||
TimiException.requiredTrue(!fulfillAll || receiveFullPayment || order.getSaleAmount() == 0
|
|
||||||
|| (paymentVerified && paymentAmount.equals(order.getSaleAmount())),
|
|
||||||
"全部履约直通必须同时完成收款核销");
|
|
||||||
checkPermissions(order.getOrderType(), paymentVerified || receiveFullPayment, fulfillAll);
|
|
||||||
if (receiveFullPayment) {
|
|
||||||
settle(order, straightThrough);
|
|
||||||
} else if (paymentVerified) {
|
|
||||||
verifyReceivedPayment(order, straightThrough, paymentAmount);
|
|
||||||
}
|
|
||||||
if (fulfillAll) {
|
|
||||||
fulfill(order, straightThrough);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkPermissions(GaoSalesOrder.OrderType orderType, boolean paymentCompleted, boolean fulfillAll) {
|
|
||||||
List<String> permissionCodeList = new ArrayList<>();
|
|
||||||
permissionCodeList.add(orderType == GaoSalesOrder.OrderType.PACKAGE
|
|
||||||
? GaoPermissionCode.CUSTOMER_PACKAGE_CREATE.getValue() : GaoPermissionCode.SALES_ORDER_CREATE.getValue());
|
|
||||||
if (paymentCompleted) {
|
|
||||||
permissionCodeList.add(GaoPermissionCode.FUND_RECEIVE_CREATE.getValue());
|
|
||||||
permissionCodeList.add(GaoPermissionCode.FUND_RECEIVE_VERIFY.getValue());
|
|
||||||
}
|
|
||||||
if (fulfillAll) {
|
|
||||||
permissionCodeList.add(GaoPermissionCode.ORDER_FULFILLMENT_CREATE.getValue());
|
|
||||||
permissionCodeList.add(GaoPermissionCode.ORDER_FULFILLMENT_VERIFY.getValue());
|
|
||||||
}
|
|
||||||
permissionChecker.checkAll(ModuleCode.GAO, permissionCodeList.toArray(String[]::new));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void settle(GaoSalesOrder order, GaoOrderStraightThroughRequest straightThrough) {
|
|
||||||
if (order.getSaleAmount() == null || order.getSaleAmount() == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
GaoOrderPaymentReceiveRequest paymentRequest = new GaoOrderPaymentReceiveRequest();
|
|
||||||
paymentRequest.setSalesOrderId(order.getId());
|
|
||||||
paymentRequest.setRequestNo("ORDER-%s-FULL-PAY".formatted(order.getId()));
|
|
||||||
paymentRequest.setAmount(order.getSaleAmount());
|
|
||||||
paymentRequest.setOccurredAt(TimiJava.defaultIfNull(straightThrough.getPaymentOccurredAt(), order.getPurchasedAt()));
|
|
||||||
paymentRequest.setAttachmentList(straightThrough.getPaymentAttachmentList());
|
|
||||||
paymentRequest.setRemark(TimiJava.defaultIfEmpty(straightThrough.getPaymentRemark(), "随订单创建直接全额收款"));
|
|
||||||
GaoFundRecord record = paymentService.receive(paymentRequest);
|
|
||||||
if (record.getStatus() == GaoFundRecord.Status.PENDING) {
|
|
||||||
paymentService.verify(record.getId());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
TimiException.requiredTrue(record.getStatus() == GaoFundRecord.Status.VERIFIED, "直通收款记录不是已核销状态");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void verifyReceivedPayment(GaoSalesOrder order, GaoOrderStraightThroughRequest straightThrough, Long paymentAmount) {
|
|
||||||
GaoOrderPaymentReceiveRequest paymentRequest = new GaoOrderPaymentReceiveRequest();
|
|
||||||
paymentRequest.setSalesOrderId(order.getId());
|
|
||||||
paymentRequest.setRequestNo("ORDER-%s-VERIFIED-PAY".formatted(order.getId()));
|
|
||||||
paymentRequest.setAmount(paymentAmount);
|
|
||||||
paymentRequest.setOccurredAt(TimiJava.defaultIfNull(straightThrough.getPaymentOccurredAt(), order.getPurchasedAt()));
|
|
||||||
paymentRequest.setAttachmentList(straightThrough.getPaymentAttachmentList());
|
|
||||||
paymentRequest.setRemark(TimiJava.defaultIfEmpty(straightThrough.getPaymentRemark(), "随订单创建直接核销已有收款"));
|
|
||||||
GaoFundRecord record = paymentService.receiveAndVerify(paymentRequest);
|
|
||||||
TimiException.requiredTrue(record.getStatus() == GaoFundRecord.Status.VERIFIED, "直通收款记录不是已核销状态");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void fulfill(GaoSalesOrder order, GaoOrderStraightThroughRequest straightThrough) {
|
|
||||||
List<GaoSalesOrderItem> orderItemList = order.getItemList();
|
|
||||||
TimiException.requiredTrue(orderItemList != null && !orderItemList.isEmpty(), "销售订单没有可履约明细");
|
|
||||||
List<GaoOrderFulfillmentItemRequest> itemList = orderItemList.stream().map(item -> {
|
|
||||||
GaoOrderFulfillmentItemRequest result = new GaoOrderFulfillmentItemRequest();
|
|
||||||
result.setSourceOrderItemId(item.getId());
|
|
||||||
result.setSkuUnitId(item.getSkuUnitId());
|
|
||||||
result.setQuantity(item.getQuantity());
|
|
||||||
return result;
|
|
||||||
}).toList();
|
|
||||||
GaoOrderFulfillmentCreateRequest fulfillmentRequest = new GaoOrderFulfillmentCreateRequest();
|
|
||||||
fulfillmentRequest.setSalesOrderId(order.getId());
|
|
||||||
fulfillmentRequest.setRequestNo("ORDER-%s-FULL-FULFILL".formatted(order.getId()));
|
|
||||||
fulfillmentRequest.setDeliveredAt(TimiJava.defaultIfNull(straightThrough.getDeliveredAt(), order.getPurchasedAt()));
|
|
||||||
fulfillmentRequest.setItemList(itemList);
|
|
||||||
fulfillmentRequest.setAttachmentList(straightThrough.getFulfillmentAttachmentList());
|
|
||||||
fulfillmentRequest.setRemark(TimiJava.defaultIfEmpty(straightThrough.getFulfillmentRemark(), "随订单创建直接全部履约"));
|
|
||||||
GaoOrderFulfillment fulfillment = fulfillmentService.create(fulfillmentRequest);
|
|
||||||
if (fulfillment.getStatus() == GaoOrderFulfillment.Status.PENDING) {
|
|
||||||
fulfillmentService.verify(actionRequest(fulfillment.getId()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
TimiException.requiredTrue(fulfillment.getStatus() == GaoOrderFulfillment.Status.VERIFIED,
|
|
||||||
fulfillment.getStatus() == GaoOrderFulfillment.Status.WAITING_STOCK ? "库存不足,不能全部履约直通" : "直通履约单不是已核销状态");
|
|
||||||
}
|
|
||||||
|
|
||||||
private GaoOrderFulfillmentActionRequest actionRequest(String fulfillmentId) {
|
|
||||||
GaoOrderFulfillmentActionRequest request = new GaoOrderFulfillmentActionRequest();
|
|
||||||
request.setFulfillmentId(fulfillmentId);
|
|
||||||
return request;
|
|
||||||
}
|
|
||||||
|
|
||||||
private long safe(Long value) {
|
|
||||||
return value == null ? 0L : value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-12
@@ -17,7 +17,6 @@ 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;
|
||||||
@@ -167,7 +166,6 @@ 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 产品不能启用库存");
|
||||||
@@ -263,14 +261,4 @@ 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));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-18
@@ -109,22 +109,6 @@ public class GaoProductSkuServiceImplement extends AbstractEntityService<GaoProd
|
|||||||
return getSkuUnit(storeId, skuId, skuUnitId, false);
|
return getSkuUnit(storeId, skuId, skuUnitId, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public GaoProductSkuUnitSelection getFulfillableSkuUnit(String storeId, String skuId, String skuUnitId) {
|
|
||||||
TimiException.required(storeId, "门店 ID 不能为空");
|
|
||||||
TimiException.required(skuId, "SKU ID 不能为空");
|
|
||||||
TimiException.required(skuUnitId, "SKU 单位 ID 不能为空");
|
|
||||||
GaoProductSku sku = mapper.selectForUpdate(skuId);
|
|
||||||
TimiException.required(sku, "SKU 不存在");
|
|
||||||
TimiException.requiredTrue(storeId.equals(sku.getStoreId()), "SKU 不属于当前门店");
|
|
||||||
GaoProduct product = productServiceProvider.getObject().get(sku.getProductId());
|
|
||||||
TimiException.required(product, "产品不存在");
|
|
||||||
GaoProductSkuUnit unit = unitMapper.selectForUpdate(skuUnitId);
|
|
||||||
TimiException.required(unit, "SKU 单位不存在");
|
|
||||||
TimiException.requiredTrue(skuId.equals(unit.getSkuId()), "SKU 单位不属于当前 SKU");
|
|
||||||
return new GaoProductSkuUnitSelection(product, sku, unit);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public GaoProductSkuUnitSelection getSkuUnit(String storeId, String skuId, String skuUnitId, boolean purchase) {
|
public GaoProductSkuUnitSelection getSkuUnit(String storeId, String skuId, String skuUnitId, boolean purchase) {
|
||||||
TimiException.required(storeId, "not found storeId");
|
TimiException.required(storeId, "not found storeId");
|
||||||
@@ -370,8 +354,11 @@ public class GaoProductSkuServiceImplement extends AbstractEntityService<GaoProd
|
|||||||
TimiException.requiredTrue(1 == unitMapper.updateUnit(unit), "SKU 单位更新失败");
|
TimiException.requiredTrue(1 == unitMapper.updateUnit(unit), "SKU 单位更新失败");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TimiException.requiredTrue(existingUnitList.stream().allMatch(existing -> retainedIdSet.contains(existing.getId())),
|
for (GaoProductSkuUnit existing : existingUnitList) {
|
||||||
"已保存的 SKU 单位不能删除,请关闭允许销售和允许采购");
|
if (!retainedIdSet.contains(existing.getId())) {
|
||||||
|
unitMapper.delete(existing.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveSpecValues(String skuId, List<String> specValueIdList) {
|
private void saveSpecValues(String skuId, List<String> specValueIdList) {
|
||||||
|
|||||||
+4
-15
@@ -156,30 +156,19 @@ public class GaoProductStockServiceImplement implements GaoProductStockService {
|
|||||||
@Override
|
@Override
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
public boolean hasSufficientForFulfillment(String storeId, List<GaoStockChangeItem> items) {
|
public boolean hasSufficientForFulfillment(String storeId, List<GaoStockChangeItem> items) {
|
||||||
return getFulfillmentStockShortageMessage(storeId, items) == null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
|
||||||
public String getFulfillmentStockShortageMessage(String storeId, List<GaoStockChangeItem> items) {
|
|
||||||
TimiException.required(storeId, "not found storeId");
|
TimiException.required(storeId, "not found storeId");
|
||||||
if (items == null || items.isEmpty()) {
|
if (items == null || items.isEmpty()) {
|
||||||
return null;
|
return true;
|
||||||
}
|
}
|
||||||
List<GaoStockChangeItem> sortedItems = new ArrayList<>(items);
|
List<GaoStockChangeItem> sortedItems = new ArrayList<>(items);
|
||||||
sortedItems.sort(Comparator.comparing(GaoStockChangeItem::getSkuId));
|
sortedItems.sort(Comparator.comparing(GaoStockChangeItem::getSkuId));
|
||||||
List<String> shortageList = new ArrayList<>();
|
|
||||||
for (GaoStockChangeItem item : sortedItems) {
|
for (GaoStockChangeItem item : sortedItems) {
|
||||||
GaoProductStock stock = stockMapper.selectForUpdate(storeId, item.getSkuId());
|
GaoProductStock stock = stockMapper.selectForUpdate(storeId, item.getSkuId());
|
||||||
BigDecimal availableQuantity = stock == null ? ZERO : decimal(stock.getOnHandQuantity()).subtract(decimal(stock.getReservedQuantity()));
|
if (stock == null || decimal(stock.getOnHandQuantity()).subtract(decimal(stock.getReservedQuantity())).compareTo(item.getBaseQuantity()) < 0) {
|
||||||
BigDecimal shortageQuantity = item.getBaseQuantity().subtract(availableQuantity);
|
return false;
|
||||||
if (0 < shortageQuantity.signum()) {
|
|
||||||
shortageList.add("%s(%s)可用 %s %s,缺少 %s %s".formatted(
|
|
||||||
item.getProductNameSnapshot(), item.getSkuNameSnapshot(), availableQuantity.toPlainString(), item.getUnitSnapshot(),
|
|
||||||
shortageQuantity.toPlainString(), item.getUnitSnapshot()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return shortageList.isEmpty() ? null : "库存不足:" + String.join(";", shortageList);
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+1
-5
@@ -21,7 +21,6 @@ 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.GaoFundRecordService;
|
import com.imyeyu.api.modules.gao.service.GaoFundRecordService;
|
||||||
import com.imyeyu.api.modules.gao.service.GaoOrderFulfillmentService;
|
import com.imyeyu.api.modules.gao.service.GaoOrderFulfillmentService;
|
||||||
import com.imyeyu.api.modules.gao.service.GaoOrderStraightThroughService;
|
|
||||||
import com.imyeyu.api.modules.gao.service.GaoPointTriggerService;
|
import com.imyeyu.api.modules.gao.service.GaoPointTriggerService;
|
||||||
import com.imyeyu.api.modules.gao.service.GaoProductService;
|
import com.imyeyu.api.modules.gao.service.GaoProductService;
|
||||||
import com.imyeyu.api.modules.gao.service.GaoProductSkuService;
|
import com.imyeyu.api.modules.gao.service.GaoProductSkuService;
|
||||||
@@ -81,7 +80,6 @@ public class GaoSalesOrderServiceImplement extends AbstractEntityService<GaoSale
|
|||||||
private final GaoSalesOrderItemMapper itemMapper;
|
private final GaoSalesOrderItemMapper itemMapper;
|
||||||
private final GaoFundRecordService fundRecordService;
|
private final GaoFundRecordService fundRecordService;
|
||||||
private final ObjectProvider<GaoOrderFulfillmentService> fulfillmentServiceProvider;
|
private final ObjectProvider<GaoOrderFulfillmentService> fulfillmentServiceProvider;
|
||||||
private final ObjectProvider<GaoOrderStraightThroughService> straightThroughServiceProvider;
|
|
||||||
private final GaoCustomerService customerService;
|
private final GaoCustomerService customerService;
|
||||||
private final GaoProductService productService;
|
private final GaoProductService productService;
|
||||||
private final GaoProductSkuService skuService;
|
private final GaoProductSkuService skuService;
|
||||||
@@ -145,9 +143,7 @@ public class GaoSalesOrderServiceImplement extends AbstractEntityService<GaoSale
|
|||||||
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
@Transactional(TimiServerDBConfig.ROLLBACKER)
|
||||||
@Override
|
@Override
|
||||||
public GaoSalesOrder createDirectProductOrder(GaoDirectProductOrderCreateRequest request) {
|
public GaoSalesOrder createDirectProductOrder(GaoDirectProductOrderCreateRequest request) {
|
||||||
GaoSalesOrder order = createDirectInternal(request);
|
return createDirectInternal(request);
|
||||||
straightThroughServiceProvider.getObject().complete(order, request.getStraightThrough());
|
|
||||||
return detail(order.getId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@OperationAudit(AuditOperation.GAO_SALES_ORDER_UPDATE)
|
@OperationAudit(AuditOperation.GAO_SALES_ORDER_UPDATE)
|
||||||
|
|||||||
-7
@@ -3,7 +3,6 @@ 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;
|
||||||
@@ -44,12 +43,6 @@ 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);
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
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,8 +2,6 @@ package com.imyeyu.api.modules.gao.vo;
|
|||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// 客户每日统计视图
|
/// 客户每日统计视图
|
||||||
///
|
///
|
||||||
@@ -20,7 +18,4 @@ public class GaoCustomerDailyStateView {
|
|||||||
|
|
||||||
/// 截止当日客户总数
|
/// 截止当日客户总数
|
||||||
private Long totalCustomerCount;
|
private Long totalCustomerCount;
|
||||||
|
|
||||||
/// 当日新增客户列表
|
|
||||||
private List<GaoCustomerDailyStateCustomerView> customerList;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
||||||
@@ -33,9 +33,6 @@ public class GaoCustomerPackagePurchaseRequest {
|
|||||||
/// 购买照片
|
/// 购买照片
|
||||||
private List<Attachment> attachmentList;
|
private List<Attachment> attachmentList;
|
||||||
|
|
||||||
/// 创建订单后的直通处理
|
|
||||||
private GaoOrderStraightThroughRequest straightThrough;
|
|
||||||
|
|
||||||
/// 备注
|
/// 备注
|
||||||
private String remark;
|
private String remark;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,10 +23,4 @@ public class GaoCustomerPage extends Page<GaoCustomer> {
|
|||||||
|
|
||||||
/// 标签 ID 列表,客户必须同时拥有列表内全部标签
|
/// 标签 ID 列表,客户必须同时拥有列表内全部标签
|
||||||
private List<String> tagIdList;
|
private List<String> tagIdList;
|
||||||
|
|
||||||
/// 录入时间起始,包含,Unix 毫秒时间戳
|
|
||||||
private Long beginCreatedAt;
|
|
||||||
|
|
||||||
/// 录入时间结束,包含,Unix 毫秒时间戳
|
|
||||||
private Long endCreatedAt;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,9 +30,6 @@ public class GaoDirectProductOrderCreateRequest {
|
|||||||
/// 购买照片
|
/// 购买照片
|
||||||
private List<Attachment> attachmentList;
|
private List<Attachment> attachmentList;
|
||||||
|
|
||||||
/// 创建订单后的直通处理
|
|
||||||
private GaoOrderStraightThroughRequest straightThrough;
|
|
||||||
|
|
||||||
/// 备注
|
/// 备注
|
||||||
private String remark;
|
private String remark;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,44 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.gao.vo;
|
|
||||||
|
|
||||||
import com.imyeyu.api.modules.common.entity.Attachment;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/// GAO 订单创建直通请求
|
|
||||||
///
|
|
||||||
/// @author Codex
|
|
||||||
/// @since 2026-09-13
|
|
||||||
@Data
|
|
||||||
public class GaoOrderStraightThroughRequest {
|
|
||||||
|
|
||||||
/// true 为已有收款并直接核销
|
|
||||||
private Boolean paymentVerified;
|
|
||||||
|
|
||||||
/// 已核销收款金额,单位分
|
|
||||||
private Long paymentAmount;
|
|
||||||
|
|
||||||
/// true 为直接全额收款并核销
|
|
||||||
private Boolean receiveFullPayment;
|
|
||||||
|
|
||||||
/// 实际收款时间,空为订单下单时间
|
|
||||||
private Long paymentOccurredAt;
|
|
||||||
|
|
||||||
/// 收款凭证照片
|
|
||||||
private List<Attachment> paymentAttachmentList;
|
|
||||||
|
|
||||||
/// 收款备注
|
|
||||||
private String paymentRemark;
|
|
||||||
|
|
||||||
/// true 为直接全部履约并核销
|
|
||||||
private Boolean fulfillAll;
|
|
||||||
|
|
||||||
/// 实际履约时间,空为订单下单时间
|
|
||||||
private Long deliveredAt;
|
|
||||||
|
|
||||||
/// 履约凭证照片
|
|
||||||
private List<Attachment> fulfillmentAttachmentList;
|
|
||||||
|
|
||||||
/// 履约备注
|
|
||||||
private String fulfillmentRemark;
|
|
||||||
}
|
|
||||||
@@ -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;
|
||||||
|
|
||||||
/// 来源业务类型
|
/// 来源业务类型
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
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 {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-7
@@ -1,7 +0,0 @@
|
|||||||
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));
|
|
||||||
@@ -49,12 +49,6 @@
|
|||||||
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">
|
||||||
@@ -98,19 +92,6 @@
|
|||||||
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)
|
||||||
@@ -131,31 +112,4 @@
|
|||||||
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,23 +348,10 @@
|
|||||||
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
|
||||||
s.`customerId`,
|
MAX(`openIndex`) AS `anchorOpenIndex`
|
||||||
CASE
|
FROM `open_calendar`
|
||||||
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
|
||||||
@@ -374,7 +361,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 ON o.`customerId` = a.`customerId`
|
JOIN `anchor_date` a
|
||||||
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">
|
||||||
|
|||||||
@@ -53,7 +53,7 @@
|
|||||||
INNER JOIN `gao_customer` `c` ON `c`.`id` = `a`.`customer_id` AND `c`.`store_id` = `a`.`store_id`
|
INNER JOIN `gao_customer` `c` ON `c`.`id` = `a`.`customer_id` AND `c`.`store_id` = `a`.`store_id`
|
||||||
WHERE
|
WHERE
|
||||||
<include refid="queryWhere"/>
|
<include refid="queryWhere"/>
|
||||||
ORDER BY `a`.`total_earned` DESC, `a`.`created_at` DESC, `a`.`id` DESC
|
ORDER BY `a`.`created_at` DESC, `a`.`id` DESC
|
||||||
LIMIT #{offset}, #{limit}
|
LIMIT #{offset}, #{limit}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
|||||||
@@ -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}, '%') OR `name_pinyin_full` LIKE CONCAT(#{keyword}, '%') OR `name_pinyin_initial` LIKE CONCAT(#{keyword}, '%') OR `name_pinyin_mixed` LIKE CONCAT(#{keyword}, '%'))</if>
|
<if test="keyword != null and keyword.trim() != ''">AND (`code` LIKE CONCAT('%', #{keyword}, '%') OR `name` 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}, '%') OR `name_pinyin_full` LIKE CONCAT(#{keyword}, '%') OR `name_pinyin_initial` LIKE CONCAT(#{keyword}, '%') OR `name_pinyin_mixed` LIKE CONCAT(#{keyword}, '%'))</if>
|
<if test="keyword != null and keyword.trim() != ''">AND (`code` LIKE CONCAT('%', #{keyword}, '%') OR `name` 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 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>
|
<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>
|
||||||
</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 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>
|
<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>
|
||||||
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}, '%') 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>
|
<if test="keyword != null and keyword.trim() != ''">AND (p.`code` LIKE CONCAT('%', #{keyword}, '%') OR p.`name` 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}, '%') 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>
|
<if test="keyword != null and keyword.trim() != ''">AND (p.`code` LIKE CONCAT('%', #{keyword}, '%') OR p.`name` 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.`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="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="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