Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
C
custom-server
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lizhonghong
custom-server
Commits
c6bf40e2
Commit
c6bf40e2
authored
Jun 15, 2026
by
Lizh
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
对照ts的实现,迁移erpPage接口
parent
ee57572a
Hide whitespace changes
Inline
Side-by-side
Showing
27 changed files
with
1068 additions
and
617 deletions
+1068
-617
custom-server-app/src/main/java/com/jomalls/custom/app/dto/CustomProductInfoQuerySnakeDTO.java
+59
-4
custom-server-app/src/main/java/com/jomalls/custom/app/dto/CustomProductInfoSaveSnakeDTO.java
+305
-0
custom-server-app/src/main/java/com/jomalls/custom/app/dto/CustomProductInfoUpdateSnakeDTO.java
+1
-4
custom-server-app/src/main/java/com/jomalls/custom/app/exception/ServiceException.java
+2
-1
custom-server-app/src/main/java/com/jomalls/custom/app/service/CustomProductInfoService.java
+5
-8
custom-server-app/src/main/java/com/jomalls/custom/app/service/CustomWarehouseInfoService.java
+9
-9
custom-server-app/src/main/java/com/jomalls/custom/app/service/impl/CustomProductInfoServiceImpl.java
+213
-27
custom-server-app/src/main/java/com/jomalls/custom/app/service/impl/CustomWarehouseInfoServiceImpl.java
+13
-13
custom-server-app/src/main/java/com/jomalls/custom/app/vo/CraftCenterSnakeVO.java
+3
-0
custom-server-app/src/main/java/com/jomalls/custom/app/vo/CustomProductCraftRelSnakeVO.java
+38
-0
custom-server-app/src/main/java/com/jomalls/custom/app/vo/CustomProductInfoPageSnakeVO.java
+190
-0
custom-server-app/src/main/java/com/jomalls/custom/app/vo/CustomProductInfoPageVO.java
+0
-245
custom-server-app/src/main/java/com/jomalls/custom/app/vo/CustomProductInfoSnakeVO.java
+13
-0
custom-server-app/src/main/java/com/jomalls/custom/app/vo/CustomProductInfoVO.java
+0
-250
custom-server-app/src/main/java/com/jomalls/custom/app/vo/CustomProductWarehouseRelSnakeVO.java
+38
-0
custom-server-app/src/main/java/com/jomalls/custom/app/vo/CustomWarehouseInfoSnakeVO.java
+30
-29
custom-server-app/src/main/java/com/jomalls/custom/app/vo/FactoryPriceIntervalRelSnakeVO.java
+45
-0
custom-server-app/src/main/java/com/jomalls/custom/app/vo/ProductRemarkVO.java
+6
-0
custom-server-core/src/main/java/com/jomalls/custom/page/PageAdaptter.java
+63
-0
custom-server-starter/src/main/java/com/jomalls/custom/config/CommonExceptionHandlerAdvice.java
+1
-1
custom-server-starter/src/main/java/com/jomalls/custom/config/RestResponseBodyConfig.java
+6
-1
custom-server-webapp/src/main/java/com/jomalls/custom/webapp/controller/CustomProductInfoController.java
+6
-9
custom-server-webapp/src/main/java/com/jomalls/custom/webapp/controller/CustomProductItemController.java
+1
-1
custom-server-webapp/src/main/java/com/jomalls/custom/webapp/controller/CustomWarehouseInfoController.java
+12
-12
custom-server-webapp/src/main/java/com/jomalls/custom/webapp/controller/HealthController.java
+7
-1
custom-server-webapp/src/main/java/com/jomalls/custom/webapp/controller/LogCustomProductController.java
+1
-1
custom-server-webapp/src/main/java/com/jomalls/custom/webapp/controller/SysBillRuleController.java
+1
-1
No files found.
custom-server-app/src/main/java/com/jomalls/custom/app/dto/CustomProductInfoSnakeDTO.java
→
custom-server-app/src/main/java/com/jomalls/custom/app/dto/CustomProductInfo
Query
SnakeDTO.java
View file @
c6bf40e2
...
...
@@ -9,7 +9,9 @@ import lombok.EqualsAndHashCode;
import
java.io.Serial
;
import
java.math.BigDecimal
;
import
java.util.Arrays
;
import
java.util.List
;
import
java.util.stream.Collectors
;
/**
...
...
@@ -20,7 +22,7 @@ import java.util.List;
*/
@Data
@EqualsAndHashCode
(
callSuper
=
true
)
public
class
CustomProductInfoSnakeDTO
extends
PageRequest
{
public
class
CustomProductInfo
Query
SnakeDTO
extends
PageRequest
{
@Serial
private
static
final
long
serialVersionUID
=
1L
;
...
...
@@ -129,11 +131,42 @@ public class CustomProductInfoSnakeDTO extends PageRequest {
/**
* 状态:1待上架 10已上架 20已下架 30待下架 40已作废
* <p>
* 支持单值(Number)和逗号分隔多值(String "1,10,20")。
* 多值时通过 statusList 字段存储,status 为 null。
*/
@Schema
(
description
=
"状态:1待上架 10已上架 20已下架 30待下架 40已作废"
)
@Schema
(
description
=
"状态:1待上架 10已上架 20已下架 30待下架 40已作废
,支持逗号分隔多值
"
)
private
Integer
status
;
/**
* 状态多值列表(ERP 专用),从 "status" JSON 字段的逗号分隔字符串解析。
*/
@Schema
(
hidden
=
true
)
private
List
<
Integer
>
statusList
;
/** 兼容逗号分隔多值与单值 */
@JsonSetter
(
"status"
)
public
void
setStatusValue
(
Object
value
)
{
if
(
value
instanceof
String
s
&&
s
.
contains
(
","
))
{
try
{
this
.
statusList
=
Arrays
.
stream
(
s
.
split
(
","
))
.
map
(
String:
:
trim
).
filter
(
v
->
!
v
.
isEmpty
())
.
map
(
Integer:
:
parseInt
).
collect
(
Collectors
.
toList
());
}
catch
(
NumberFormatException
ignored
)
{
this
.
statusList
=
null
;
}
}
else
if
(
value
instanceof
Number
n
)
{
this
.
status
=
n
.
intValue
();
}
else
if
(
value
instanceof
String
s
)
{
try
{
this
.
status
=
Integer
.
parseInt
(
s
.
trim
());
}
catch
(
NumberFormatException
ignored
)
{
this
.
status
=
null
;
}
}
}
/**
* 是否九猫处理(0=否 1=是 2=不确定/未设置)
* <p>
* 兼容前端发送 Boolean(true→1, false→0)和 Number(0/1/2)。
...
...
@@ -231,11 +264,33 @@ public class CustomProductInfoSnakeDTO extends PageRequest {
private
BigDecimal
sales_price_max
;
/**
* 排序
* 排序值(用于过滤),与 ERP 排序方向(asc/desc)共享 "sort" JSON 字段。
* <p>
* 前端传 Number → 存入此字段;传 String "asc"/"desc" → 存入 sortDirection。
*/
@Schema
(
description
=
"排序"
)
@Schema
(
description
=
"排序
值或排序方向
"
)
private
Integer
sort
;
/** ERP 排序方向(asc/desc),从 "sort" JSON 字段解析 */
@Schema
(
hidden
=
true
)
private
String
sortDirection
;
/** 兼容 sort 字段的 Number(排序值)和 String "asc"/"desc"(排序方向) */
@JsonSetter
(
"sort"
)
public
void
setSortValue
(
Object
value
)
{
if
(
value
instanceof
String
s
&&
(
"asc"
.
equalsIgnoreCase
(
s
)
||
"desc"
.
equalsIgnoreCase
(
s
)))
{
this
.
sortDirection
=
s
.
toLowerCase
();
}
else
if
(
value
instanceof
Number
n
)
{
this
.
sort
=
n
.
intValue
();
}
else
if
(
value
instanceof
String
s
)
{
try
{
this
.
sort
=
Integer
.
parseInt
(
s
.
trim
());
}
catch
(
NumberFormatException
ignored
)
{
this
.
sort
=
null
;
}
}
}
/**
*
*/
...
...
custom-server-app/src/main/java/com/jomalls/custom/app/dto/CustomProductInfoSaveSnakeDTO.java
0 → 100644
View file @
c6bf40e2
package
com
.
jomalls
.
custom
.
app
.
dto
;
import
com.fasterxml.jackson.annotation.JsonSetter
;
import
com.jomalls.custom.page.PageRequest
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
jakarta.validation.constraints.Digits
;
import
jakarta.validation.constraints.Max
;
import
jakarta.validation.constraints.Min
;
import
jakarta.validation.constraints.NotBlank
;
import
jakarta.validation.constraints.NotEmpty
;
import
jakarta.validation.constraints.NotNull
;
import
jakarta.validation.constraints.Size
;
import
lombok.Data
;
import
lombok.EqualsAndHashCode
;
import
java.io.Serial
;
import
java.io.Serializable
;
import
java.math.BigDecimal
;
import
java.util.List
;
/**
* Entity
*
* @author huanying
* @date 2026-06-02 19:07:12
*/
@Data
public
class
CustomProductInfoSaveSnakeDTO
implements
Serializable
{
@Serial
private
static
final
long
serialVersionUID
=
1L
;
/**
* SKU 筛选
*/
@Schema
(
description
=
"SKU 筛选"
)
@Size
(
max
=
20
,
message
=
"sku长度不能超过20个字符"
)
private
String
sku
;
/**
* 商品名称
*/
@Schema
(
description
=
"name"
,
example
=
""
)
@NotNull
(
message
=
"商品名称不能为空"
)
@Size
(
max
=
255
,
message
=
"商品名称长度不能超过255个字符"
)
private
String
name
;
/**
* 商品类别ID
*/
@Schema
(
description
=
"商品类别ID"
,
example
=
""
)
@NotNull
(
message
=
"商品类别不能为空"
)
private
Integer
category_id
;
/**
* 材质
*/
@Schema
(
description
=
"材质"
,
example
=
""
)
@NotNull
(
message
=
"材质不能为空"
)
private
String
material
;
/**
* 印花类型:0满印 1局部印 2代发普货
*/
@Schema
(
description
=
"印花类型:0满印 1局部印 2代发普货"
)
@Min
(
value
=
0
,
message
=
"请选择正确的印花类型"
)
@Max
(
value
=
2
,
message
=
"请选择正确的印花类型"
)
private
Integer
print_type
;
/**
* 货号
*/
@Schema
(
description
=
"货号"
)
@Size
(
max
=
20
,
message
=
"货号长度不能超过20个字符"
)
private
String
product_no
;
/**
* 产地编码
*/
@Schema
(
description
=
"产地编码"
)
@NotBlank
(
message
=
"产地不能为空"
)
private
String
origin_code
;
/**
* 产地中文名
*/
@Schema
(
description
=
"产地中文名"
)
@NotBlank
(
message
=
"产地不能为空"
)
private
String
origin_name_cn
;
/**
* 产地英文名
*/
@Schema
(
description
=
"产地英文名"
)
@NotBlank
(
message
=
"产地不能为空"
)
private
String
origin_name_en
;
/**
* 币种编码
*/
@Schema
(
description
=
"币种编码"
)
@NotBlank
(
message
=
"币种不能为空"
)
private
String
currency_code
;
/**
* 币种名称
*/
@Schema
(
description
=
"币种名称"
)
@NotBlank
(
message
=
"币种不能为空"
)
private
String
currency_name
;
/**
* 产品类型:platform/customer
*/
@Schema
(
description
=
"产品类型:platform/customer"
)
@NotBlank
(
message
=
"产品类型不能为空"
)
private
String
product_type
;
/**
* 仓库 ID 列表
*/
@Schema
(
description
=
"仓库 ID 列表"
)
private
List
<
Integer
>
warehouseIds
;
/**
* 商品title
*/
@Schema
(
description
=
"title"
)
@Size
(
max
=
255
,
message
=
"title长度不能超过255个字符"
)
private
String
title
;
/**
* 工艺 ID 列表
*/
@Schema
(
description
=
"工艺 ID 列表"
)
private
List
<
Integer
>
craftIds
;
/**
* 状态:1待上架 10已上架 20已下架 30待下架 40已作废
*/
@Schema
(
description
=
"状态:1待上架 10已上架 20已下架 30待下架 40已作废"
)
private
Integer
status
;
/**
* 是否九猫处理(0=否 1=是)
* <p>
* 兼容前端发送 Boolean(true→1, false→0)。
*/
@Schema
(
description
=
"是否九猫处理(false=否 true=是)"
)
private
Boolean
processing
;
/**
* 英文备注
*/
@Schema
(
description
=
"英文备注"
)
private
String
remark
;
/**
* 中文备注
*/
@Schema
(
description
=
"中文备注"
)
private
String
cnRemark
;
/**
* 图片列表
*/
@Schema
(
description
=
"普通图片列表"
)
@NotEmpty
(
message
=
"商品图片不能为空"
)
private
List
<
CustomProductImageSnakeDTO
>
imageList
;
/**
* 尺码图片列表
*/
@Schema
(
description
=
"尺码图片列表(type=1)"
)
private
List
<
CustomProductImageSnakeDTO
>
sizeList
;
/**
* 颜色图
*/
@Schema
(
description
=
"颜色图(JSON字符串)"
)
private
String
color_images
;
/**
* 商品主图
*/
@Schema
(
description
=
"商品主图"
)
@NotBlank
(
message
=
"商品主图不能为空"
)
private
String
img_url
;
/**
* 工厂价格关联列表
*/
@Schema
(
description
=
"工厂价格关联列表"
)
private
List
<
FactoryPriceRelSnakeDTO
>
factoryPriceList
;
/**
* SKU 属性集合
*/
@Schema
(
description
=
"SKU 属性集合"
)
private
List
<
CustomProductInfoPropertyDTO
>
skuProperties
;
/**
* 商品明细
*/
@Schema
(
description
=
"商品明细"
,
implementation
=
CustomProductItemSnakeDTO
.
class
)
@NotEmpty
(
message
=
"商品明细不能为空"
)
private
List
<
CustomProductItemSnakeDTO
>
productList
;
/**
* 工厂价(¥)
*/
@Schema
(
description
=
"工厂价(¥)"
,
example
=
""
)
@Digits
(
integer
=
15
,
fraction
=
2
,
message
=
"工厂价数值最多保留2位小数"
)
private
BigDecimal
factory_price
;
/**
* 销售价(¥)
*/
@Schema
(
description
=
"销售价(¥)"
)
@Digits
(
integer
=
15
,
fraction
=
2
,
message
=
"工厂价数值最多保留2位小数"
)
private
BigDecimal
sales_price
;
/**
* 销售价最高价(¥)
*/
@Schema
(
description
=
"销售价最高价(¥)"
)
@Digits
(
integer
=
15
,
fraction
=
2
,
message
=
"工厂价数值最多保留2位小数"
)
private
BigDecimal
sales_price_max
;
/**
* 排序
*/
@Schema
(
description
=
"排序"
)
private
Integer
sort
;
/**
*
*/
@Schema
(
description
=
"商品属性ID 1"
,
example
=
""
)
@NotNull
(
message
=
"商品属性不能为空"
)
private
Integer
property1_cate_id
;
/**
*
*/
@Schema
(
description
=
"商品属性英文名称 1"
,
example
=
""
)
@NotNull
(
message
=
"商品属性名不能为空"
)
private
String
property1_enname
;
/**
*
*/
@Schema
(
description
=
"商品属性ID 2"
,
example
=
""
)
private
Integer
property2_cate_id
;
/**
*
*/
@Schema
(
description
=
"商品属性英文名称 2"
,
example
=
""
)
private
String
property2_enname
;
/**
*
*/
@Schema
(
description
=
"商品属性ID 3"
,
example
=
""
)
private
Integer
property3_cate_id
;
/**
*
*/
@Schema
(
description
=
"商品属性英文名称 3"
,
example
=
""
)
private
String
property3_enname
;
/**
* 重量kg
*/
@Schema
(
description
=
"重量(kg)"
,
example
=
""
)
@NotNull
(
message
=
"重量不能为空"
)
@Digits
(
integer
=
15
,
fraction
=
2
,
message
=
"重量(kg)数值最多保留2位小数"
)
private
BigDecimal
weight
;
/**
* 工厂价格区间关联列表
*/
@Schema
(
description
=
"工厂价格区间关联列表"
)
private
List
<
FactoryPriceIntervalRelSnakeDTO
>
factoryPriceIntervalList
;
/**
* DIY 用户 ID 列表(绑定客户)
*/
@Schema
(
description
=
"DIY 用户 ID 列表"
)
private
List
<
Integer
>
diyUserIds
;
/**
* 普通属性集合
*/
@Schema
(
description
=
"普通属性集合"
)
private
List
<
CustomProductInfoPropertyDTO
>
normalProperties
;
/**
* 工厂ID集合
*/
@Schema
(
description
=
"工厂ID集合"
)
private
List
<
Integer
>
factoryIds
;
}
custom-server-app/src/main/java/com/jomalls/custom/app/dto/CustomProductInfoUpdateSnakeDTO.java
View file @
c6bf40e2
...
...
@@ -21,7 +21,7 @@ import java.util.List;
@EqualsAndHashCode
(
callSuper
=
true
)
@Data
@Schema
(
description
=
"组合更新商品请求"
)
public
class
CustomProductInfoUpdateSnakeDTO
extends
CustomProductInfoS
nakeDTO
implements
Serializable
{
public
class
CustomProductInfoUpdateSnakeDTO
extends
CustomProductInfoS
aveSnakeDTO
{
@Serial
private
static
final
long
serialVersionUID
=
1L
;
...
...
@@ -44,9 +44,6 @@ public class CustomProductInfoUpdateSnakeDTO extends CustomProductInfoSnakeDTO i
@Schema
(
description
=
"尺码图变更列表(增/删/改)"
,
implementation
=
ProductImageChangeDTO
.
class
)
private
ProductImageChangeDTO
sizeChange
;
@Schema
(
description
=
"DIY 用户 ID 列表(绑定客户)"
)
private
List
<
Integer
>
diyUserIds
;
/**
* 工厂价格变更 DTO
*/
...
...
custom-server-app/src/main/java/com/jomalls/custom/app/exception/ServiceException.java
View file @
c6bf40e2
package
com
.
jomalls
.
custom
.
app
.
exception
;
import
com.jomalls.custom.enums.CodeEnum
;
import
lombok.Getter
;
import
java.io.Serial
;
...
...
@@ -40,7 +41,7 @@ public final class ServiceException extends RuntimeException {
}
public
ServiceException
(
String
message
)
{
this
.
message
=
message
;
this
(
message
,
CodeEnum
.
FAIL
.
getCode
())
;
}
public
ServiceException
(
String
message
,
Integer
code
)
{
...
...
custom-server-app/src/main/java/com/jomalls/custom/app/service/CustomProductInfoService.java
View file @
c6bf40e2
package
com
.
jomalls
.
custom
.
app
.
service
;
import
com.baomidou.mybatisplus.core.metadata.IPage
;
import
com.jomalls.custom.app.dto.AddBlackListDTO
;
import
com.jomalls.custom.app.dto.BindDiyUserDTO
;
import
com.jomalls.custom.app.dto.CustomProductInfoSnakeDTO
;
import
com.jomalls.custom.app.dto.CustomProductInfoUpdateSnakeDTO
;
import
com.jomalls.custom.app.dto.*
;
import
com.jomalls.custom.app.vo.CraftCenterSnakeVO
;
import
com.jomalls.custom.app.vo.CustomProductInfoPageSnakeVO
;
import
com.jomalls.custom.app.vo.CustomProductInfoSnakeVO
;
import
com.jomalls.custom.app.vo.CustomProductInfoVO
;
import
com.jomalls.custom.app.vo.DbDiySnakeVO
;
import
java.util.List
;
...
...
@@ -20,14 +17,14 @@ import java.util.List;
*/
public
interface
CustomProductInfoService
{
IPage
<
CustomProductInfo
SnakeVO
>
pageList
(
CustomProductInfo
SnakeDTO
param
);
IPage
<
CustomProductInfo
PageSnakeVO
>
pageList
(
CustomProductInfoQuery
SnakeDTO
param
);
/**
* 组合创建商品(SKU 生成 + 事务内写入主表及所有子表)
*
* @param dto 组合创建 DTO
*/
void
saveFull
(
CustomProductInfoSnakeDTO
dto
);
void
saveFull
(
CustomProductInfoS
aveS
nakeDTO
dto
);
/**
* 组合更新商品(事务内处理主表及子表的增/删/改差异)
...
...
@@ -108,7 +105,7 @@ public interface CustomProductInfoService {
* <p>
* 包含黑名单过滤、用户折扣、模板上架状态等 ERP 特定逻辑。
*/
IPage
<
CustomProductInfo
VO
>
erpPage
(
CustomProductInfo
SnakeDTO
param
);
IPage
<
CustomProductInfo
PageSnakeVO
>
erpPage
(
CustomProductInfoQuery
SnakeDTO
param
);
/**
* ERP 获取绑定 DIY(对齐 TS getBindsDiyByIdAndUserMark)
...
...
custom-server-app/src/main/java/com/jomalls/custom/app/service/CustomWarehouseInfoService.java
View file @
c6bf40e2
...
...
@@ -2,7 +2,7 @@ package com.jomalls.custom.app.service;
import
com.baomidou.mybatisplus.core.metadata.IPage
;
import
com.jomalls.custom.app.vo.CustomWarehouseInfoPageVO
;
import
com.jomalls.custom.app.vo.CustomWarehouseInfoVO
;
import
com.jomalls.custom.app.vo.CustomWarehouseInfo
Snake
VO
;
import
java.util.List
;
...
...
@@ -17,10 +17,10 @@ public interface CustomWarehouseInfoService {
/**
* 列表查询接口
*
* @param customWarehouseInfoVO 条件model
* @param customWarehouseInfo
Snake
VO 条件model
* @return list集合
*/
List
<
CustomWarehouseInfo
VO
>
list
(
CustomWarehouseInfoVO
customWarehouseInfo
VO
);
List
<
CustomWarehouseInfo
SnakeVO
>
list
(
CustomWarehouseInfoSnakeVO
customWarehouseInfoSnake
VO
);
/**
* 根据条件查询分页列表接口
...
...
@@ -28,7 +28,7 @@ public interface CustomWarehouseInfoService {
* @param customWarehouseInfoPageVO 分页入参model
* @return 分页对象
*/
IPage
<
CustomWarehouseInfoVO
>
pageList
(
CustomWarehouseInfoPageVO
customWarehouseInfoPageVO
);
IPage
<
CustomWarehouseInfo
Snake
VO
>
pageList
(
CustomWarehouseInfoPageVO
customWarehouseInfoPageVO
);
/**
* 根据id查询详情
...
...
@@ -36,21 +36,21 @@ public interface CustomWarehouseInfoService {
* @param id 主键
* @return 实体model
*/
CustomWarehouseInfoVO
info
(
Long
id
);
CustomWarehouseInfo
Snake
VO
info
(
Long
id
);
/**
* 保存对象
*
* @param customWarehouseInfoVO 保存对象
* @param customWarehouseInfo
Snake
VO 保存对象
*/
void
save
(
CustomWarehouseInfo
VO
customWarehouseInfo
VO
);
void
save
(
CustomWarehouseInfo
SnakeVO
customWarehouseInfoSnake
VO
);
/**
* 根据id修改对象
*
* @param customWarehouseInfoVO 修改对象
* @param customWarehouseInfo
Snake
VO 修改对象
*/
void
updateById
(
CustomWarehouseInfo
VO
customWarehouseInfo
VO
);
void
updateById
(
CustomWarehouseInfo
SnakeVO
customWarehouseInfoSnake
VO
);
/**
* 根据主键ID进行删除
...
...
custom-server-app/src/main/java/com/jomalls/custom/app/service/impl/CustomProductInfoServiceImpl.java
View file @
c6bf40e2
...
...
@@ -86,14 +86,14 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
@Override
public
IPage
<
CustomProductInfo
SnakeVO
>
pageList
(
CustomProductInfo
SnakeDTO
param
)
{
public
IPage
<
CustomProductInfo
PageSnakeVO
>
pageList
(
CustomProductInfoQuery
SnakeDTO
param
)
{
CustomAsserts
.
nonNull
(
param
,
"分页查询参数不能为空"
);
LambdaQueryWrapper
<
CustomProductInfoEntity
>
queryWrapper
=
new
LambdaQueryWrapper
<>();
// 构造查询条件
toQueryWrapper
(
param
,
queryWrapper
);
IPage
<
CustomProductInfoEntity
>
page
=
customProductInfoDomainService
.
selectPage
(
queryWrapper
,
param
);
return
page
.
convert
(
e
->
{
CustomProductInfo
SnakeVO
snakeVO
=
BeanMapper
.
snakeCase
().
convert
(
e
,
CustomProductInfo
SnakeVO
.
class
);
CustomProductInfo
PageSnakeVO
snakeVO
=
BeanMapper
.
snakeCase
().
convert
(
e
,
CustomProductInfoPage
SnakeVO
.
class
);
if
(
StringUtils
.
isNotBlank
(
e
.
getColorImages
()))
{
snakeVO
.
setColorImageList
(
Arrays
.
asList
(
e
.
getColorImages
().
split
(
","
)));
}
...
...
@@ -102,7 +102,7 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
}
/** 标准分页查询条件构建(非 ERP) */
private
void
toQueryWrapper
(
CustomProductInfoSnakeDTO
param
,
LambdaQueryWrapper
<
CustomProductInfoEntity
>
queryWrapper
)
{
private
void
toQueryWrapper
(
CustomProductInfo
Query
SnakeDTO
param
,
LambdaQueryWrapper
<
CustomProductInfoEntity
>
queryWrapper
)
{
toQueryWrapper
(
param
,
queryWrapper
,
false
);
}
...
...
@@ -111,7 +111,7 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
*
* @param isErp true=ERP 模式(title 双字段 OR 搜索,processing 支持 2=IS NULL,跳过 DIY/黑名单过滤)
*/
private
void
toQueryWrapper
(
CustomProductInfoSnakeDTO
param
,
LambdaQueryWrapper
<
CustomProductInfoEntity
>
queryWrapper
,
boolean
isErp
)
{
private
void
toQueryWrapper
(
CustomProductInfo
Query
SnakeDTO
param
,
LambdaQueryWrapper
<
CustomProductInfoEntity
>
queryWrapper
,
boolean
isErp
)
{
// 分类层级过滤
if
(
param
.
getCategory_id
()
!=
null
)
{
List
<
CategoryInfoModel
>
cateList
=
saasAdminService
.
getAllList
();
...
...
@@ -180,7 +180,10 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
queryWrapper
.
eq
(
CustomProductInfoEntity:
:
getSku
,
param
.
getSku
());
}
}
if
(
param
.
getStatus
()
!=
null
)
{
// 状态过滤(支持逗号分隔多值,对齐 TS status split(","))
if
(
param
.
getStatusList
()
!=
null
&&
!
param
.
getStatusList
().
isEmpty
())
{
queryWrapper
.
in
(
CustomProductInfoEntity:
:
getStatus
,
param
.
getStatusList
());
}
else
if
(
param
.
getStatus
()
!=
null
)
{
queryWrapper
.
eq
(
CustomProductInfoEntity:
:
getStatus
,
param
.
getStatus
());
}
if
(
StringUtils
.
isNotBlank
(
param
.
getProduct_type
()))
{
...
...
@@ -223,7 +226,7 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
* diyUserId 与 blackUserId 互斥(else if),
* diyUserId=-1 使用 LEFT JOIN 语义查找无绑定的商品。
*/
private
void
applyDiyAndBlacklistFilter
(
CustomProductInfoSnakeDTO
param
,
LambdaQueryWrapper
<
CustomProductInfoEntity
>
queryWrapper
)
{
private
void
applyDiyAndBlacklistFilter
(
CustomProductInfo
Query
SnakeDTO
param
,
LambdaQueryWrapper
<
CustomProductInfoEntity
>
queryWrapper
)
{
if
(
param
.
getDiyUserId
()
!=
null
)
{
if
(
param
.
getDiyUserId
()
==
-
1
)
{
// 查找无任何 diy_user 绑定的商品(通过 Domain 层 LEFT JOIN 查询)
...
...
@@ -261,7 +264,7 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
}
@Override
public
void
saveFull
(
CustomProductInfoSnakeDTO
dto
)
{
public
void
saveFull
(
CustomProductInfoS
aveS
nakeDTO
dto
)
{
CustomAsserts
.
nonNull
(
dto
,
"创建参数不能为空"
);
// 1. 生成 SKU 调用SysBillRuleService
...
...
@@ -830,9 +833,17 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
}
@Override
public
IPage
<
CustomProductInfo
VO
>
erpPage
(
CustomProductInfo
SnakeDTO
param
)
{
public
IPage
<
CustomProductInfo
PageSnakeVO
>
erpPage
(
CustomProductInfoQuery
SnakeDTO
param
)
{
CustomAsserts
.
nonNull
(
param
,
"分页查询参数不能为空"
);
if
(
StringUtils
.
isBlank
(
param
.
getUserMark
()))
{
throw
new
ServiceException
(
"userMark不能为空"
);
}
if
(
param
.
getPrint_type
()
==
null
)
{
throw
new
ServiceException
(
"print_type不能为空"
);
}
if
(
param
.
getProcessing
()
==
null
)
{
throw
new
ServiceException
(
"processing不能为空"
);
}
// 1. 查询用户(对齐 TS:683-684)
DbDiyUserEntity
user
=
null
;
if
(
StringUtils
.
isNotBlank
(
param
.
getUserMark
()))
{
...
...
@@ -842,7 +853,26 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
}
}
// 2. 构建查询条件
// 2. SKU JM 前缀拆分(对齐 TS:590-607)
// JM 开头的为产品 SKU,其余为 DIY 模板 SKU
if
(
StringUtils
.
isNotBlank
(
param
.
getSku
()))
{
List
<
String
>
productSkus
=
new
ArrayList
<>();
List
<
String
>
diySkus
=
new
ArrayList
<>();
for
(
String
s
:
param
.
getSku
().
split
(
","
))
{
String
trimmed
=
s
.
trim
();
if
(
trimmed
.
startsWith
(
"JM"
))
{
productSkus
.
add
(
trimmed
);
}
else
{
diySkus
.
add
(
trimmed
);
}
}
param
.
setSku
(
productSkus
.
isEmpty
()
?
null
:
String
.
join
(
","
,
productSkus
));
if
(!
diySkus
.
isEmpty
()
&&
StringUtils
.
isBlank
(
param
.
getDiySku
()))
{
param
.
setDiySku
(
String
.
join
(
","
,
diySkus
));
}
}
// 3. 构建查询条件
LambdaQueryWrapper
<
CustomProductInfoEntity
>
queryWrapper
=
new
LambdaQueryWrapper
<>();
toQueryWrapper
(
param
,
queryWrapper
,
true
);
...
...
@@ -908,8 +938,17 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
queryWrapper
.
in
(
CustomProductInfoEntity:
:
getId
,
allowedIds
);
}
// 6. 排序(对齐 TS:716-721:sort IS NULL ASC, sort ASC, id DESC)
queryWrapper
.
orderByAsc
(
CustomProductInfoEntity:
:
getSort
).
orderByDesc
(
CustomProductInfoEntity:
:
getId
);
// 6. 排序(对齐 TS:716-721:支持 sort=asc/desc,默认 sort IS NULL ASC, sort ASC, id DESC)
if
(
StringUtils
.
isNotBlank
(
param
.
getSortDirection
()))
{
if
(
"asc"
.
equalsIgnoreCase
(
param
.
getSortDirection
()))
{
queryWrapper
.
orderByAsc
(
CustomProductInfoEntity:
:
getId
);
}
else
{
queryWrapper
.
orderByDesc
(
CustomProductInfoEntity:
:
getId
);
}
}
else
{
// 默认排序需要 sort IS NULL ASC 确保 NULL 排在非 NULL 之后(对齐 TS Sequelize.literal)
queryWrapper
.
last
(
" ORDER BY sort IS NULL ASC, sort ASC, id DESC"
);
}
// 7. 执行分页查询
IPage
<
CustomProductInfoEntity
>
page
=
customProductInfoDomainService
.
selectPage
(
queryWrapper
,
param
);
...
...
@@ -923,7 +962,22 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
diyShelfStatusMap
=
Collections
.
emptyMap
();
}
// 9. 预计算折扣率(对齐 TS:731-733 setProductExternalPrice)
// 9. 批量加载关联实体(对齐 TS:715 include:[CraftCenter, CustomWarehouseInfo, CustomProductFactoryPriceIntervalRel])
final
Map
<
Integer
,
List
<
CraftCenterSnakeVO
>>
craftMap
;
final
Map
<
Integer
,
List
<
CustomWarehouseInfoSnakeVO
>>
warehouseMap
;
final
Map
<
Integer
,
List
<
FactoryPriceIntervalRelSnakeVO
>>
intervalMap
;
if
(!
rows
.
isEmpty
())
{
List
<
Integer
>
productIds
=
rows
.
stream
().
map
(
CustomProductInfoEntity:
:
getId
).
distinct
().
collect
(
Collectors
.
toList
());
craftMap
=
batchLoadCraftsByProductIds
(
productIds
);
warehouseMap
=
batchLoadWarehousesByProductIds
(
productIds
);
intervalMap
=
batchLoadFactoryPriceIntervalsByProductIds
(
productIds
);
}
else
{
craftMap
=
Collections
.
emptyMap
();
warehouseMap
=
Collections
.
emptyMap
();
intervalMap
=
Collections
.
emptyMap
();
}
// 10. 预计算折扣率(对齐 TS:316-355 setProductExternalPrice)
final
BigDecimal
discountRate
;
if
(
user
!=
null
&&
user
.
getDiscount
()
!=
null
)
{
discountRate
=
user
.
getDiscount
().
divide
(
new
BigDecimal
(
"100"
),
4
,
RoundingMode
.
HALF_UP
);
...
...
@@ -932,15 +986,17 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
}
return
page
.
convert
(
e
->
{
CustomProductInfoVO
vo
=
BeanMapper
.
mapper
().
convert
(
e
,
CustomProductInfoVO
.
class
);
// 应用用户折扣定价
if
(
discountRate
!=
null
)
{
if
(
vo
.
getSalesPrice
()
!=
null
)
{
vo
.
setSalesPrice
(
vo
.
getSalesPrice
().
multiply
(
discountRate
).
setScale
(
2
,
RoundingMode
.
HALF_UP
));
}
if
(
vo
.
getSalesPriceMax
()
!=
null
)
{
vo
.
setSalesPriceMax
(
vo
.
getSalesPriceMax
().
multiply
(
discountRate
).
setScale
(
2
,
RoundingMode
.
HALF_UP
));
}
CustomProductInfoPageSnakeVO
vo
=
BeanMapper
.
snakeCase
().
convert
(
e
,
CustomProductInfoPageSnakeVO
.
class
);
// 填充关联实体(对齐 TS include)
vo
.
setCraftList
(
craftMap
.
getOrDefault
(
e
.
getId
(),
Collections
.
emptyList
()));
vo
.
setWarehouseList
(
warehouseMap
.
getOrDefault
(
e
.
getId
(),
Collections
.
emptyList
()));
vo
.
setFactoryPriceIntervalList
(
intervalMap
.
getOrDefault
(
e
.
getId
(),
Collections
.
emptyList
()));
// 应用用户折扣定价(对齐 TS setProductExternalPrice:discount=1 时跳过)
if
(
discountRate
!=
null
&&
discountRate
.
compareTo
(
BigDecimal
.
ONE
)
!=
0
)
{
applyDiscountToVO
(
vo
,
discountRate
);
}
if
(
StringUtils
.
isNotBlank
(
e
.
getColorImages
()))
{
vo
.
setColorImageList
(
Arrays
.
asList
(
e
.
getColorImages
().
split
(
","
)));
}
// 标记绑定的 DIY 模板是否已上架
vo
.
setDiyShelfStatus
(
diyShelfStatusMap
.
getOrDefault
(
e
.
getDiyId
(),
false
));
...
...
@@ -948,8 +1004,30 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
});
}
/** 折扣逻辑(对齐 TS setProductExternalPrice:主表 + 价格区间 + 工厂价格) */
private
void
applyDiscountToVO
(
CustomProductInfoPageSnakeVO
vo
,
BigDecimal
discountRate
)
{
if
(
vo
.
getSales_price
()
!=
null
)
{
vo
.
setSales_price
(
vo
.
getSales_price
().
multiply
(
discountRate
).
setScale
(
2
,
RoundingMode
.
HALF_UP
));
}
if
(
vo
.
getSales_price_max
()
!=
null
)
{
vo
.
setSales_price_max
(
vo
.
getSales_price_max
().
multiply
(
discountRate
).
setScale
(
2
,
RoundingMode
.
HALF_UP
));
}
// 价格区间折扣(对齐 TS:342-347)
if
(
vo
.
getFactoryPriceIntervalList
()
!=
null
)
{
for
(
FactoryPriceIntervalRelSnakeVO
interval
:
vo
.
getFactoryPriceIntervalList
())
{
if
(
interval
.
getPrice_max
()
!=
null
)
{
interval
.
setPrice_max
(
interval
.
getPrice_max
().
multiply
(
discountRate
).
setScale
(
2
,
RoundingMode
.
HALF_UP
));
}
if
(
interval
.
getPrice_min
()
!=
null
)
{
interval
.
setPrice_min
(
interval
.
getPrice_min
().
multiply
(
discountRate
).
setScale
(
2
,
RoundingMode
.
HALF_UP
));
}
}
}
// 注意:erpPage 不加载 productList(TS include 亦不包含),子项折扣仅用于 getByIdOrSku
}
/** 返回空分页结果 */
private
IPage
<
CustomProductInfo
VO
>
emptyPage
(
CustomProductInfo
SnakeDTO
param
)
{
private
IPage
<
CustomProductInfo
PageSnakeVO
>
emptyPage
(
CustomProductInfoQuery
SnakeDTO
param
)
{
return
new
Page
<>(
param
.
getCurrent
(),
param
.
getSize
());
}
...
...
@@ -977,11 +1055,119 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
}
/**
* 批量查询工艺关联(对齐 TS erpPage include: CraftCenter → BelongsToMany → CustomProductCraftRel)
* <p>
* 每个 craft VO 嵌套一份 CustomProductCraftRel 数据(product_id + craft_id),
* 对齐 TS Sequelize BelongsToMany 自动包含的 junction 表数据。
*
* @return productId → List<CraftCenterSnakeVO>
*/
private
Map
<
Integer
,
List
<
CraftCenterSnakeVO
>>
batchLoadCraftsByProductIds
(
List
<
Integer
>
productIds
)
{
if
(
productIds
.
isEmpty
())
{
return
Collections
.
emptyMap
();
}
// 1. 关联表
List
<
CustomProductCraftRelEntity
>
rels
=
customProductCraftRelDomainService
.
list
(
new
LambdaQueryWrapper
<
CustomProductCraftRelEntity
>()
.
in
(
CustomProductCraftRelEntity:
:
getProductId
,
productIds
));
if
(
rels
.
isEmpty
())
{
return
Collections
.
emptyMap
();
}
// 2. 工艺实体
List
<
Long
>
craftIds
=
rels
.
stream
().
map
(
CustomProductCraftRelEntity:
:
getCraftId
).
distinct
().
collect
(
Collectors
.
toList
());
List
<
CraftCenterEntity
>
crafts
=
craftCenterDomainService
.
list
(
new
LambdaQueryWrapper
<
CraftCenterEntity
>().
in
(
CraftCenterEntity:
:
getId
,
craftIds
));
Map
<
Long
,
CraftCenterEntity
>
craftMap
=
crafts
.
stream
()
.
collect
(
Collectors
.
toMap
(
CraftCenterEntity:
:
getId
,
c
->
c
,
(
a
,
b
)
->
a
));
// 3. 按 productId 分组,每个 craft VO 独立创建(含 junction 表数据)
return
rels
.
stream
().
collect
(
Collectors
.
groupingBy
(
CustomProductCraftRelEntity:
:
getProductId
,
Collectors
.
mapping
(
r
->
{
CraftCenterEntity
craft
=
craftMap
.
get
(
r
.
getCraftId
());
if
(
craft
==
null
)
return
null
;
CraftCenterSnakeVO
craftVO
=
BeanMapper
.
snakeCase
().
convert
(
craft
,
CraftCenterSnakeVO
.
class
);
// 注入 junction 表数据(对齐 TS CustomProductCraftRel)
CustomProductCraftRelSnakeVO
relVO
=
new
CustomProductCraftRelSnakeVO
();
relVO
.
setId
(
r
.
getId
());
relVO
.
setProduct_id
(
r
.
getProductId
());
relVO
.
setCraft_id
(
r
.
getCraftId
());
craftVO
.
setCustomProductCraftRel
(
relVO
);
return
craftVO
;
},
Collectors
.
toList
())));
}
/**
* 批量查询仓库关联(对齐 TS erpPage include: CustomWarehouseInfo → BelongsToMany → CustomProductWarehouseRel)
*
* @return productId → List<CustomWarehouseInfoSnakeVO>
*/
private
Map
<
Integer
,
List
<
CustomWarehouseInfoSnakeVO
>>
batchLoadWarehousesByProductIds
(
List
<
Integer
>
productIds
)
{
if
(
productIds
.
isEmpty
())
{
return
Collections
.
emptyMap
();
}
// 1. 关联表
List
<
CustomProductWarehouseRelEntity
>
rels
=
customProductWarehouseRelDomainService
.
list
(
new
LambdaQueryWrapper
<
CustomProductWarehouseRelEntity
>()
.
in
(
CustomProductWarehouseRelEntity:
:
getProductId
,
productIds
));
if
(
rels
.
isEmpty
())
{
return
Collections
.
emptyMap
();
}
// 2. 仓库实体
List
<
Long
>
wIds
=
rels
.
stream
().
map
(
CustomProductWarehouseRelEntity:
:
getWarehouseId
).
distinct
().
collect
(
Collectors
.
toList
());
List
<
CustomWarehouseInfoEntity
>
warehouses
=
customWarehouseInfoDomainService
.
list
(
new
LambdaQueryWrapper
<
CustomWarehouseInfoEntity
>().
in
(
CustomWarehouseInfoEntity:
:
getId
,
wIds
));
Map
<
Long
,
CustomWarehouseInfoEntity
>
whMap
=
warehouses
.
stream
()
.
collect
(
Collectors
.
toMap
(
CustomWarehouseInfoEntity:
:
getId
,
w
->
w
,
(
a
,
b
)
->
a
));
// 3. 按 productId 分组,每个 warehouse VO 独立创建(含 junction 表数据)
return
rels
.
stream
().
collect
(
Collectors
.
groupingBy
(
CustomProductWarehouseRelEntity:
:
getProductId
,
Collectors
.
mapping
(
r
->
{
CustomWarehouseInfoEntity
wh
=
whMap
.
get
(
r
.
getWarehouseId
());
if
(
wh
==
null
)
return
null
;
CustomWarehouseInfoSnakeVO
whVO
=
BeanMapper
.
snakeCase
().
convert
(
wh
,
CustomWarehouseInfoSnakeVO
.
class
);
CustomProductWarehouseRelSnakeVO
relVO
=
new
CustomProductWarehouseRelSnakeVO
();
relVO
.
setId
(
r
.
getId
());
relVO
.
setProduct_id
(
r
.
getProductId
());
relVO
.
setWarehouse_id
(
r
.
getWarehouseId
());
whVO
.
setCustomProductWarehouseRel
(
relVO
);
return
whVO
;
},
Collectors
.
toList
())));
}
/**
* 批量查询工厂价格区间关联(对齐 TS erpPage include: CustomProductFactoryPriceIntervalRel → HasMany)
*
* @return productId → List<FactoryPriceIntervalRelSnakeVO>
*/
private
Map
<
Integer
,
List
<
FactoryPriceIntervalRelSnakeVO
>>
batchLoadFactoryPriceIntervalsByProductIds
(
List
<
Integer
>
productIds
)
{
if
(
productIds
.
isEmpty
())
{
return
Collections
.
emptyMap
();
}
List
<
CustomProductFactoryPriceIntervalRelEntity
>
rels
=
customProductFactoryPriceIntervalRelDomainService
.
list
(
new
LambdaQueryWrapper
<
CustomProductFactoryPriceIntervalRelEntity
>()
.
in
(
CustomProductFactoryPriceIntervalRelEntity:
:
getProductId
,
productIds
));
if
(
rels
.
isEmpty
())
{
return
Collections
.
emptyMap
();
}
List
<
FactoryPriceIntervalRelSnakeVO
>
voList
=
rels
.
stream
().
map
(
r
->
{
FactoryPriceIntervalRelSnakeVO
vo
=
new
FactoryPriceIntervalRelSnakeVO
();
vo
.
setId
(
r
.
getId
());
vo
.
setProduct_id
(
r
.
getProductId
());
vo
.
setCurrency_code
(
r
.
getCurrencyCode
());
vo
.
setPrice_min
(
r
.
getPriceMin
());
vo
.
setPrice_max
(
r
.
getPriceMax
());
return
vo
;
}).
toList
();
return
voList
.
stream
().
collect
(
Collectors
.
groupingBy
(
FactoryPriceIntervalRelSnakeVO:
:
getProduct_id
,
Collectors
.
toList
()));
}
/**
* 从事务外的子项列表中计算主表的 factory_price / sales_price / sales_price_max
* <p>
* factory_price 取子项中的最小值,sales_price 取子项中的最大值,sales_price_max 取子项中的最大值。
*/
private
void
computeProductPricesFromItems
(
CustomProductInfoSnakeDTO
dto
)
{
private
void
computeProductPricesFromItems
(
CustomProductInfoS
aveS
nakeDTO
dto
)
{
if
(
dto
.
getProductList
()
==
null
||
dto
.
getProductList
().
isEmpty
())
{
return
;
}
...
...
@@ -1021,13 +1207,13 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
* 从 SaveDTO 构建 Entity
* <p>
* SaveDTO 使用驼峰命名,与 Entity 字段名一致,直接用默认 mapper 转换。
* 对于蛇形命名的 {@link CustomProductInfoSnakeDTO},调用方需先用 {@code BeanMapper.snakeCase()} 转为 SaveDTO。
* 对于蛇形命名的 {@link CustomProductInfoS
aveS
nakeDTO},调用方需先用 {@code BeanMapper.snakeCase()} 转为 SaveDTO。
*
* @param dto 保存 DTO(驼峰命名)
* @param sku 生成的 SKU(创建时传入,更新时传 null)
* @return 商品实体
*/
private
CustomProductInfoEntity
buildEntityFromSaveDTO
(
CustomProductInfoSnakeDTO
dto
,
String
sku
)
{
private
CustomProductInfoEntity
buildEntityFromSaveDTO
(
CustomProductInfoS
aveS
nakeDTO
dto
,
String
sku
)
{
CustomProductInfoEntity
entity
=
BeanMapper
.
snakeCase
().
convert
(
dto
,
CustomProductInfoEntity
.
class
);
if
(
sku
!=
null
)
{
entity
.
setSku
(
sku
);
...
...
@@ -1289,7 +1475,7 @@ public class CustomProductInfoServiceImpl implements CustomProductInfoService {
* @return 新增子项的原始 SKU → 已保存实体映射(含自增 ID)
*/
private
Map
<
String
,
CustomProductItemEntity
>
handleItemChanges
(
ProductChangeSnakeDTO
change
,
Integer
productId
,
CustomProductInfoSnakeDTO
dto
)
{
ProductChangeSnakeDTO
change
,
Integer
productId
,
CustomProductInfoS
aveS
nakeDTO
dto
)
{
Map
<
String
,
CustomProductItemEntity
>
newItemMap
=
new
HashMap
<>();
if
(
change
==
null
)
{
return
newItemMap
;
...
...
custom-server-app/src/main/java/com/jomalls/custom/app/service/impl/CustomWarehouseInfoServiceImpl.java
View file @
c6bf40e2
...
...
@@ -7,7 +7,7 @@ import com.jomalls.custom.app.service.CustomWarehouseInfoService;
import
com.jomalls.custom.app.utils.BeanMapper
;
import
com.jomalls.custom.app.utils.CustomAsserts
;
import
com.jomalls.custom.app.vo.CustomWarehouseInfoPageVO
;
import
com.jomalls.custom.app.vo.CustomWarehouseInfoVO
;
import
com.jomalls.custom.app.vo.CustomWarehouseInfo
Snake
VO
;
import
com.jomalls.custom.dal.entity.CustomWarehouseInfoEntity
;
import
com.jomalls.custom.domain.service.CustomWarehouseInfoDomainService
;
import
lombok.extern.slf4j.Slf4j
;
...
...
@@ -37,34 +37,34 @@ public class CustomWarehouseInfoServiceImpl implements CustomWarehouseInfoServic
}
@Override
public
List
<
CustomWarehouseInfo
VO
>
list
(
CustomWarehouseInfoVO
customWarehouseInfo
VO
)
{
public
List
<
CustomWarehouseInfo
SnakeVO
>
list
(
CustomWarehouseInfoSnakeVO
customWarehouseInfoSnake
VO
)
{
QueryWrapper
<
CustomWarehouseInfoEntity
>
queryWrapper
=
new
QueryWrapper
<>();
// TODO 根据业务条件组装入参
List
<
CustomWarehouseInfoEntity
>
list
=
customWarehouseInfoDomainService
.
list
(
queryWrapper
);
return
list
.
stream
().
map
(
e
->
BeanMapper
.
mapper
().
convert
(
e
,
CustomWarehouseInfoVO
.
class
)).
collect
(
Collectors
.
toList
());
return
list
.
stream
().
map
(
e
->
BeanMapper
.
mapper
().
convert
(
e
,
CustomWarehouseInfo
Snake
VO
.
class
)).
collect
(
Collectors
.
toList
());
}
@Override
public
IPage
<
CustomWarehouseInfoVO
>
pageList
(
CustomWarehouseInfoPageVO
customWarehouseInfoPageVO
)
{
public
IPage
<
CustomWarehouseInfo
Snake
VO
>
pageList
(
CustomWarehouseInfoPageVO
customWarehouseInfoPageVO
)
{
CustomAsserts
.
nonNull
(
customWarehouseInfoPageVO
,
"分页查询参数不能为空"
);
QueryWrapper
<
CustomWarehouseInfoEntity
>
queryWrapper
=
new
QueryWrapper
<>();
// TODO 根据业务条件组装入参
IPage
<
CustomWarehouseInfoEntity
>
page
=
customWarehouseInfoDomainService
.
selectPage
(
queryWrapper
,
customWarehouseInfoPageVO
);
return
page
.
convert
(
e
->
BeanMapper
.
mapper
().
convert
(
e
,
CustomWarehouseInfoVO
.
class
));
return
page
.
convert
(
e
->
BeanMapper
.
mapper
().
convert
(
e
,
CustomWarehouseInfo
Snake
VO
.
class
));
}
@Override
public
CustomWarehouseInfoVO
info
(
Long
id
)
{
public
CustomWarehouseInfo
Snake
VO
info
(
Long
id
)
{
CustomAsserts
.
nonNull
(
id
,
"主键id不能为空"
);
CustomWarehouseInfoEntity
customWarehouseInfo
=
customWarehouseInfoDomainService
.
getById
(
id
);
return
BeanMapper
.
mapper
().
convert
(
customWarehouseInfo
,
CustomWarehouseInfoVO
.
class
);
return
BeanMapper
.
mapper
().
convert
(
customWarehouseInfo
,
CustomWarehouseInfo
Snake
VO
.
class
);
}
@Transactional
(
rollbackFor
=
Exception
.
class
)
@Override
public
void
save
(
CustomWarehouseInfo
VO
customWarehouseInfo
VO
)
{
CustomAsserts
.
nonNull
(
customWarehouseInfoVO
,
"实体对象不能为空"
);
CustomWarehouseInfoEntity
customWarehouseInfoEntity
=
BeanMapper
.
mapper
().
convert
(
customWarehouseInfoVO
,
CustomWarehouseInfoEntity
.
class
);
public
void
save
(
CustomWarehouseInfo
SnakeVO
customWarehouseInfoSnake
VO
)
{
CustomAsserts
.
nonNull
(
customWarehouseInfo
Snake
VO
,
"实体对象不能为空"
);
CustomWarehouseInfoEntity
customWarehouseInfoEntity
=
BeanMapper
.
mapper
().
convert
(
customWarehouseInfo
Snake
VO
,
CustomWarehouseInfoEntity
.
class
);
try
{
customWarehouseInfoDomainService
.
save
(
customWarehouseInfoEntity
);
}
catch
(
DuplicateKeyException
e
)
{
...
...
@@ -75,9 +75,9 @@ public class CustomWarehouseInfoServiceImpl implements CustomWarehouseInfoServic
@Transactional
(
rollbackFor
=
Exception
.
class
)
@Override
public
void
updateById
(
CustomWarehouseInfo
VO
customWarehouseInfo
VO
)
{
CustomAsserts
.
nonNull
(
customWarehouseInfoVO
,
"实体对象不能为空"
);
CustomWarehouseInfoEntity
customWarehouseInfo
=
BeanMapper
.
mapper
().
convert
(
customWarehouseInfoVO
,
CustomWarehouseInfoEntity
.
class
);
public
void
updateById
(
CustomWarehouseInfo
SnakeVO
customWarehouseInfoSnake
VO
)
{
CustomAsserts
.
nonNull
(
customWarehouseInfo
Snake
VO
,
"实体对象不能为空"
);
CustomWarehouseInfoEntity
customWarehouseInfo
=
BeanMapper
.
mapper
().
convert
(
customWarehouseInfo
Snake
VO
,
CustomWarehouseInfoEntity
.
class
);
try
{
customWarehouseInfoDomainService
.
updateById
(
customWarehouseInfo
);
}
catch
(
DuplicateKeyException
e
)
{
...
...
custom-server-app/src/main/java/com/jomalls/custom/app/vo/CraftCenterSnakeVO.java
View file @
c6bf40e2
...
...
@@ -65,4 +65,7 @@ public class CraftCenterSnakeVO implements Serializable {
@Schema
(
description
=
"修改时间"
)
private
Date
update_time
;
@Schema
(
description
=
"工艺与商品的关联数据(对齐 TS CustomProductCraftRel)"
)
private
CustomProductCraftRelSnakeVO
customProductCraftRel
;
}
custom-server-app/src/main/java/com/jomalls/custom/app/vo/CustomProductCraftRelSnakeVO.java
0 → 100644
View file @
c6bf40e2
package
com
.
jomalls
.
custom
.
app
.
vo
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
lombok.AllArgsConstructor
;
import
lombok.Builder
;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
import
java.io.Serial
;
import
java.io.Serializable
;
/**
* 工艺关联表 VO(对齐 TS CustomProductCraftRel 实体)
* <p>
* Sequelize BelongsToMany include 时会嵌套在 CraftCenter 对象下。
*
* @author Lizh
* @date 2026-06-15
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Schema
(
description
=
"工艺关联"
)
public
class
CustomProductCraftRelSnakeVO
implements
Serializable
{
@Serial
private
static
final
long
serialVersionUID
=
1L
;
@Schema
(
description
=
"关联 ID"
)
private
Integer
id
;
@Schema
(
description
=
"商品 ID"
)
private
Integer
product_id
;
@Schema
(
description
=
"工艺 ID"
)
private
Long
craft_id
;
}
custom-server-app/src/main/java/com/jomalls/custom/app/vo/CustomProductInfoPageSnakeVO.java
0 → 100644
View file @
c6bf40e2
package
com
.
jomalls
.
custom
.
app
.
vo
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
lombok.AllArgsConstructor
;
import
lombok.Builder
;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
import
java.io.Serial
;
import
java.io.Serializable
;
import
java.math.BigDecimal
;
import
java.util.Date
;
import
java.util.List
;
/**
* 商品完整详情 VO
* <p>
* 对齐 TS 项目 {@code entity/custom_product_info.ts} 的返回结构。
* 包含主表字段 + 所有子实体列表,由 App Service 通过并行单表查询后在 Java 层组合。
*
* @author Lizh
* @date 2026-06-06
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Schema
(
description
=
"商品完整详情"
)
public
class
CustomProductInfoPageSnakeVO
implements
Serializable
{
@Serial
private
static
final
long
serialVersionUID
=
1L
;
@Schema
(
description
=
"主键 ID"
)
private
Integer
id
;
@Schema
(
description
=
"SKU"
)
private
String
sku
;
@Schema
(
description
=
"货号"
)
private
String
product_no
;
@Schema
(
description
=
"title"
)
private
String
title
;
@Schema
(
description
=
"商品名称"
)
private
String
name
;
@Schema
(
description
=
"图片集"
)
private
List
<
String
>
colorImageList
;
@Schema
(
description
=
"图片集"
)
private
String
color_images
;
@Schema
(
description
=
"商品主图"
)
private
String
img_url
;
@Schema
(
description
=
"商品类别ID"
)
private
Integer
category_id
;
@Schema
(
description
=
"重量(kg)"
)
private
BigDecimal
weight
;
@Schema
(
description
=
"最小采购量"
)
private
Integer
purchasing_min
;
@Schema
(
description
=
"工厂价(¥)"
)
private
BigDecimal
factory_price
;
@Schema
(
description
=
"销售价(¥)"
)
private
BigDecimal
sales_price
;
@Schema
(
description
=
"销售价最高价(¥)"
)
private
BigDecimal
sales_price_max
;
@Schema
(
description
=
"状态:1待上架 10已上架 20已下架 30待下架 40已作废"
)
private
Integer
status
;
@Schema
(
description
=
"商品属性分类ID 1"
)
private
Integer
property1_cate_id
;
@Schema
(
description
=
"商品属性分类ID 2"
)
private
Integer
property2_cate_id
;
@Schema
(
description
=
"商品属性分类ID 3"
)
private
Integer
property3_cate_id
;
@Schema
(
description
=
"商品属性英文名称 1"
)
private
String
property1_enname
;
@Schema
(
description
=
"商品属性英文名称 2"
)
private
String
property2_enname
;
@Schema
(
description
=
"商品属性英文名称 3"
)
private
String
property3_enname
;
@Schema
(
description
=
"材质"
)
private
String
material
;
@Schema
(
description
=
"印花类型:0满印 1局部印"
)
private
Integer
print_type
;
@Schema
(
description
=
"产地编码"
)
private
String
origin_code
;
@Schema
(
description
=
"产地中文名"
)
private
String
origin_name_cn
;
@Schema
(
description
=
"产地英文名"
)
private
String
origin_name_en
;
@Schema
(
description
=
"币种编码"
)
private
String
currency_code
;
@Schema
(
description
=
"币种名称"
)
private
String
currency_name
;
@Schema
(
description
=
"产品类型:platform/customer"
)
private
String
product_type
;
@Schema
(
description
=
"工厂ID"
)
private
Integer
factory_id
;
@Schema
(
description
=
"工厂编码"
)
private
String
factory_code
;
@Schema
(
description
=
"是否九猫处理"
)
private
Boolean
processing
;
@Schema
(
description
=
"创建时间"
)
private
Date
create_time
;
@Schema
(
description
=
"更新时间"
)
private
Date
update_time
;
@Schema
(
description
=
"排序"
)
private
Integer
sort
;
@Schema
(
description
=
"默认模ID"
)
private
Integer
diy_id
;
@Schema
(
description
=
"默认模SKU"
)
private
String
diy_sku
;
@Schema
(
description
=
"普通图片列表(type=0)"
)
private
List
<
CustomProductImageSnakeVO
>
imageList
;
@Schema
(
description
=
"商品描述"
)
private
ProductRemarkVO
productRemark
;
@Schema
(
description
=
"商品中文描述"
)
private
ProductRemarkVO
productCnRemark
;
@Schema
(
description
=
"工厂价格关联列表"
)
private
List
<
CustomProductFactoryPriceRelSnakeVO
>
factoryPriceList
;
@Schema
(
description
=
"尺码图片列表(type=1)"
)
private
List
<
CustomProductImageSnakeVO
>
sizeList
;
@Schema
(
description
=
"DIY 用户 ID 列表"
)
private
List
<
Integer
>
diyUserIds
;
@Schema
(
description
=
"工艺 ID 列表"
)
private
List
<
String
>
craftIds
;
@Schema
(
description
=
"工厂 ID 列表"
)
private
List
<
Integer
>
factoryIds
;
@Schema
(
description
=
"仓库 ID 列表"
)
private
List
<
Integer
>
warehouseIds
;
@Schema
(
description
=
"英文备注内容"
)
private
String
remark
;
@Schema
(
description
=
"中文备注内容"
)
private
String
cnRemark
;
@Schema
(
description
=
"标记绑定的 DIY 模板是否已上架"
)
private
Boolean
diyShelfStatus
;
@Schema
(
description
=
"工厂价格区间关联列表(对齐 TS factoryPriceIntervalList)"
)
private
List
<
FactoryPriceIntervalRelSnakeVO
>
factoryPriceIntervalList
;
@Schema
(
description
=
"工艺列表"
)
private
List
<
CraftCenterSnakeVO
>
craftList
;
@Schema
(
description
=
"仓库列表"
)
private
List
<
CustomWarehouseInfoSnakeVO
>
warehouseList
;
}
custom-server-app/src/main/java/com/jomalls/custom/app/vo/CustomProductInfoPageVO.java
deleted
100644 → 0
View file @
ee57572a
package
com
.
jomalls
.
custom
.
app
.
vo
;
import
com.jomalls.custom.page.PageRequest
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
lombok.*
;
import
java.io.Serial
;
import
java.io.Serializable
;
import
java.math.BigDecimal
;
import
java.util.Date
;
/**
* PageModel
*
* @author Lizh
* @date 2026-06-03 11:57:02
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
(
callSuper
=
true
)
@Schema
(
description
=
"CustomProductInfoPageVo"
)
public
class
CustomProductInfoPageVO
extends
PageRequest
implements
Serializable
{
@Serial
private
static
final
long
serialVersionUID
=
1L
;
/**
*
*/
@Schema
(
description
=
""
)
private
Integer
id
;
/**
* sku
*/
@Schema
(
description
=
"sku"
)
private
String
sku
;
/**
*
*/
@Schema
(
description
=
""
)
private
String
title
;
/**
* 商品名称
*/
@Schema
(
description
=
"商品名称"
)
private
String
name
;
/**
* 商品主图
*/
@Schema
(
description
=
"商品主图"
)
private
String
imgUrl
;
/**
* 商品类别ID
*/
@Schema
(
description
=
"商品类别ID"
)
private
Integer
categoryId
;
/**
* 重量kg
*/
@Schema
(
description
=
"重量kg"
)
private
BigDecimal
weight
;
/**
* 最小采购量
*/
@Schema
(
description
=
"最小采购量"
)
private
Integer
purchasingMin
;
/**
* 工厂价(¥)
*/
@Schema
(
description
=
"工厂价(¥)"
)
private
BigDecimal
factoryPrice
;
/**
* 销售价(¥)
*/
@Schema
(
description
=
"销售价(¥)"
)
private
BigDecimal
salesPrice
;
/**
* 销售价最大值(¥)
*/
@Schema
(
description
=
"销售价最大值(¥)"
)
private
BigDecimal
salesPriceMax
;
/**
* 1待上架 10已上架 20已下架 30待下架 40已作废
*/
@Schema
(
description
=
"1待上架 10已上架 20已下架 30待下架 40已作废"
)
private
Integer
status
;
/**
*
*/
@Schema
(
description
=
""
)
private
Integer
property1CateId
;
/**
*
*/
@Schema
(
description
=
""
)
private
Integer
property2CateId
;
/**
*
*/
@Schema
(
description
=
""
)
private
Integer
property3CateId
;
/**
*
*/
@Schema
(
description
=
""
)
private
String
property1Enname
;
/**
*
*/
@Schema
(
description
=
""
)
private
String
property2Enname
;
/**
*
*/
@Schema
(
description
=
""
)
private
String
property3Enname
;
/**
* 颜色图
*/
@Schema
(
description
=
"颜色图"
)
private
String
colorImages
;
/**
* 材质
*/
@Schema
(
description
=
"材质"
)
private
String
material
;
/**
* 印花类型 0满印 1局部印
*/
@Schema
(
description
=
"印花类型 0满印 1局部印"
)
private
Integer
printType
;
/**
* 货号
*/
@Schema
(
description
=
"货号"
)
private
String
productNo
;
/**
* 产地code
*/
@Schema
(
description
=
"产地code"
)
private
String
originCode
;
/**
* 产地中文名字
*/
@Schema
(
description
=
"产地中文名字"
)
private
String
originNameCn
;
/**
* 产地英文名字
*/
@Schema
(
description
=
"产地英文名字"
)
private
String
originNameEn
;
/**
* 币种code
*/
@Schema
(
description
=
"币种code"
)
private
String
currencyCode
;
/**
* 币种名称
*/
@Schema
(
description
=
"币种名称"
)
private
String
currencyName
;
/**
* 产品类型(platform-平台直营 customer-客户自营)
*/
@Schema
(
description
=
"产品类型(platform-平台直营 customer-客户自营)"
)
private
String
productType
;
/**
* 工厂id
*/
@Schema
(
description
=
"工厂id"
)
private
Integer
factoryId
;
/**
* 工厂编码
*/
@Schema
(
description
=
"工厂编码"
)
private
String
factoryCode
;
/**
* 是否九猫处理
*/
@Schema
(
description
=
"是否九猫处理"
)
private
Boolean
processing
;
/**
* 创建时间
*/
@Schema
(
description
=
"创建时间"
)
private
Date
createTime
;
/**
*
*/
@Schema
(
description
=
""
)
private
Date
updateTime
;
/**
*
*/
@Schema
(
description
=
""
)
private
Integer
sort
;
/**
* 默认模ID
*/
@Schema
(
description
=
"默认模ID"
)
private
Integer
diyId
;
/**
* 默认模SKU
*/
@Schema
(
description
=
"默认模SKU"
)
private
String
diySku
;
}
custom-server-app/src/main/java/com/jomalls/custom/app/vo/CustomProductInfoSnakeVO.java
View file @
c6bf40e2
...
...
@@ -190,4 +190,17 @@ public class CustomProductInfoSnakeVO implements Serializable {
@Schema
(
description
=
"中文备注内容"
)
private
String
cnRemark
;
@Schema
(
description
=
"标记绑定的 DIY 模板是否已上架"
)
private
Boolean
diyShelfStatus
;
@Schema
(
description
=
"工厂价格区间关联列表"
)
private
List
<
FactoryPriceIntervalRelSnakeVO
>
factoryPriceIntervalList
;
@Schema
(
description
=
"标记绑定的 DIY 模板是否已上架"
)
private
List
<
CraftCenterSnakeVO
>
craftList
;
@Schema
(
description
=
"标记绑定的 DIY 模板是否已上架"
)
private
List
<
CustomWarehouseInfoSnakeVO
>
warehouseList
;
}
custom-server-app/src/main/java/com/jomalls/custom/app/vo/CustomProductInfoVO.java
deleted
100644 → 0
View file @
ee57572a
package
com
.
jomalls
.
custom
.
app
.
vo
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
lombok.AllArgsConstructor
;
import
lombok.Builder
;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
import
java.io.Serial
;
import
java.io.Serializable
;
import
java.math.BigDecimal
;
import
java.util.Date
;
import
java.util.List
;
/**
* Model
*
* @author Lizh
* @date 2026-06-03 11:57:02
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Schema
(
description
=
"VO"
)
public
class
CustomProductInfoVO
implements
Serializable
{
@Serial
private
static
final
long
serialVersionUID
=
1L
;
/**
*
*/
@Schema
(
description
=
""
)
private
Integer
id
;
/**
* sku
*/
@Schema
(
description
=
"sku"
)
private
String
sku
;
/**
*
*/
@Schema
(
description
=
""
)
private
String
title
;
/**
* 商品名称
*/
@Schema
(
description
=
"商品名称"
)
private
String
name
;
/**
* 商品主图
*/
@Schema
(
description
=
"商品主图"
)
private
String
imgUrl
;
/**
* 商品类别ID
*/
@Schema
(
description
=
"商品类别ID"
)
private
Integer
categoryId
;
/**
* 重量kg
*/
@Schema
(
description
=
"重量kg"
)
private
BigDecimal
weight
;
/**
* 最小采购量
*/
@Schema
(
description
=
"最小采购量"
)
private
Integer
purchasingMin
;
/**
* 工厂价(¥)
*/
@Schema
(
description
=
"工厂价(¥)"
)
private
BigDecimal
factoryPrice
;
/**
* 销售价(¥)
*/
@Schema
(
description
=
"销售价(¥)"
)
private
BigDecimal
salesPrice
;
/**
* 销售价最大值(¥)
*/
@Schema
(
description
=
"销售价最大值(¥)"
)
private
BigDecimal
salesPriceMax
;
/**
* 1待上架 10已上架 20已下架 30待下架 40已作废
*/
@Schema
(
description
=
"1待上架 10已上架 20已下架 30待下架 40已作废"
)
private
Integer
status
;
/**
*
*/
@Schema
(
description
=
""
)
private
Integer
property1CateId
;
/**
*
*/
@Schema
(
description
=
""
)
private
Integer
property2CateId
;
/**
*
*/
@Schema
(
description
=
""
)
private
Integer
property3CateId
;
/**
*
*/
@Schema
(
description
=
""
)
private
String
property1Enname
;
/**
*
*/
@Schema
(
description
=
""
)
private
String
property2Enname
;
/**
*
*/
@Schema
(
description
=
""
)
private
String
property3Enname
;
/**
* 颜色图
*/
@Schema
(
description
=
"颜色图"
)
private
String
colorImages
;
/**
* 材质
*/
@Schema
(
description
=
"材质"
)
private
String
material
;
/**
* 印花类型 0满印 1局部印
*/
@Schema
(
description
=
"印花类型 0满印 1局部印"
)
private
Integer
printType
;
/**
* 货号
*/
@Schema
(
description
=
"货号"
)
private
String
productNo
;
/**
* 产地code
*/
@Schema
(
description
=
"产地code"
)
private
String
originCode
;
/**
* 产地中文名字
*/
@Schema
(
description
=
"产地中文名字"
)
private
String
originNameCn
;
/**
* 产地英文名字
*/
@Schema
(
description
=
"产地英文名字"
)
private
String
originNameEn
;
/**
* 币种code
*/
@Schema
(
description
=
"币种code"
)
private
String
currencyCode
;
/**
* 币种名称
*/
@Schema
(
description
=
"币种名称"
)
private
String
currencyName
;
/**
* 产品类型(platform-平台直营 customer-客户自营)
*/
@Schema
(
description
=
"产品类型(platform-平台直营 customer-客户自营)"
)
private
String
productType
;
/**
* 工厂id
*/
@Schema
(
description
=
"工厂id"
)
private
Integer
factoryId
;
/**
* 工厂编码
*/
@Schema
(
description
=
"工厂编码"
)
private
String
factoryCode
;
/**
* 是否九猫处理
*/
@Schema
(
description
=
"是否九猫处理"
)
private
Boolean
processing
;
/**
* 创建时间
*/
@Schema
(
description
=
"创建时间"
)
private
Date
createTime
;
/**
*
*/
@Schema
(
description
=
""
)
private
Date
updateTime
;
/**
*
*/
@Schema
(
description
=
""
)
private
Integer
sort
;
/**
* 默认模ID
*/
@Schema
(
description
=
"默认模ID"
)
private
Integer
diyId
;
/**
* 默认模SKU
*/
@Schema
(
description
=
"默认模SKU"
)
private
String
diySku
;
@Schema
(
description
=
"绑定的DIY模板是否已上架(ERP专用)"
)
private
Boolean
diyShelfStatus
;
}
custom-server-app/src/main/java/com/jomalls/custom/app/vo/CustomProductWarehouseRelSnakeVO.java
0 → 100644
View file @
c6bf40e2
package
com
.
jomalls
.
custom
.
app
.
vo
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
lombok.AllArgsConstructor
;
import
lombok.Builder
;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
import
java.io.Serial
;
import
java.io.Serializable
;
/**
* 仓库关联表 VO(对齐 TS CustomProductWarehouseRel 实体)
* <p>
* Sequelize BelongsToMany include 时会嵌套在 CustomWarehouseInfo 对象下。
*
* @author Lizh
* @date 2026-06-15
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Schema
(
description
=
"仓库关联"
)
public
class
CustomProductWarehouseRelSnakeVO
implements
Serializable
{
@Serial
private
static
final
long
serialVersionUID
=
1L
;
@Schema
(
description
=
"关联 ID"
)
private
Integer
id
;
@Schema
(
description
=
"商品 ID"
)
private
Integer
product_id
;
@Schema
(
description
=
"仓库 ID"
)
private
Long
warehouse_id
;
}
custom-server-app/src/main/java/com/jomalls/custom/app/vo/CustomWarehouseInfoVO.java
→
custom-server-app/src/main/java/com/jomalls/custom/app/vo/CustomWarehouseInfo
Snake
VO.java
View file @
c6bf40e2
package
com
.
jomalls
.
custom
.
app
.
vo
;
import
com.jomalls.custom.page.PageRequest
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
lombok.*
;
...
...
@@ -19,7 +18,7 @@ import java.util.Date;
@NoArgsConstructor
@AllArgsConstructor
@Schema
(
description
=
"VO"
)
public
class
CustomWarehouseInfoVO
implements
Serializable
{
public
class
CustomWarehouseInfo
Snake
VO
implements
Serializable
{
@Serial
private
static
final
long
serialVersionUID
=
1L
;
...
...
@@ -33,67 +32,67 @@ public class CustomWarehouseInfoVO implements Serializable {
* 仓库名称
*/
@Schema
(
description
=
"仓库名称"
)
private
String
warehouse
N
ame
;
private
String
warehouse
_n
ame
;
/**
* 仓库编码
*/
@Schema
(
description
=
"仓库编码"
)
private
String
warehouse
C
ode
;
private
String
warehouse
_c
ode
;
/**
* 统筹物流
*/
@Schema
(
description
=
"统筹物流"
)
private
Boolean
overall
L
ogistics
;
private
Boolean
overall
_l
ogistics
;
/**
* 超级工厂
*/
@Schema
(
description
=
"超级工厂"
)
private
Integer
super
F
actory
;
private
Integer
super
_f
actory
;
/**
* 系统物流
*/
@Schema
(
description
=
"系统物流"
)
private
Boolean
system
L
ogistics
;
private
Boolean
system
_l
ogistics
;
/**
* 统筹物流覆盖范围
*/
@Schema
(
description
=
"统筹物流覆盖范围"
)
private
String
overall
LogisticsS
cope
;
private
String
overall
_logistics_s
cope
;
/**
* 联系人姓名
*/
@Schema
(
description
=
"联系人姓名"
)
private
String
contact
N
ame
;
private
String
contact
_n
ame
;
/**
* 联系人电话
*/
@Schema
(
description
=
"联系人电话"
)
private
String
contact
P
hone
;
private
String
contact
_p
hone
;
/**
* 联系人邮箱
*/
@Schema
(
description
=
"联系人邮箱"
)
private
String
contact
E
mail
;
private
String
contact
_e
mail
;
/**
* 国家代码
*/
@Schema
(
description
=
"国家代码"
)
private
String
country
C
ode
;
private
String
country
_c
ode
;
/**
* 国家名称
*/
@Schema
(
description
=
"国家名称"
)
private
String
country
N
ame
;
private
String
country
_n
ame
;
/**
* 州省
...
...
@@ -105,13 +104,13 @@ public class CustomWarehouseInfoVO implements Serializable {
* 州省 code
*/
@Schema
(
description
=
"州省 code"
)
private
String
province
C
ode
;
private
String
province
_c
ode
;
/**
* 州省简称
*/
@Schema
(
description
=
"州省简称"
)
private
String
province
A
bb
;
private
String
province
_a
bb
;
/**
* 城市
...
...
@@ -123,7 +122,7 @@ public class CustomWarehouseInfoVO implements Serializable {
* 城市编码
*/
@Schema
(
description
=
"城市编码"
)
private
String
city
C
ode
;
private
String
city
_c
ode
;
/**
* 区县
...
...
@@ -147,13 +146,13 @@ public class CustomWarehouseInfoVO implements Serializable {
* 公司名称
*/
@Schema
(
description
=
"公司名称"
)
private
String
company
N
ame
;
private
String
company
_n
ame
;
/**
* 社会信用代码
*/
@Schema
(
description
=
"社会信用代码"
)
private
String
social
CreditC
ode
;
private
String
social
_credit_c
ode
;
/**
* 备注
...
...
@@ -165,13 +164,13 @@ public class CustomWarehouseInfoVO implements Serializable {
*
*/
@Schema
(
description
=
""
)
private
Date
update
T
ime
;
private
Date
update
_t
ime
;
/**
*
*/
@Schema
(
description
=
""
)
private
Date
create
T
ime
;
private
Date
create
_t
ime
;
/**
* 1已上线,10待上线,20已下线,30待下线
...
...
@@ -183,37 +182,37 @@ public class CustomWarehouseInfoVO implements Serializable {
* 联系人姓名(中文)
*/
@Schema
(
description
=
"联系人姓名(中文)"
)
private
String
contact
NameC
n
;
private
String
contact
_name_c
n
;
/**
* 国家名称(中文)
*/
@Schema
(
description
=
"国家名称(中文)"
)
private
String
country
NameC
n
;
private
String
country
_name_c
n
;
/**
* 洲省(中文)
*/
@Schema
(
description
=
"洲省(中文)"
)
private
String
province
C
n
;
private
String
province
_c
n
;
/**
* 城市(中文)
*/
@Schema
(
description
=
"城市(中文)"
)
private
String
city
C
n
;
private
String
city
_c
n
;
/**
* 区县(中文)
*/
@Schema
(
description
=
"区县(中文)"
)
private
String
district
C
n
;
private
String
district
_c
n
;
/**
* 街道(中文)
*/
@Schema
(
description
=
"街道(中文)"
)
private
String
street
C
n
;
private
String
street
_c
n
;
/**
* 是否为正式仓库
...
...
@@ -225,13 +224,15 @@ public class CustomWarehouseInfoVO implements Serializable {
* 币种
*/
@Schema
(
description
=
"币种"
)
private
String
settlement
C
urrency
;
private
String
settlement
_c
urrency
;
/**
* 公司名称(中文)
*/
@Schema
(
description
=
"公司名称(中文)"
)
private
String
companyNameCn
;
private
String
company_name_cn
;
@Schema
(
description
=
"仓库与商品的关联数据(对齐 TS CustomProductWarehouseRel)"
)
private
CustomProductWarehouseRelSnakeVO
customProductWarehouseRel
;
}
custom-server-app/src/main/java/com/jomalls/custom/app/vo/FactoryPriceIntervalRelSnakeVO.java
0 → 100644
View file @
c6bf40e2
package
com
.
jomalls
.
custom
.
app
.
vo
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
lombok.AllArgsConstructor
;
import
lombok.Builder
;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
import
java.io.Serial
;
import
java.io.Serializable
;
import
java.math.BigDecimal
;
/**
* 工厂价格区间关联 VO(对齐 TS CustomProductFactoryPriceIntervalRel)
* <p>
* 在 erpPage 等包含关联数据的端点中作为 productInfo.factoryPriceIntervalList 返回。
*
* @author Lizh
* @date 2026-06-15
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Schema
(
description
=
"工厂价格区间关联"
)
public
class
FactoryPriceIntervalRelSnakeVO
implements
Serializable
{
@Serial
private
static
final
long
serialVersionUID
=
1L
;
@Schema
(
description
=
"关联 ID"
)
private
Integer
id
;
@Schema
(
description
=
"商品 ID"
)
private
Integer
product_id
;
@Schema
(
description
=
"币种编码"
)
private
String
currency_code
;
@Schema
(
description
=
"系统成本最低价"
)
private
BigDecimal
price_min
;
@Schema
(
description
=
"系统成本最高价"
)
private
BigDecimal
price_max
;
}
custom-server-app/src/main/java/com/jomalls/custom/app/vo/ProductRemarkVO.java
View file @
c6bf40e2
...
...
@@ -37,4 +37,10 @@ public class ProductRemarkVO implements Serializable {
*/
@Schema
(
description
=
"图片地址"
)
private
String
remark
;
/**
* 创建时间
*/
@Schema
(
description
=
"创建时间"
)
private
String
create_time
;
}
custom-server-core/src/main/java/com/jomalls/custom/page/PageAdaptter.java
0 → 100644
View file @
c6bf40e2
package
com
.
jomalls
.
custom
.
page
;
import
com.baomidou.mybatisplus.core.metadata.IPage
;
import
lombok.AllArgsConstructor
;
import
lombok.Getter
;
import
java.io.Serial
;
import
java.io.Serializable
;
import
java.util.List
;
/**
* 分页结果适配转换,将MyBatis-Plus分页结果转为老服务(TS)格式
*
* <pre>
* 映射关系:
* IPage.records → list
* IPage.current → curPage
* IPage.total → totalRow
* IPage.pages → totalPage
* </pre>
*
* @author Lizh
* @date 2026-06-15
*/
@Getter
@AllArgsConstructor
public
class
PageAdaptter
<
T
>
implements
Serializable
{
@Serial
private
static
final
long
serialVersionUID
=
1L
;
/** 数据列表(对齐老服务 "list") */
private
List
<
T
>
list
;
/** 当前页码(对齐老服务 "curPage") */
private
long
curPage
;
/** 总记录数(对齐老服务 "totalRow") */
private
long
totalRow
;
/** 总页数(对齐老服务 "totalPage") */
private
long
totalPage
;
/** 每页多少条 */
private
long
size
;
/**
* 从 MyBatis-Plus 分页结果构建老服务格式的分页 VO。
*
* @param page MyBatis-Plus 分页对象
* @param <T> 数据类型
* @return 老服务格式的分页结果
*/
public
static
<
T
>
PageAdaptter
<
T
>
from
(
IPage
<
T
>
page
)
{
return
new
PageAdaptter
<>(
page
.
getRecords
(),
page
.
getCurrent
(),
page
.
getTotal
(),
page
.
getPages
(),
page
.
getSize
()
);
}
}
custom-server-starter/src/main/java/com/jomalls/custom/config/CommonExceptionHandlerAdvice.java
View file @
c6bf40e2
...
...
@@ -91,7 +91,7 @@ public class CommonExceptionHandlerAdvice {
@ExceptionHandler
(
ServiceException
.
class
)
public
ResponseEntity
<
R
<
Object
>>
handleServiceException
(
ServiceException
e
)
{
log
.
debug
(
"[ 业务异常 ] code={}, {}"
,
e
.
getCode
(),
e
.
getMessage
(),
e
);
HttpStatus
httpStatus
=
CodeEnum
.
MAP
.
getOrDefault
(
e
.
getCode
(),
HttpStatus
.
INTERNAL_SERVER_ERROR
);
HttpStatus
httpStatus
=
CodeEnum
.
MAP
.
getOrDefault
(
e
.
getCode
(),
HttpStatus
.
OK
);
return
ResponseEntity
.
status
(
httpStatus
).
body
(
R
.
fail
(
e
.
getCode
(),
e
.
getMessage
()));
}
...
...
custom-server-starter/src/main/java/com/jomalls/custom/config/RestResponseBodyConfig.java
View file @
c6bf40e2
package
com
.
jomalls
.
custom
.
config
;
import
com.baomidou.mybatisplus.core.metadata.IPage
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
com.jomalls.custom.enums.CodeEnum
;
import
com.jomalls.custom.page.PageAdaptter
;
import
org.jspecify.annotations.NonNull
;
import
org.springframework.core.MethodParameter
;
import
org.springframework.core.annotation.AnnotatedElementUtils
;
...
...
@@ -23,7 +25,6 @@ import java.util.List;
/**
* 统一返回处理
*
* @author lizh
* @date 2026-05-28 10:25:27
*/
...
...
@@ -60,6 +61,10 @@ public class RestResponseBodyConfig implements ResponseBodyAdvice<Object> {
}
else
if
(
this
.
isNoWrapResponseUrl
(
requestPath
))
{
return
body
;
}
else
{
// 分页结果转为老服务(TS)格式:records→list, current→curPage, total→totalRow, pages→totalPage
if
(
body
instanceof
IPage
<?>
page
)
{
body
=
PageAdaptter
.
from
(
page
);
}
if
(
body
instanceof
String
)
{
try
{
return
objectMapper
.
writeValueAsString
(
com
.
jomalls
.
custom
.
utils
.
R
.
ok
(
body
));
...
...
custom-server-webapp/src/main/java/com/jomalls/custom/webapp/controller/CustomProductInfoController.java
View file @
c6bf40e2
package
com
.
jomalls
.
custom
.
webapp
.
controller
;
import
com.baomidou.mybatisplus.core.metadata.IPage
;
import
com.jomalls.custom.app.dto.AddBlackListDTO
;
import
com.jomalls.custom.app.dto.BindDiyUserDTO
;
import
com.jomalls.custom.app.dto.CustomProductInfoSnakeDTO
;
import
com.jomalls.custom.app.dto.CustomProductInfoUpdateSnakeDTO
;
import
com.jomalls.custom.app.dto.*
;
import
com.jomalls.custom.app.enums.CustomProductInfoStatusEnum
;
import
com.jomalls.custom.app.service.CustomProductInfoService
;
import
com.jomalls.custom.app.vo.CustomProductInfoPageSnakeVO
;
import
com.jomalls.custom.app.vo.CustomProductInfoSnakeVO
;
import
com.jomalls.custom.app.vo.CustomProductInfoVO
;
import
com.jomalls.custom.app.vo.CraftCenterSnakeVO
;
import
com.jomalls.custom.app.vo.DbDiySnakeVO
;
import
io.swagger.v3.oas.annotations.Operation
;
...
...
@@ -32,7 +29,7 @@ import java.util.Map;
@Slf4j
@RestController
@Tag
(
name
=
"定制商品管理"
,
description
=
"定制商品管理接口"
)
@RequestMapping
(
"/api/v
2
/product/info"
)
@RequestMapping
(
"/api/v
3
/product/info"
)
@RequiredArgsConstructor
public
class
CustomProductInfoController
{
...
...
@@ -40,7 +37,7 @@ public class CustomProductInfoController {
@Operation
(
summary
=
"创建商品"
,
description
=
"创建商品"
)
@PostMapping
(
"/create"
)
public
void
create
(
@RequestBody
@Valid
CustomProductInfoSnakeDTO
dto
)
{
public
void
create
(
@RequestBody
@Valid
CustomProductInfoS
aveS
nakeDTO
dto
)
{
customProductInfoService
.
saveFull
(
dto
);
}
...
...
@@ -61,7 +58,7 @@ public class CustomProductInfoController {
@Operation
(
summary
=
"分页列表接口"
,
description
=
"根据条件查询分页列表接口"
)
@RequestMapping
(
value
=
"/page"
,
method
=
RequestMethod
.
POST
)
public
IPage
<
CustomProductInfo
SnakeVO
>
pageList
(
@RequestBody
CustomProductInfo
SnakeDTO
param
)
{
public
IPage
<
CustomProductInfo
PageSnakeVO
>
pageList
(
@RequestBody
CustomProductInfoQuery
SnakeDTO
param
)
{
return
customProductInfoService
.
pageList
(
param
);
}
...
...
@@ -119,7 +116,7 @@ public class CustomProductInfoController {
@Operation
(
summary
=
"ERP 分页查询"
,
description
=
"包含黑名单过滤、用户折扣等 ERP 特定逻辑"
)
@PostMapping
(
"/erpPage"
)
public
IPage
<
CustomProductInfo
VO
>
erpPage
(
@RequestBody
CustomProductInfo
SnakeDTO
param
)
{
public
IPage
<
CustomProductInfo
PageSnakeVO
>
erpPage
(
@RequestBody
CustomProductInfoQuery
SnakeDTO
param
)
{
return
customProductInfoService
.
erpPage
(
param
);
}
...
...
custom-server-webapp/src/main/java/com/jomalls/custom/webapp/controller/CustomProductItemController.java
View file @
c6bf40e2
...
...
@@ -25,7 +25,7 @@ import java.util.List;
@Slf4j
@RestController
@Tag
(
name
=
"定制商品明细"
,
description
=
"定制商品明细接口"
)
@RequestMapping
(
"/api/v
2
/product/item"
)
@RequestMapping
(
"/api/v
3
/product/item"
)
@RequiredArgsConstructor
public
class
CustomProductItemController
{
...
...
custom-server-webapp/src/main/java/com/jomalls/custom/webapp/controller/CustomWarehouseInfoController.java
View file @
c6bf40e2
...
...
@@ -3,7 +3,7 @@ package com.jomalls.custom.webapp.controller;
import
com.baomidou.mybatisplus.core.metadata.IPage
;
import
com.jomalls.custom.app.service.CustomWarehouseInfoService
;
import
com.jomalls.custom.app.vo.CustomWarehouseInfoPageVO
;
import
com.jomalls.custom.app.vo.CustomWarehouseInfoVO
;
import
com.jomalls.custom.app.vo.CustomWarehouseInfo
Snake
VO
;
import
io.swagger.v3.oas.annotations.Operation
;
import
io.swagger.v3.oas.annotations.Parameter
;
import
io.swagger.v3.oas.annotations.tags.Tag
;
...
...
@@ -33,13 +33,13 @@ public class CustomWarehouseInfoController {
/**
* 列表查询接口
*
* @param customWarehouseInfoVO 条件model
* @param customWarehouseInfo
Snake
VO 条件model
* @return list集合
*/
@Operation
(
summary
=
"列表查询接口"
,
description
=
"根据条件查询列表接口(不分页)"
)
@RequestMapping
(
value
=
"/list"
,
method
=
RequestMethod
.
POST
)
public
List
<
CustomWarehouseInfo
VO
>
list
(
@RequestBody
CustomWarehouseInfoVO
customWarehouseInfo
VO
)
{
return
customWarehouseInfoService
.
list
(
customWarehouseInfoVO
);
public
List
<
CustomWarehouseInfo
SnakeVO
>
list
(
@RequestBody
CustomWarehouseInfoSnakeVO
customWarehouseInfoSnake
VO
)
{
return
customWarehouseInfoService
.
list
(
customWarehouseInfo
Snake
VO
);
}
/**
...
...
@@ -50,7 +50,7 @@ public class CustomWarehouseInfoController {
*/
@Operation
(
summary
=
"分页列表接口"
,
description
=
"根据条件查询分页列表接口"
)
@RequestMapping
(
value
=
"/pageList"
,
method
=
RequestMethod
.
POST
)
public
IPage
<
CustomWarehouseInfoVO
>
pageList
(
@RequestBody
CustomWarehouseInfoPageVO
customWarehouseInfoPageVO
)
{
public
IPage
<
CustomWarehouseInfo
Snake
VO
>
pageList
(
@RequestBody
CustomWarehouseInfoPageVO
customWarehouseInfoPageVO
)
{
return
customWarehouseInfoService
.
pageList
(
customWarehouseInfoPageVO
);
}
...
...
@@ -63,31 +63,31 @@ public class CustomWarehouseInfoController {
*/
@Operation
(
summary
=
"根据主键id查询详情"
,
description
=
"根据主键id查询详情"
)
@RequestMapping
(
value
=
"/info/{id}"
,
method
=
RequestMethod
.
GET
)
public
CustomWarehouseInfoVO
info
(
@Parameter
(
description
=
"主键id"
,
required
=
true
)
@PathVariable
(
"id"
)
Long
id
)
{
public
CustomWarehouseInfo
Snake
VO
info
(
@Parameter
(
description
=
"主键id"
,
required
=
true
)
@PathVariable
(
"id"
)
Long
id
)
{
return
customWarehouseInfoService
.
info
(
id
);
}
/**
* 保存对象
*
* @param customWarehouseInfoVO 保存对象
* @param customWarehouseInfo
Snake
VO 保存对象
*/
@Operation
(
summary
=
"保存对象"
,
description
=
"保存对象"
)
@RequestMapping
(
value
=
"/save"
,
method
=
RequestMethod
.
POST
)
public
void
save
(
@RequestBody
@Valid
CustomWarehouseInfo
VO
customWarehouseInfo
VO
)
{
customWarehouseInfoService
.
save
(
customWarehouseInfoVO
);
public
void
save
(
@RequestBody
@Valid
CustomWarehouseInfo
SnakeVO
customWarehouseInfoSnake
VO
)
{
customWarehouseInfoService
.
save
(
customWarehouseInfo
Snake
VO
);
}
/**
* 根据id修改对象
*
* @param customWarehouseInfoVO 修改对象
* @param customWarehouseInfo
Snake
VO 修改对象
*/
@Operation
(
summary
=
"根据id修改对象"
,
description
=
"根据id修改对象"
)
@RequestMapping
(
value
=
"/updateById"
,
method
=
RequestMethod
.
PUT
)
public
void
updateById
(
@RequestBody
CustomWarehouseInfo
VO
customWarehouseInfo
VO
)
{
customWarehouseInfoService
.
updateById
(
customWarehouseInfoVO
);
public
void
updateById
(
@RequestBody
CustomWarehouseInfo
SnakeVO
customWarehouseInfoSnake
VO
)
{
customWarehouseInfoService
.
updateById
(
customWarehouseInfo
Snake
VO
);
}
/**
...
...
custom-server-webapp/src/main/java/com/jomalls/custom/webapp/controller/HealthController.java
View file @
c6bf40e2
...
...
@@ -2,7 +2,10 @@ package com.jomalls.custom.webapp.controller;
import
com.jomalls.custom.app.constant.Constants
;
import
io.swagger.v3.oas.annotations.Operation
;
import
io.swagger.v3.oas.annotations.tags.Tag
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.web.bind.annotation.GetMapping
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
import
java.util.HashMap
;
...
...
@@ -14,6 +17,9 @@ import java.util.Map;
* @Description: 心跳检测接口
* @Version: 1.0
*/
@Slf4j
@Tag
(
name
=
"服务健康检查"
,
description
=
"服务健康检查"
)
@RequestMapping
(
"/actuator"
)
@RestController
public
class
HealthController
{
/**
...
...
@@ -29,7 +35,7 @@ public class HealthController {
* 健康检查接口,返回UP状态
*/
@Operation
(
summary
=
"健康检测接口"
,
description
=
"健康检测接口"
)
@GetMapping
(
value
=
"/
actuator/
health"
)
@GetMapping
(
value
=
"/health"
)
public
Map
<
String
,
String
>
check
()
{
Map
<
String
,
String
>
map
=
new
HashMap
<>(
Constants
.
DEFAULT_INITIAL_CAPACITY
);
map
.
put
(
HEALTH_STATUS_KEY
,
HEALTH_STATUS_UP
);
...
...
custom-server-webapp/src/main/java/com/jomalls/custom/webapp/controller/LogCustomProductController.java
View file @
c6bf40e2
...
...
@@ -24,7 +24,7 @@ import java.util.List;
@Slf4j
@RestController
@Tag
(
name
=
"商品日志管理"
,
description
=
"商品日志管理接口"
)
@RequestMapping
(
"/api/v
2
/product/log"
)
@RequestMapping
(
"/api/v
3
/product/log"
)
@RequiredArgsConstructor
public
class
LogCustomProductController
{
...
...
custom-server-webapp/src/main/java/com/jomalls/custom/webapp/controller/SysBillRuleController.java
View file @
c6bf40e2
...
...
@@ -22,7 +22,7 @@ import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
@Tag
(
name
=
"SKU编号生成"
,
description
=
"生成产品SKU编号"
)
@RequestMapping
(
"/api/v
2
/product/homesku"
)
@RequestMapping
(
"/api/v
3
/product/homesku"
)
@RequiredArgsConstructor
public
class
SysBillRuleController
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment