Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
Y
yd-product
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
xingmin
yd-product
Commits
1ced84b5
Commit
1ced84b5
authored
May 19, 2026
by
zhangxingmin
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/dev' into prod
parents
a739b13e
d4994eaa
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
190 additions
and
335 deletions
+190
-335
yd-product-api/src/main/java/com/yd/product/api/service/impl/ApiAnnouncementCommissionRatioServiceImpl.java
+92
-214
yd-product-api/src/main/java/com/yd/product/api/service/impl/ApiExpectedCommissionRatioServiceImpl.java
+98
-121
No files found.
yd-product-api/src/main/java/com/yd/product/api/service/impl/ApiAnnouncementCommissionRatioServiceImpl.java
View file @
1ced84b5
...
...
@@ -25,6 +25,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import
org.springframework.stereotype.Service
;
import
org.springframework.util.CollectionUtils
;
import
java.time.LocalDateTime
;
import
java.time.format.DateTimeFormatter
;
import
java.util.*
;
import
java.util.stream.Collectors
;
...
...
@@ -41,10 +43,10 @@ public class ApiAnnouncementCommissionRatioServiceImpl implements ApiAnnouncemen
@Autowired
private
ApiAnnouncementSpeciesService
apiAnnouncementSpeciesService
;
private
static
final
DateTimeFormatter
DATE_FORMATTER
=
DateTimeFormatter
.
ofPattern
(
"yyyy-MM-dd"
);
/**
* 分页列表查询-公告佣比率规格明细信息
* @param request
* @return
*/
@Override
public
Result
<
IPage
<
ApiAnnouncementCommissionRatioPageResponse
>>
page
(
ApiAnnouncementCommissionRatioPageRequest
request
)
{
...
...
@@ -55,8 +57,6 @@ public class ApiAnnouncementCommissionRatioServiceImpl implements ApiAnnouncemen
/**
* 列表查询-条件查询-公告佣比率规格明细信息列表
* @param request
* @return
*/
@Override
public
Result
<
List
<
ApiAnnouncementCommissionRatioListResponse
>>
list
(
ApiAnnouncementCommissionRatioListRequest
request
)
{
...
...
@@ -71,8 +71,6 @@ public class ApiAnnouncementCommissionRatioServiceImpl implements ApiAnnouncemen
/**
* 批量保存-公告佣比率规格明细信息
* @param request
* @return
*/
@Override
public
Result
batchSave
(
ApiAnnouncementCommissionRatioBatchSaveRequest
request
)
{
...
...
@@ -88,7 +86,7 @@ public class ApiAnnouncementCommissionRatioServiceImpl implements ApiAnnouncemen
.
stream
()
.
map
(
dto
->
{
AnnouncementCommissionRatio
ratio
=
new
AnnouncementCommissionRatio
();
BeanUtils
.
copyProperties
(
dto
,
ratio
);
BeanUtils
.
copyProperties
(
dto
,
ratio
);
ratio
.
setAnnouncementSpeciesBizId
(
request
.
getAnnouncementSpeciesBizId
());
ratio
.
setAnnouncementCommissionRatioBizId
(
RandomStringGenerator
.
generateBizId16
(
CommonEnum
.
UID_TYPE_ANNOUNCEMENT_COMMISSION_RATIO
.
getCode
()));
return
ratio
;
...
...
@@ -100,8 +98,6 @@ public class ApiAnnouncementCommissionRatioServiceImpl implements ApiAnnouncemen
/**
* 添加-公告佣比率规格明细信息
* @param request
* @return
*/
@Override
public
Result
add
(
ApiAnnouncementCommissionRatioAddRequest
request
)
{
...
...
@@ -110,7 +106,7 @@ public class ApiAnnouncementCommissionRatioServiceImpl implements ApiAnnouncemen
//入参校验,佣金年限校验不同条件下的唯一性 TODO
//新增
AnnouncementCommissionRatio
ratio
=
new
AnnouncementCommissionRatio
();
BeanUtils
.
copyProperties
(
request
,
ratio
);
BeanUtils
.
copyProperties
(
request
,
ratio
);
ratio
.
setAnnouncementCommissionRatioBizId
(
RandomStringGenerator
.
generateBizId16
(
CommonEnum
.
UID_TYPE_ANNOUNCEMENT_COMMISSION_RATIO
.
getCode
()));
iAnnouncementCommissionRatioService
.
saveOrUpdate
(
ratio
);
return
Result
.
success
();
...
...
@@ -118,8 +114,6 @@ public class ApiAnnouncementCommissionRatioServiceImpl implements ApiAnnouncemen
/**
* 编辑-公告佣比率规格明细信息
* @param request
* @return
*/
@Override
public
Result
edit
(
ApiAnnouncementCommissionRatioEditRequest
request
)
{
...
...
@@ -130,16 +124,13 @@ public class ApiAnnouncementCommissionRatioServiceImpl implements ApiAnnouncemen
apiAnnouncementSpeciesService
.
checkAnnouncementSpeciesIsExist
(
request
.
getAnnouncementSpeciesBizId
());
//入参校验,佣金年限校验不同条件下的唯一性 TODO
//新增
BeanUtils
.
copyProperties
(
request
,
ratio
);
BeanUtils
.
copyProperties
(
request
,
ratio
);
iAnnouncementCommissionRatioService
.
saveOrUpdate
(
ratio
);
return
Result
.
success
();
}
/**
* 编辑-状态
* @param announcementCommissionRatioBizId
* @param status
* @return
*/
@Override
public
Result
editStatus
(
String
announcementCommissionRatioBizId
,
Integer
status
)
{
...
...
@@ -153,8 +144,6 @@ public class ApiAnnouncementCommissionRatioServiceImpl implements ApiAnnouncemen
/**
* 详情-公告佣比率规格明细信息
* @param announcementCommissionRatioBizId 公告佣比率规格明细表唯一业务ID
* @return
*/
@Override
public
Result
<
ApiAnnouncementCommissionRatioDetailResponse
>
detail
(
String
announcementCommissionRatioBizId
)
{
...
...
@@ -162,14 +151,12 @@ public class ApiAnnouncementCommissionRatioServiceImpl implements ApiAnnouncemen
Result
<
AnnouncementCommissionRatio
>
result
=
checkAnnouncementCommissionRatioIsExist
(
announcementCommissionRatioBizId
);
AnnouncementCommissionRatio
announcementCommissionRatio
=
result
.
getData
();
ApiAnnouncementCommissionRatioDetailResponse
response
=
new
ApiAnnouncementCommissionRatioDetailResponse
();
BeanUtils
.
copyProperties
(
announcementCommissionRatio
,
response
);
BeanUtils
.
copyProperties
(
announcementCommissionRatio
,
response
);
return
Result
.
success
(
response
);
}
/**
* 删除-公告佣比率规格明细信息
* @param announcementCommissionRatioBizId 公告佣比率规格明细表唯一业务ID
* @return
*/
@Override
public
Result
del
(
String
announcementCommissionRatioBizId
)
{
...
...
@@ -182,8 +169,6 @@ public class ApiAnnouncementCommissionRatioServiceImpl implements ApiAnnouncemen
/**
* 复制-公告佣比率规格明细信息
* @param announcementCommissionRatioBizId 公告佣比率规格明细表唯一业务ID
* @return
*/
@Override
public
Result
copy
(
String
announcementCommissionRatioBizId
)
{
...
...
@@ -198,13 +183,11 @@ public class ApiAnnouncementCommissionRatioServiceImpl implements ApiAnnouncemen
/**
* 根据条件查询是否有公告佣比率规格明细信息数据
* @param productLaunchBizId 产品上架信息表唯一业务ID不
* @return
*/
@Override
public
Result
<
Boolean
>
isData
(
String
productLaunchBizId
)
{
List
<
AnnouncementSpecies
>
speciesList
=
iAnnouncementSpeciesService
.
queryList
(
productLaunchBizId
);
if
(
CollectionUtils
.
isEmpty
(
speciesList
)){
if
(
CollectionUtils
.
isEmpty
(
speciesList
))
{
return
Result
.
success
(
false
);
}
List
<
String
>
announcementSpeciesBizIdList
=
speciesList
.
stream
().
map
(
AnnouncementSpecies:
:
getAnnouncementSpeciesBizId
).
collect
(
Collectors
.
toList
());
...
...
@@ -217,8 +200,6 @@ public class ApiAnnouncementCommissionRatioServiceImpl implements ApiAnnouncemen
/**
* 校验公告佣比率规格明细信息是否存在
* @param announcementCommissionRatioBizId
* @return
*/
@Override
public
Result
<
AnnouncementCommissionRatio
>
checkAnnouncementCommissionRatioIsExist
(
String
announcementCommissionRatioBizId
)
{
...
...
@@ -231,30 +212,45 @@ public class ApiAnnouncementCommissionRatioServiceImpl implements ApiAnnouncemen
}
/**
* 校验入参-公告佣比率规格明细列表
* @param ratioBatchSaveDtoList
* @return
* 校验入参-公告佣比率规格明细列表(年限区间重叠 且 有效时间区间重叠 时禁止)
*/
public
Result
checkBatchSaveRequestPram
(
List
<
ApiAnnouncementCommissionRatioBatchSaveDto
>
ratioBatchSaveDtoList
)
{
// 1. 验证并准备数据
// 1. 准备解析后的数据
List
<
DtoWithParsedData
>
preparedDataList
=
prepareData
(
ratioBatchSaveDtoList
);
// 2. 检查所有数据对的年限重叠情况(考虑scope交集)
List
<
OverlapError
>
errors
=
checkAllDataPairs
(
preparedDataList
);
// 2. 检查年限重叠且有效时间重叠的冲突(业务字段相同 + scope有交集才视为同一分组)
List
<
OverlapError
>
errors
=
new
ArrayList
<>();
int
n
=
preparedDataList
.
size
();
// 3. 如果有错误,返回错误信息
for
(
int
i
=
0
;
i
<
n
-
1
;
i
++)
{
DtoWithParsedData
data1
=
preparedDataList
.
get
(
i
);
for
(
int
j
=
i
+
1
;
j
<
n
;
j
++)
{
DtoWithParsedData
data2
=
preparedDataList
.
get
(
j
);
// 分组条件:费用名称、是否受汇率影响、币种相同,且scope有交集
if
(
isSameBusinessAndScopeIntersect
(
data1
,
data2
))
{
boolean
yearOverlap
=
ProductCommonUtils
.
isYearRangeOverlap
(
data1
.
startYear
,
data1
.
endYear
,
data2
.
startYear
,
data2
.
endYear
);
boolean
timeOverlap
=
isTimeRangeOverlap
(
data1
.
effectiveStart
,
data1
.
effectiveEnd
,
data2
.
effectiveStart
,
data2
.
effectiveEnd
);
if
(
yearOverlap
&&
timeOverlap
)
{
if
(!
isErrorAlreadyExists
(
errors
,
data1
.
originalIndex
,
data2
.
originalIndex
,
"CONFLICT"
))
{
errors
.
add
(
new
OverlapError
(
data1
.
originalIndex
,
data2
.
originalIndex
,
"CONFLICT"
));
}
}
}
}
}
// 3. 有冲突则抛出异常
if
(!
errors
.
isEmpty
())
{
String
errorMsg
=
buildErrorMessage
(
errors
,
ratioBatchSaveDtoList
);
throw
new
BusinessException
(
1004
,
errorMsg
);
String
errorMsg
=
build
Conflict
ErrorMessage
(
errors
,
ratioBatchSaveDtoList
);
throw
new
BusinessException
(
1004
,
errorMsg
);
}
return
Result
.
success
();
}
/**
* 准备数据:解析年限并将scope转换为集合
* @param dtoList
* @return
* 准备数据:解析年限、有效时间、scope,并校验基本合法性
*/
private
List
<
DtoWithParsedData
>
prepareData
(
List
<
ApiAnnouncementCommissionRatioBatchSaveDto
>
dtoList
)
{
List
<
DtoWithParsedData
>
preparedList
=
new
ArrayList
<>();
...
...
@@ -267,201 +263,79 @@ public class ApiAnnouncementCommissionRatioServiceImpl implements ApiAnnouncemen
Integer
endYear
=
ProductCommonUtils
.
parseYearToInt
(
dto
.
getEndPeriod
());
if
(
startYear
>
endYear
)
{
throw
new
BusinessException
(
"第"
+
(
i
+
1
)
+
"条数据的起始年限["
+
startYear
+
"]不能大于结束年限["
+
endYear
+
"]"
);
throw
new
BusinessException
(
"第"
+
(
i
+
1
)
+
"条数据的起始年限["
+
startYear
+
"]不能大于结束年限["
+
endYear
+
"]"
);
}
// 校验有效时间起止顺序
if
(
dto
.
getEffectiveStart
().
isAfter
(
dto
.
getEffectiveEnd
()))
{
throw
new
BusinessException
(
"第"
+
(
i
+
1
)
+
"条数据的有效开始时间不能晚于有效结束时间"
);
}
// 解析scope为集合
,
去重
// 解析scope为集合
,
去重
Set
<
String
>
scopeSet
=
ProductCommonUtils
.
parseScopeToSet
(
dto
.
getScope
());
preparedList
.
add
(
new
DtoWithParsedData
(
i
,
dto
,
startYear
,
endYear
,
scopeSet
));
preparedList
.
add
(
new
DtoWithParsedData
(
i
,
dto
,
startYear
,
endYear
,
scopeSet
,
dto
.
getEffectiveStart
(),
dto
.
getEffectiveEnd
()));
}
return
preparedList
;
}
/**
* 检查所有数据对的年限重叠情况
*/
private
List
<
OverlapError
>
checkAllDataPairs
(
List
<
DtoWithParsedData
>
preparedDataList
)
{
List
<
OverlapError
>
errors
=
new
ArrayList
<>();
int
n
=
preparedDataList
.
size
();
// 使用双重循环检查所有数据对
for
(
int
i
=
0
;
i
<
n
-
1
;
i
++)
{
DtoWithParsedData
data1
=
preparedDataList
.
get
(
i
);
for
(
int
j
=
i
+
1
;
j
<
n
;
j
++)
{
DtoWithParsedData
data2
=
preparedDataList
.
get
(
j
);
// 检查是否属于同一分组条件(考虑scope交集)
if
(
isSameGroup
(
data1
,
data2
))
{
// 检查年限是否重叠
if
(
ProductCommonUtils
.
isYearRangeOverlap
(
data1
.
startYear
,
data1
.
endYear
,
data2
.
startYear
,
data2
.
endYear
))
{
// 避免重复添加相同的错误
if
(!
isErrorAlreadyExists
(
errors
,
data1
.
originalIndex
,
data2
.
originalIndex
))
{
errors
.
add
(
new
OverlapError
(
data1
.
originalIndex
,
data2
.
originalIndex
));
}
}
}
}
}
return
errors
;
}
/**
* 判断两个数据是否属于同一分组条件
* 判断两个有效时间区间是否重叠
*/
private
boolean
isSameGroup
(
DtoWithParsedData
data1
,
DtoWithParsedData
data2
)
{
// 1. 检查除scope外的其他条件是否相同
if
(!
isSameGroupExceptScope
(
data1
.
dto
,
data2
.
dto
))
{
return
false
;
}
// 2. 检查scope是否有交集
return
ProductCommonUtils
.
hasScopeIntersection
(
data1
.
scopeSet
,
data2
.
scopeSet
);
private
boolean
isTimeRangeOverlap
(
LocalDateTime
start1
,
LocalDateTime
end1
,
LocalDateTime
start2
,
LocalDateTime
end2
)
{
return
!(
end1
.
isBefore
(
start2
)
||
end2
.
isBefore
(
start1
));
}
/**
*
检查除scope外的其他条件是否相同
*
同一业务分组判断:费用名称、是否受汇率影响、币种相同,且scope有交集(忽略有效时间)
*/
private
boolean
isSameGroupExceptScope
(
ApiAnnouncementCommissionRatioBatchSaveDto
dto1
,
ApiAnnouncementCommissionRatioBatchSaveDto
dto2
)
{
private
boolean
isSameBusinessAndScopeIntersect
(
DtoWithParsedData
data1
,
DtoWithParsedData
data2
)
{
ApiAnnouncementCommissionRatioBatchSaveDto
dto1
=
data1
.
dto
;
ApiAnnouncementCommissionRatioBatchSaveDto
dto2
=
data2
.
dto
;
return
Objects
.
equals
(
dto1
.
getExpenseName
(),
dto2
.
getExpenseName
())
&&
Objects
.
equals
(
dto1
.
getEffectiveStart
(),
dto2
.
getEffectiveStart
())
&&
Objects
.
equals
(
dto1
.
getEffectiveEnd
(),
dto2
.
getEffectiveEnd
())
&&
Objects
.
equals
(
dto1
.
getIsExchangeRate
(),
dto2
.
getIsExchangeRate
())
&&
Objects
.
equals
(
dto1
.
getCurrency
(),
dto2
.
getCurrency
());
&&
Objects
.
equals
(
dto1
.
getCurrency
(),
dto2
.
getCurrency
())
&&
ProductCommonUtils
.
hasScopeIntersection
(
data1
.
scopeSet
,
data2
.
scopeSet
);
}
/**
*
校验基础字段
*
检查冲突是否已记录(去重)
*/
private
boolean
validateBasicFields
(
ApiAnnouncementCommissionRatioBatchSaveDto
dto
)
{
return
dto
.
getExpenseName
()
!=
null
&&
!
dto
.
getExpenseName
().
trim
().
isEmpty
()
&&
dto
.
getEffectiveStart
()
!=
null
&&
dto
.
getEffectiveEnd
()
!=
null
&&
dto
.
getEffectiveStart
().
isBefore
(
dto
.
getEffectiveEnd
())
&&
dto
.
getScope
()
!=
null
&&
!
dto
.
getScope
().
trim
().
isEmpty
()
&&
dto
.
getIsExchangeRate
()
!=
null
&&
!
dto
.
getIsExchangeRate
().
trim
().
isEmpty
()
&&
dto
.
getCurrency
()
!=
null
&&
!
dto
.
getCurrency
().
trim
().
isEmpty
();
}
/**
* 检查错误是否已存在
*/
private
boolean
isErrorAlreadyExists
(
List
<
OverlapError
>
errors
,
int
index1
,
int
index2
)
{
private
boolean
isErrorAlreadyExists
(
List
<
OverlapError
>
errors
,
int
index1
,
int
index2
,
String
type
)
{
for
(
OverlapError
error
:
errors
)
{
if
((
error
.
index1
==
index1
&&
error
.
index2
==
index2
)
||
(
error
.
index1
==
index2
&&
error
.
index2
==
index1
))
{
if
(((
error
.
index1
==
index1
&&
error
.
index2
==
index2
)
||
(
error
.
index1
==
index2
&&
error
.
index2
==
index1
))
&&
error
.
type
.
equals
(
type
))
{
return
true
;
}
}
return
false
;
}
// /**
// * 构建错误消息
// */
// private String buildErrorMessage(List<OverlapError> errors,
// List<ApiAnnouncementCommissionRatioBatchSaveDto> originalList) {
// if (errors.isEmpty()) {
// return "未发现重叠数据";
// }
//
// StringBuilder sb = new StringBuilder();
//
// Set<Integer> set = new HashSet<>();
// if (!CollectionUtils.isEmpty(errors)) {
// errors.stream().forEach(dto -> {
// set.add(dto.getIndex1());
// set.add(dto.getIndex2());
// });
// }
//
// sb.append("发现佣金年限区间重叠的数据,请检查以下行数:\n\n");
//
// // 将行数(索引+1,因为用户从1开始计数)排序并格式化为"第X行"
// String rowNumbers = set.stream()
// .sorted()
// .map(index -> "第" + (index + 1) + "行")
// .collect(Collectors.joining(",")); // 用中文逗号分隔
//
// sb.append(rowNumbers);
//
// return sb.toString();
// }
/**
* 构建
错误消
息
* 构建
合并后的冲突错误信
息
*/
private
String
buildErrorMessage
(
List
<
OverlapError
>
errors
,
List
<
ApiAnnouncementCommissionRatioBatchSaveDto
>
originalList
)
{
private
String
build
Conflict
ErrorMessage
(
List
<
OverlapError
>
errors
,
List
<
ApiAnnouncementCommissionRatioBatchSaveDto
>
originalList
)
{
if
(
errors
.
isEmpty
())
{
return
"未发现
重叠
数据"
;
return
"未发现
冲突
数据"
;
}
StringBuilder
sb
=
new
StringBuilder
();
// Set<Integer> set = new HashSet<>();
// if (!CollectionUtils.isEmpty(errors)) {
// errors.stream().forEach(dto -> {
// set.add(dto.getIndex1());
// set.add(dto.getIndex2());
// });
// }
sb
.
append
(
"发现佣金年限区间重叠的数据,请检查以下数据:\n\n"
);
// sb.append("发现佣金年限区间重叠的数据,请检查以下行数:\n\n");
// sb.append(String.join("",set))
// // 按数据索引分组,方便查看每条数据的所有重叠关系
Map
<
Integer
,
List
<
Integer
>>
overlapMap
=
new
TreeMap
<>();
StringBuilder
sb
=
new
StringBuilder
(
"发现年限区间重叠且有效时间区间重叠的数据:\n"
);
for
(
OverlapError
error
:
errors
)
{
overlapMap
.
computeIfAbsent
(
error
.
index1
,
k
->
new
ArrayList
<>()).
add
(
error
.
index2
);
overlapMap
.
computeIfAbsent
(
error
.
index2
,
k
->
new
ArrayList
<>()).
add
(
error
.
index1
);
}
// 构建错误信息
for
(
Map
.
Entry
<
Integer
,
List
<
Integer
>>
entry
:
overlapMap
.
entrySet
())
{
int
dataIndex
=
entry
.
getKey
();
List
<
Integer
>
overlapIndices
=
entry
.
getValue
();
ApiAnnouncementCommissionRatioBatchSaveDto
dto
=
originalList
.
get
(
dataIndex
);
sb
.
append
(
"第"
).
append
(
dataIndex
+
1
).
append
(
"行数据年限区间"
)
// .append(" - 费用名称: ").append(dto.getExpenseName()).append("\n")
// .append(" - 年限区间: ").append(dto.getStartPeriod()).append(" 至 ").append(dto.getEndPeriod()).append("\n")
// .append(" - 适用范围: ").append(dto.getScope()).append("\n")
// .append(" - 有效时间: ").append(dto.getEffectiveStart()).append(" 至 ").append(dto.getEffectiveEnd()).append("\n")
// .append(" - 汇率影响: ").append(dto.getIsExchangeRate()).append("\n")
// .append(" - 结算币种: ").append(dto.getCurrency()).append("\n")
.
append
(
"与以下数据年限区间有重叠:"
);
for
(
int
overlapIndex
:
overlapIndices
)
{
ApiAnnouncementCommissionRatioBatchSaveDto
overlapDto
=
originalList
.
get
(
overlapIndex
);
sb
.
append
(
" 第"
).
append
(
overlapIndex
+
1
).
append
(
"行"
);
// .append(overlapDto.getExpenseName())
// .append(" [").append(overlapDto.getStartPeriod())
// .append("-").append(overlapDto.getEndPeriod()).append("]")
// .append(" 适用范围:").append(overlapDto.getScope()).append("\n");
}
sb
.
append
(
"\n"
);
int
i
=
error
.
index1
;
int
j
=
error
.
index2
;
ApiAnnouncementCommissionRatioBatchSaveDto
dto1
=
originalList
.
get
(
i
);
ApiAnnouncementCommissionRatioBatchSaveDto
dto2
=
originalList
.
get
(
j
);
sb
.
append
(
"第"
).
append
(
i
+
1
).
append
(
"行(年限 "
).
append
(
dto1
.
getStartPeriod
()).
append
(
"~"
).
append
(
dto1
.
getEndPeriod
())
.
append
(
",有效 "
).
append
(
dto1
.
getEffectiveStart
().
format
(
DATE_FORMATTER
)).
append
(
"~"
).
append
(
dto1
.
getEffectiveEnd
().
format
(
DATE_FORMATTER
))
.
append
(
")与第"
).
append
(
j
+
1
).
append
(
"行(年限 "
).
append
(
dto2
.
getStartPeriod
()).
append
(
"~"
).
append
(
dto2
.
getEndPeriod
())
.
append
(
",有效 "
).
append
(
dto2
.
getEffectiveStart
().
format
(
DATE_FORMATTER
)).
append
(
"~"
).
append
(
dto2
.
getEffectiveEnd
().
format
(
DATE_FORMATTER
))
.
append
(
")冲突\n"
);
}
// 添加通用分组条件说明
// sb.append("重叠判断规则说明:\n");
// sb.append("1. 以下条件完全相同的数据才会被比较:\n");
// sb.append(" - 费用名称\n");
// sb.append(" - 有效开始时间\n");
// sb.append(" - 有效结束时间\n");
// sb.append(" - 是否受汇率影响\n");
// sb.append(" - 结算币种\n");
// sb.append("2. 适用范围只要有一个相同的值(交集)就视为相同分组条件\n");
// sb.append("3. 年限区间重叠判断规则:\n");
// sb.append(" - 1-3 和 3-5: 算重叠(因为有共同的3)\n");
// sb.append(" - 1-3 和 4-7: 不算重叠\n");
// sb.append(" - 1-5 和 2-4: 算重叠\n");
return
sb
.
toString
();
}
...
...
@@ -469,36 +343,39 @@ public class ApiAnnouncementCommissionRatioServiceImpl implements ApiAnnouncemen
* 内部类:包含解析后数据的DTO
*/
private
static
class
DtoWithParsedData
{
final
int
originalIndex
;
// 在原始列表中的索引
final
ApiAnnouncementCommissionRatioBatchSaveDto
dto
;
// 原始DTO
final
int
startYear
;
// 解析后的起始年份
final
int
endYear
;
// 解析后的结束年份
final
Set
<
String
>
scopeSet
;
// 解析后的scope集合
final
int
originalIndex
;
final
ApiAnnouncementCommissionRatioBatchSaveDto
dto
;
final
int
startYear
;
final
int
endYear
;
final
Set
<
String
>
scopeSet
;
final
LocalDateTime
effectiveStart
;
final
LocalDateTime
effectiveEnd
;
public
DtoWithParsedData
(
int
originalIndex
,
ApiAnnouncementCommissionRatioBatchSaveDto
dto
,
int
startYear
,
int
endYear
,
Set
<
String
>
scopeSet
)
{
int
startYear
,
int
endYear
,
Set
<
String
>
scopeSet
,
LocalDateTime
effectiveStart
,
LocalDateTime
effectiveEnd
)
{
this
.
originalIndex
=
originalIndex
;
this
.
dto
=
dto
;
this
.
startYear
=
startYear
;
this
.
endYear
=
endYear
;
this
.
scopeSet
=
scopeSet
;
this
.
effectiveStart
=
effectiveStart
;
this
.
effectiveEnd
=
effectiveEnd
;
}
}
/**
* 内部类:重叠错误
* 内部类:重叠错误
(类型统一为"CONFLICT")
*/
private
static
class
OverlapError
{
private
final
int
index1
;
private
final
int
index2
;
private
final
String
type
;
public
OverlapError
(
int
index1
,
int
index2
)
{
public
OverlapError
(
int
index1
,
int
index2
,
String
type
)
{
this
.
index1
=
index1
;
this
.
index2
=
index2
;
this
.
type
=
type
;
}
public
int
getIndex1
()
{
return
index1
;
}
public
int
getIndex2
()
{
return
index2
;
}
}
}
}
\ No newline at end of file
yd-product-api/src/main/java/com/yd/product/api/service/impl/ApiExpectedCommissionRatioServiceImpl.java
View file @
1ced84b5
...
...
@@ -9,7 +9,7 @@ import com.yd.common.utils.RandomStringGenerator;
import
com.yd.product.api.service.ApiExpectedCommissionRatioService
;
import
com.yd.product.api.service.ApiExpectedSpeciesService
;
import
com.yd.product.api.utils.ProductCommonUtils
;
import
com.yd.product.feign.dto.Api
Expected
CommissionRatioBatchSaveDto
;
import
com.yd.product.feign.dto.Api
Announcement
CommissionRatioBatchSaveDto
;
import
com.yd.product.feign.dto.ApiExpectedCommissionRatioBatchSaveDto
;
import
com.yd.product.feign.request.expectedcommissionratio.ApiExpectedCommissionRatioAddRequest
;
import
com.yd.product.feign.request.expectedcommissionratio.ApiExpectedCommissionRatioBatchSaveRequest
;
...
...
@@ -17,7 +17,6 @@ import com.yd.product.feign.request.expectedcommissionratio.ApiExpectedCommissio
import
com.yd.product.feign.request.expectedcommissionratio.ApiExpectedCommissionRatioPageRequest
;
import
com.yd.product.feign.response.expectedcommissionratio.ApiExpectedCommissionRatioDetailResponse
;
import
com.yd.product.feign.response.expectedcommissionratio.ApiExpectedCommissionRatioPageResponse
;
import
com.yd.product.service.model.AnnouncementCommissionRatio
;
import
com.yd.product.service.model.ExpectedCommissionRatio
;
import
com.yd.product.service.service.IExpectedCommissionRatioService
;
import
lombok.extern.slf4j.Slf4j
;
...
...
@@ -26,6 +25,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import
org.springframework.stereotype.Service
;
import
org.springframework.util.CollectionUtils
;
import
java.time.LocalDateTime
;
import
java.time.format.DateTimeFormatter
;
import
java.util.*
;
import
java.util.stream.Collectors
;
...
...
@@ -39,6 +40,8 @@ public class ApiExpectedCommissionRatioServiceImpl implements ApiExpectedCommiss
@Autowired
private
ApiExpectedSpeciesService
apiExpectedSpeciesService
;
private
static
final
DateTimeFormatter
DATE_FORMATTER
=
DateTimeFormatter
.
ofPattern
(
"yyyy-MM-dd"
);
/**
* 分页列表查询-来佣比率规格明细信息
* @param request
...
...
@@ -70,7 +73,7 @@ public class ApiExpectedCommissionRatioServiceImpl implements ApiExpectedCommiss
.
stream
()
.
map
(
dto
->
{
ExpectedCommissionRatio
ratio
=
new
ExpectedCommissionRatio
();
BeanUtils
.
copyProperties
(
dto
,
ratio
);
BeanUtils
.
copyProperties
(
dto
,
ratio
);
ratio
.
setExpectedSpeciesBizId
(
request
.
getExpectedSpeciesBizId
());
ratio
.
setExpectedCommissionRatioBizId
(
RandomStringGenerator
.
generateBizId16
(
CommonEnum
.
UID_TYPE_EXPECTED_COMMISSION_RATIO
.
getCode
()));
return
ratio
;
...
...
@@ -92,7 +95,7 @@ public class ApiExpectedCommissionRatioServiceImpl implements ApiExpectedCommiss
//入参校验,佣金年限校验不同条件下的唯一性 TODO
//新增
ExpectedCommissionRatio
ratio
=
new
ExpectedCommissionRatio
();
BeanUtils
.
copyProperties
(
request
,
ratio
);
BeanUtils
.
copyProperties
(
request
,
ratio
);
ratio
.
setExpectedCommissionRatioBizId
(
RandomStringGenerator
.
generateBizId16
(
CommonEnum
.
UID_TYPE_EXPECTED_COMMISSION_RATIO
.
getCode
()));
iExpectedCommissionRatioService
.
saveOrUpdate
(
ratio
);
return
Result
.
success
();
...
...
@@ -112,7 +115,7 @@ public class ApiExpectedCommissionRatioServiceImpl implements ApiExpectedCommiss
apiExpectedSpeciesService
.
checkExpectedSpeciesIsExist
(
request
.
getExpectedSpeciesBizId
());
//入参校验,佣金年限校验不同条件下的唯一性 TODO
//编辑
BeanUtils
.
copyProperties
(
request
,
ratio
);
BeanUtils
.
copyProperties
(
request
,
ratio
);
iExpectedCommissionRatioService
.
saveOrUpdate
(
ratio
);
return
Result
.
success
();
}
...
...
@@ -144,7 +147,7 @@ public class ApiExpectedCommissionRatioServiceImpl implements ApiExpectedCommiss
Result
<
ExpectedCommissionRatio
>
result
=
checkExpectedCommissionRatioIsExist
(
expectedSpeciesBizId
);
ExpectedCommissionRatio
ratio
=
result
.
getData
();
ApiExpectedCommissionRatioDetailResponse
response
=
new
ApiExpectedCommissionRatioDetailResponse
();
BeanUtils
.
copyProperties
(
ratio
,
response
);
BeanUtils
.
copyProperties
(
ratio
,
response
);
return
Result
.
success
(
response
);
}
...
...
@@ -178,114 +181,103 @@ public class ApiExpectedCommissionRatioServiceImpl implements ApiExpectedCommiss
return
Result
.
success
();
}
/**
* 校验入参-来佣比率规格明细列表
* @param ratioBatchSaveDtoList
* @return
* 校验入参-来佣比率规格明细列表(年限区间和有效时间区间同时重叠时才禁止)
* 规则:
* - 分组条件:费用名称、是否受汇率影响、结算币种、对账公司、销售组织 完全一致
* - 同一分组内,年限重叠 且 有效时间重叠 → 报错
* - 年限不重叠则无论如何都通过
*/
public
Result
checkBatchSaveRequestPram
(
List
<
ApiExpectedCommissionRatioBatchSaveDto
>
ratioBatchSaveDtoList
)
{
// 1. 准备解析后的数据
List
<
DtoWithParsedData
>
preparedDataList
=
prepareData
(
ratioBatchSaveDtoList
);
// 1. 验证并准备数据
List
<
ApiExpectedCommissionRatioServiceImpl
.
DtoWithParsedData
>
preparedDataList
=
prepareData
(
ratioBatchSaveDtoList
);
// 2. 检查同一分组内年限重叠且有效时间重叠的冲突
List
<
OverlapError
>
errors
=
new
ArrayList
<>();
int
n
=
preparedDataList
.
size
();
// 2. 检查所有数据对的年限重叠情况
List
<
ApiExpectedCommissionRatioServiceImpl
.
OverlapError
>
errors
=
checkAllDataPairs
(
preparedDataList
);
for
(
int
i
=
0
;
i
<
n
-
1
;
i
++)
{
DtoWithParsedData
data1
=
preparedDataList
.
get
(
i
);
for
(
int
j
=
i
+
1
;
j
<
n
;
j
++)
{
DtoWithParsedData
data2
=
preparedDataList
.
get
(
j
);
if
(
isSameBusinessGroup
(
data1
.
dto
,
data2
.
dto
))
{
boolean
yearOverlap
=
ProductCommonUtils
.
isYearRangeOverlap
(
data1
.
startYear
,
data1
.
endYear
,
data2
.
startYear
,
data2
.
endYear
);
boolean
timeOverlap
=
isTimeRangeOverlap
(
data1
.
effectiveStart
,
data1
.
effectiveEnd
,
data2
.
effectiveStart
,
data2
.
effectiveEnd
);
if
(
yearOverlap
&&
timeOverlap
)
{
if
(!
isErrorAlreadyExists
(
errors
,
data1
.
originalIndex
,
data2
.
originalIndex
,
"CONFLICT"
))
{
errors
.
add
(
new
OverlapError
(
data1
.
originalIndex
,
data2
.
originalIndex
,
"CONFLICT"
));
}
}
}
}
}
// 3.
如果有错误,返回错误信息
// 3.
有冲突则抛出异常
if
(!
errors
.
isEmpty
())
{
String
errorMsg
=
buildErrorMessage
(
errors
,
ratioBatchSaveDtoList
);
throw
new
BusinessException
(
1004
,
errorMsg
);
String
errorMsg
=
build
Conflict
ErrorMessage
(
errors
,
ratioBatchSaveDtoList
);
throw
new
BusinessException
(
1004
,
errorMsg
);
}
return
Result
.
success
();
}
/**
* 准备数据:解析年限并转换为集合
* @param dtoList
* @return
* 准备数据:解析年限、有效时间,并校验基本合法性
*/
private
List
<
ApiExpectedCommissionRatioServiceImpl
.
DtoWithParsedData
>
prepareData
(
List
<
ApiExpectedCommissionRatioBatchSaveDto
>
dtoList
)
{
List
<
ApiExpectedCommissionRatioServiceImpl
.
DtoWithParsedData
>
preparedList
=
new
ArrayList
<>();
private
List
<
DtoWithParsedData
>
prepareData
(
List
<
ApiExpectedCommissionRatioBatchSaveDto
>
dtoList
)
{
List
<
DtoWithParsedData
>
preparedList
=
new
ArrayList
<>();
for
(
int
i
=
0
;
i
<
dtoList
.
size
();
i
++)
{
ApiExpectedCommissionRatioBatchSaveDto
dto
=
dtoList
.
get
(
i
);
// 解析年限
Integer
startYear
=
ProductCommonUtils
.
parseYearToInt
(
dto
.
getStartPeriod
());
Integer
endYear
=
ProductCommonUtils
.
parseYearToInt
(
dto
.
getEndPeriod
());
if
(
startYear
>
endYear
)
{
throw
new
BusinessException
(
"第"
+
(
i
+
1
)
+
"条数据的起始年限["
+
startYear
+
"]不能大于结束年限["
+
endYear
+
"]"
);
throw
new
BusinessException
(
"第"
+
(
i
+
1
)
+
"条数据的起始年限["
+
startYear
+
"]不能大于结束年限["
+
endYear
+
"]"
);
}
preparedList
.
add
(
new
ApiExpectedCommissionRatioServiceImpl
.
DtoWithParsedData
(
i
,
dto
,
startYear
,
endYear
));
}
return
preparedList
;
}
/**
* 检查所有数据对的年限重叠情况
*/
private
List
<
ApiExpectedCommissionRatioServiceImpl
.
OverlapError
>
checkAllDataPairs
(
List
<
ApiExpectedCommissionRatioServiceImpl
.
DtoWithParsedData
>
preparedDataList
)
{
List
<
ApiExpectedCommissionRatioServiceImpl
.
OverlapError
>
errors
=
new
ArrayList
<>();
int
n
=
preparedDataList
.
size
();
// 使用双重循环检查所有数据对
for
(
int
i
=
0
;
i
<
n
-
1
;
i
++)
{
ApiExpectedCommissionRatioServiceImpl
.
DtoWithParsedData
data1
=
preparedDataList
.
get
(
i
);
for
(
int
j
=
i
+
1
;
j
<
n
;
j
++)
{
ApiExpectedCommissionRatioServiceImpl
.
DtoWithParsedData
data2
=
preparedDataList
.
get
(
j
);
// 检查是否属于同一分组条件
if
(
isSameGroup
(
data1
,
data2
))
{
// 检查年限是否重叠
if
(
ProductCommonUtils
.
isYearRangeOverlap
(
data1
.
startYear
,
data1
.
endYear
,
data2
.
startYear
,
data2
.
endYear
))
{
// 避免重复添加相同的错误
if
(!
isErrorAlreadyExists
(
errors
,
data1
.
originalIndex
,
data2
.
originalIndex
))
{
errors
.
add
(
new
ApiExpectedCommissionRatioServiceImpl
.
OverlapError
(
data1
.
originalIndex
,
data2
.
originalIndex
));
}
}
}
if
(
dto
.
getEffectiveStart
().
isAfter
(
dto
.
getEffectiveEnd
()))
{
throw
new
BusinessException
(
"第"
+
(
i
+
1
)
+
"条数据的有效开始时间不能晚于有效结束时间"
);
}
preparedList
.
add
(
new
DtoWithParsedData
(
i
,
dto
,
startYear
,
endYear
,
dto
.
getEffectiveStart
(),
dto
.
getEffectiveEnd
()));
}
return
errors
;
return
preparedList
;
}
/**
* 判断两个
数据是否属于同一分组条件
* 判断两个
有效时间区间是否重叠
*/
private
boolean
isSameGroup
(
ApiExpectedCommissionRatioServiceImpl
.
DtoWithParsedData
data1
,
ApiExpectedCommissionRatioServiceImpl
.
DtoWithParsedData
data2
)
{
// 1. 检查条件是否相同
if
(!
isSameGroupExcept
(
data1
.
dto
,
data2
.
dto
))
{
return
false
;
}
return
true
;
private
boolean
isTimeRangeOverlap
(
LocalDateTime
start1
,
LocalDateTime
end1
,
LocalDateTime
start2
,
LocalDateTime
end2
)
{
return
!(
end1
.
isBefore
(
start2
)
||
end2
.
isBefore
(
start1
));
}
/**
*
检查条件是否相同
*
同一业务分组判断:费用名称、是否受汇率影响、结算币种、对账公司、销售组织完全一致
*/
private
boolean
isSame
GroupExcept
(
ApiExpectedCommissionRatioBatchSaveDto
dto1
,
ApiExpectedCommissionRatioBatchSaveDto
dto2
)
{
private
boolean
isSame
BusinessGroup
(
ApiExpectedCommissionRatioBatchSaveDto
dto1
,
ApiExpectedCommissionRatioBatchSaveDto
dto2
)
{
return
Objects
.
equals
(
dto1
.
getExpenseName
(),
dto2
.
getExpenseName
())
&&
Objects
.
equals
(
dto1
.
getEffectiveStart
(),
dto2
.
getEffectiveStart
())
&&
Objects
.
equals
(
dto1
.
getEffectiveEnd
(),
dto2
.
getEffectiveEnd
())
&&
Objects
.
equals
(
dto1
.
getIsExchangeRate
(),
dto2
.
getIsExchangeRate
())
&&
Objects
.
equals
(
dto1
.
getCurrency
(),
dto2
.
getCurrency
())
&&
Objects
.
equals
(
dto1
.
getReconciliationCompany
(),
dto2
.
getReconciliationCompany
());
&&
Objects
.
equals
(
dto1
.
getReconciliationCompany
(),
dto2
.
getReconciliationCompany
())
&&
Objects
.
equals
(
dto1
.
getSalesOrg
(),
dto2
.
getSalesOrg
());
}
/**
* 检查
错误是否已存在
* 检查
冲突是否已记录(去重)
*/
private
boolean
isErrorAlreadyExists
(
List
<
ApiExpectedCommissionRatioServiceImpl
.
OverlapError
>
errors
,
int
index1
,
int
index2
)
{
for
(
ApiExpectedCommissionRatioServiceImpl
.
OverlapError
error
:
errors
)
{
if
((
error
.
index1
==
index1
&&
error
.
index2
==
index2
)
||
(
error
.
index1
==
index2
&&
error
.
index2
==
index1
))
{
private
boolean
isErrorAlreadyExists
(
List
<
OverlapError
>
errors
,
int
index1
,
int
index2
,
String
type
)
{
for
(
OverlapError
error
:
errors
)
{
if
(((
error
.
index1
==
index1
&&
error
.
index2
==
index2
)
||
(
error
.
index1
==
index2
&&
error
.
index2
==
index1
))
&&
error
.
type
.
equals
(
type
))
{
return
true
;
}
}
...
...
@@ -293,76 +285,60 @@ public class ApiExpectedCommissionRatioServiceImpl implements ApiExpectedCommiss
}
/**
* 构建
错误消
息
* 构建
冲突错误信
息
*/
private
String
build
ErrorMessage
(
List
<
ApiExpectedCommissionRatioServiceImpl
.
OverlapError
>
errors
,
List
<
ApiExpectedCommissionRatioBatchSaveDto
>
originalList
)
{
private
String
build
ConflictErrorMessage
(
List
<
OverlapError
>
errors
,
List
<
ApiExpectedCommissionRatioBatchSaveDto
>
originalList
)
{
if
(
errors
.
isEmpty
())
{
return
"未发现
重叠
数据"
;
return
"未发现
冲突
数据"
;
}
StringBuilder
sb
=
new
StringBuilder
();
sb
.
append
(
"发现佣金年限区间重叠的数据,请检查以下数据:\n\n"
);
Map
<
Integer
,
List
<
Integer
>>
overlapMap
=
new
TreeMap
<>();
for
(
ApiExpectedCommissionRatioServiceImpl
.
OverlapError
error
:
errors
)
{
overlapMap
.
computeIfAbsent
(
error
.
index1
,
k
->
new
ArrayList
<>()).
add
(
error
.
index2
);
overlapMap
.
computeIfAbsent
(
error
.
index2
,
k
->
new
ArrayList
<>()).
add
(
error
.
index1
);
StringBuilder
sb
=
new
StringBuilder
(
"发现年限区间重叠且有效时间区间重叠的数据:\n"
);
for
(
OverlapError
error
:
errors
)
{
int
i
=
error
.
index1
;
int
j
=
error
.
index2
;
ApiExpectedCommissionRatioBatchSaveDto
dto1
=
originalList
.
get
(
i
);
ApiExpectedCommissionRatioBatchSaveDto
dto2
=
originalList
.
get
(
j
);
sb
.
append
(
"第"
).
append
(
i
+
1
).
append
(
"行(年限 "
).
append
(
dto1
.
getStartPeriod
()).
append
(
"~"
).
append
(
dto1
.
getEndPeriod
())
.
append
(
",有效 "
).
append
(
dto1
.
getEffectiveStart
().
format
(
DATE_FORMATTER
)).
append
(
"~"
).
append
(
dto1
.
getEffectiveEnd
().
format
(
DATE_FORMATTER
))
.
append
(
")与第"
).
append
(
j
+
1
).
append
(
"行(年限 "
).
append
(
dto2
.
getStartPeriod
()).
append
(
"~"
).
append
(
dto2
.
getEndPeriod
())
.
append
(
",有效 "
).
append
(
dto2
.
getEffectiveStart
().
format
(
DATE_FORMATTER
)).
append
(
"~"
).
append
(
dto2
.
getEffectiveEnd
().
format
(
DATE_FORMATTER
))
.
append
(
")冲突\n"
);
}
// 构建错误信息
for
(
Map
.
Entry
<
Integer
,
List
<
Integer
>>
entry
:
overlapMap
.
entrySet
())
{
int
dataIndex
=
entry
.
getKey
();
List
<
Integer
>
overlapIndices
=
entry
.
getValue
();
ApiExpectedCommissionRatioBatchSaveDto
dto
=
originalList
.
get
(
dataIndex
);
sb
.
append
(
"第"
).
append
(
dataIndex
+
1
).
append
(
"行数据年限区间"
)
.
append
(
"与以下数据年限区间有重叠:"
);
for
(
int
overlapIndex
:
overlapIndices
)
{
ApiExpectedCommissionRatioBatchSaveDto
overlapDto
=
originalList
.
get
(
overlapIndex
);
sb
.
append
(
" 第"
).
append
(
overlapIndex
+
1
).
append
(
"行"
);
}
sb
.
append
(
"\n"
);
}
return
sb
.
toString
();
}
/
**
* 内部类:包含解析后数据的DTO
*/
private
static
class
DtoWithParsedData
{
final
int
originalIndex
;
// 在原始列表中的索引
final
ApiExpectedCommissionRatioBatchSaveDto
dto
;
// 原始DTO
final
int
startYear
;
// 解析后的起始年份
final
int
endYear
;
// 解析后的结束年份
/
/ ------------------ 内部类 ------------------
public
static
class
DtoWithParsedData
{
final
int
originalIndex
;
final
ApiExpectedCommissionRatioBatchSaveDto
dto
;
final
int
startYear
;
final
int
endYear
;
final
LocalDateTime
effectiveStart
;
final
LocalDateTime
effectiveEnd
;
public
DtoWithParsedData
(
int
originalIndex
,
ApiExpectedCommissionRatioBatchSaveDto
dto
,
int
startYear
,
int
endYear
)
{
int
startYear
,
int
endYear
,
LocalDateTime
effectiveStart
,
LocalDateTime
effectiveEnd
)
{
this
.
originalIndex
=
originalIndex
;
this
.
dto
=
dto
;
this
.
startYear
=
startYear
;
this
.
endYear
=
endYear
;
this
.
effectiveStart
=
effectiveStart
;
this
.
effectiveEnd
=
effectiveEnd
;
}
}
/**
* 内部类:重叠错误
*/
private
static
class
OverlapError
{
public
static
class
OverlapError
{
private
final
int
index1
;
private
final
int
index2
;
private
final
String
type
;
public
OverlapError
(
int
index1
,
int
index2
)
{
public
OverlapError
(
int
index1
,
int
index2
,
String
type
)
{
this
.
index1
=
index1
;
this
.
index2
=
index2
;
this
.
type
=
type
;
}
public
int
getIndex1
()
{
return
index1
;
}
public
int
getIndex2
()
{
return
index2
;
}
}
/**
...
...
@@ -379,4 +355,4 @@ public class ApiExpectedCommissionRatioServiceImpl implements ApiExpectedCommiss
}
return
Result
.
success
(
expectedCommissionRatio
);
}
}
}
\ No newline at end of file
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