Toggle navigation
Toggle navigation
This project
Loading...
Sign in
jiujian
/
client-customer-order-api
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Authored by
孟苏慧
2025-06-03 13:28:27 +0800
Browse Files
Options
Browse Files
Download
Plain Diff
Commit
5413121fb23a92798d6b4e76be4e9014b32839a7
5413121f
2 parents
3f5a00ef
f8d3acda
Merge branch 'dev/nx-20250526' into 'master'
农信停餐需求 See merge request
!4
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
606 additions
and
25 deletions
src/main/java/com/infoloop/tianting/controller/MealOrderController.java
src/main/java/com/infoloop/tianting/exception/ErrorCodeEnum.java
src/main/java/com/infoloop/tianting/logic/task/AutoCreateMealOrderTask.java
src/main/java/com/infoloop/tianting/model/vo/DinerMealSuspensionRecordVO.java
src/main/java/com/infoloop/tianting/service/MealOrderService.java
src/main/java/com/infoloop/tianting/service/client/MealOrderServiceRpcClient.java
src/main/java/com/infoloop/tianting/service/impl/MealOrderServiceImpl.java
src/main/proto/MealOrderService.proto
src/main/java/com/infoloop/tianting/controller/MealOrderController.java
View file @
5413121
...
...
@@ -6,10 +6,12 @@ import com.infoloop.tianting.mealorderservice.SingleMealOrderRpcResponse;
import
com.infoloop.tianting.model.common.CreatedResult
;
import
com.infoloop.tianting.model.dto.MealOrderDTO
;
import
com.infoloop.tianting.model.vo.DeliveryRuleVO
;
import
com.infoloop.tianting.model.vo.DinerMealSuspensionRecordVO
;
import
com.infoloop.tianting.model.vo.MealOrderVO
;
import
com.infoloop.tianting.service.MealOrderService
;
import
io.swagger.annotations.Api
;
import
io.swagger.annotations.ApiOperation
;
import
io.swagger.annotations.ApiParam
;
import
lombok.RequiredArgsConstructor
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Autowired
;
...
...
@@ -20,6 +22,7 @@ import org.springframework.web.bind.annotation.PostMapping;
import
org.springframework.web.bind.annotation.PutMapping
;
import
org.springframework.web.bind.annotation.RequestAttribute
;
import
org.springframework.web.bind.annotation.RequestBody
;
import
org.springframework.web.bind.annotation.RequestParam
;
import
org.springframework.web.bind.annotation.ResponseStatus
;
import
org.springframework.web.bind.annotation.RestController
;
...
...
@@ -67,4 +70,11 @@ public class MealOrderController {
return
mealOrderService
.
getDeliveryRule
();
}
@ApiOperation
(
value
=
"查询停餐信息"
)
@GetMapping
(
"/dinermealsuspensionrecord"
)
@ResponseStatus
(
HttpStatus
.
OK
)
public
List
<
DinerMealSuspensionRecordVO
>
queryDinerMealSuspensionRecordsByCondition
()
{
return
mealOrderService
.
queryDinerMealSuspensionRecordsByCondition
();
}
}
...
...
src/main/java/com/infoloop/tianting/exception/ErrorCodeEnum.java
View file @
5413121
...
...
@@ -66,6 +66,8 @@ public enum ErrorCodeEnum implements BaseEnum {
MP_ACCOUNT_ALREADY_DISABLED
(
406000024
,
"账号已禁用"
),
DINER_MEAL_SUSPENDED
(
406000025
,
"当前就餐人处于停餐状态"
)
;
private
final
int
code
;
...
...
src/main/java/com/infoloop/tianting/logic/task/AutoCreateMealOrderTask.java
View file @
5413121
...
...
@@ -3,14 +3,7 @@ package com.infoloop.tianting.logic.task;
import
com.infoloop.tianting.clientinventoryservice.SingleClientRpcResponse
;
import
com.infoloop.tianting.context.LoginContextHolder
;
import
com.infoloop.tianting.enums.LoginSourceEnum
;
import
com.infoloop.tianting.mealorderservice.MealOrderCreation
;
import
com.infoloop.tianting.mealorderservice.MealOrderOrderMethodEnum
;
import
com.infoloop.tianting.mealorderservice.MenuSchedule
;
import
com.infoloop.tianting.mealorderservice.SingleDinerRpcResponse
;
import
com.infoloop.tianting.mealorderservice.SingleGradeClassRpcResponse
;
import
com.infoloop.tianting.mealorderservice.SingleMealMenuRecordRpcResponse
;
import
com.infoloop.tianting.mealorderservice.SingleMealOrderRpcResponse
;
import
com.infoloop.tianting.mealorderservice.SingleMpAccountDinerRefRpcResponse
;
import
com.infoloop.tianting.mealorderservice.*
;
import
com.infoloop.tianting.service.client.ClientInventoryServiceRpcClient
;
import
com.infoloop.tianting.service.client.DeliveryRuleServiceRpcClient
;
import
com.infoloop.tianting.service.client.MealOrderServiceRpcClient
;
...
...
@@ -31,6 +24,7 @@ import java.time.temporal.TemporalAdjusters;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.Comparator
;
import
java.util.HashMap
;
import
java.util.LinkedHashSet
;
import
java.util.List
;
import
java.util.Map
;
...
...
@@ -90,6 +84,24 @@ public class AutoCreateMealOrderTask {
final
var
thisWeekEnd
=
today
.
with
(
DayOfWeek
.
SUNDAY
).
atTime
(
LocalTime
.
MAX
).
atZone
(
DateUtil
.
CHINA_ZONE
);
final
var
nextWeekStart
=
today
.
with
(
TemporalAdjusters
.
next
(
DayOfWeek
.
MONDAY
)).
atStartOfDay
().
atZone
(
DateUtil
.
CHINA_ZONE
);
// 获取下周每天的节假日信息
final
var
holidayMap
=
new
HashMap
<
String
,
Integer
>();
for
(
int
i
=
0
;
i
<
7
;
i
++)
{
final
var
date
=
nextWeekStart
.
plusDays
(
i
);
final
var
dateStr
=
date
.
format
(
DateUtil
.
YYYY_MM_DD
);
try
{
final
var
url
=
String
.
format
(
"https://api.haoshenqi.top/holiday?date=%s"
,
dateStr
);
final
var
response
=
new
java
.
net
.
URL
(
url
).
openConnection
();
final
var
reader
=
new
java
.
io
.
BufferedReader
(
new
java
.
io
.
InputStreamReader
(
response
.
getInputStream
()));
final
var
jsonResponse
=
reader
.
readLine
();
final
var
jsonNode
=
new
com
.
fasterxml
.
jackson
.
databind
.
ObjectMapper
().
readTree
(
jsonResponse
);
final
var
status
=
jsonNode
.
get
(
0
).
get
(
"status"
).
asInt
();
holidayMap
.
put
(
dateStr
,
status
);
}
catch
(
Exception
e
)
{
log
.
error
(
"检查节假日失败: {}"
,
dateStr
,
e
);
}
}
// 查询本周已订餐学生 ID
final
var
mealOrders
=
mealOrderServiceRpcClient
.
queryMealOrdersByCondition
(
enterpriseId
,
null
,
thisWeekStart
.
toInstant
().
toEpochMilli
(),
thisWeekEnd
.
toInstant
().
toEpochMilli
());
final
var
dinerIds
=
mealOrders
.
stream
().
map
(
SingleMealOrderRpcResponse:
:
getDinerId
).
sorted
(
Comparator
.
comparingInt
(
Integer:
:
intValue
)).
collect
(
Collectors
.
toCollection
(
LinkedHashSet:
:
new
));
...
...
@@ -109,8 +121,86 @@ public class AutoCreateMealOrderTask {
final
var
clientMap
=
clientInventoryServiceRpcClient
.
getClientsByIds
(
enterpriseId
,
clientIds
).
getClientsList
().
stream
().
collect
(
Collectors
.
toMap
(
SingleClientRpcResponse:
:
getId
,
Function
.
identity
()));
final
var
gradeClassMap
=
mealOrderServiceRpcClient
.
getGradeClassesByIds
(
enterpriseId
,
classIds
).
stream
().
collect
(
Collectors
.
toMap
(
SingleGradeClassRpcResponse:
:
getId
,
Function
.
identity
()));
final
var
latestMealMenuRecordMap
=
mealOrderServiceRpcClient
.
queryLatestMealMenuRecordsByClientIds
(
enterpriseId
,
clientIds
).
stream
().
collect
(
Collectors
.
toMap
(
SingleMealMenuRecordRpcResponse:
:
getClientId
,
Function
.
identity
()));
// 批量查询学校级别的停餐信息
final
var
schoolSuspensionMap
=
new
HashMap
<
Integer
,
SingleDinerMealSuspensionRecordRpcResponse
>();
var
schoolSuspensionRecords
=
mealOrderServiceRpcClient
.
queryDinerMealSuspensionRecordsByCondition
(
enterpriseId
,
clientIds
,
// 使用0表示查询所有
null
,
List
.
of
(
0
)
);
if
(
schoolSuspensionRecords
!=
null
)
{
final
var
nextWeekStartTime
=
nextWeekStart
.
toInstant
().
toEpochMilli
();
final
var
nextWeekEndTime
=
nextWeekStart
.
plusDays
(
6
).
with
(
LocalTime
.
MAX
).
toInstant
().
toEpochMilli
();
schoolSuspensionRecords
.
stream
()
.
filter
(
record
->
clientIds
.
contains
(
record
.
getClientId
()))
.
filter
(
record
->
!(
record
.
getEndAt
()
<
nextWeekStartTime
||
record
.
getStartAt
()
>
nextWeekEndTime
))
.
collect
(
Collectors
.
groupingBy
(
SingleDinerMealSuspensionRecordRpcResponse:
:
getClientId
,
Collectors
.
collectingAndThen
(
Collectors
.
maxBy
((
a
,
b
)
->
Long
.
compare
(
a
.
getCreatedAt
(),
b
.
getCreatedAt
())),
opt
->
opt
.
orElse
(
null
)
)
))
.
forEach
((
clientId
,
record
)
->
{
if
(
record
!=
null
)
{
schoolSuspensionMap
.
put
(
clientId
,
record
);
}
});
}
// 批量查询学生级别的停餐信息
final
var
studentSuspensionMap
=
new
HashMap
<
Integer
,
SingleDinerMealSuspensionRecordRpcResponse
>();
var
studentSuspensionRecords
=
mealOrderServiceRpcClient
.
queryDinerMealSuspensionRecordsByCondition
(
enterpriseId
,
null
,
// 使用0表示查询所有
null
,
notReservedDiners
.
stream
().
map
(
SingleDinerRpcResponse:
:
getId
).
toList
()
);
if
(
studentSuspensionRecords
!=
null
)
{
final
var
nextWeekStartTime
=
nextWeekStart
.
toInstant
().
toEpochMilli
();
final
var
nextWeekEndTime
=
nextWeekStart
.
plusDays
(
6
).
with
(
LocalTime
.
MAX
).
toInstant
().
toEpochMilli
();
var
dinerIdSet
=
notReservedDiners
.
stream
()
.
map
(
SingleDinerRpcResponse:
:
getId
)
.
collect
(
Collectors
.
toSet
());
studentSuspensionRecords
.
stream
()
.
filter
(
record
->
dinerIdSet
.
contains
(
record
.
getDinerId
()))
.
filter
(
record
->
!(
record
.
getEndAt
()
<
nextWeekStartTime
||
record
.
getStartAt
()
>
nextWeekEndTime
))
.
collect
(
Collectors
.
groupingBy
(
SingleDinerMealSuspensionRecordRpcResponse:
:
getDinerId
,
Collectors
.
collectingAndThen
(
Collectors
.
maxBy
((
a
,
b
)
->
Long
.
compare
(
a
.
getCreatedAt
(),
b
.
getCreatedAt
())),
opt
->
opt
.
orElse
(
null
)
)
))
.
forEach
((
dinerId
,
record
)
->
{
if
(
record
!=
null
)
{
studentSuspensionMap
.
put
(
dinerId
,
record
);
}
});
}
// 构建创建请求
final
var
creations
=
notReservedDiners
.
stream
().
map
(
diner
->
toMealOrderCreation
(
diner
,
clientMap
,
gradeClassMap
,
latestMealMenuRecordMap
,
mpAccountDinerRefMap
,
nextWeekStart
)).
filter
(
Objects:
:
nonNull
).
toList
();
final
var
creations
=
notReservedDiners
.
stream
()
.
map
(
diner
->
toMealOrderCreation
(
diner
,
clientMap
,
gradeClassMap
,
latestMealMenuRecordMap
,
mpAccountDinerRefMap
,
nextWeekStart
,
schoolSuspensionMap
,
studentSuspensionMap
,
holidayMap
))
.
filter
(
Objects:
:
nonNull
)
.
toList
();
if
(
creations
.
isEmpty
())
{
return
;
}
...
...
@@ -132,12 +222,25 @@ public class AutoCreateMealOrderTask {
Map
<
Integer
,
SingleGradeClassRpcResponse
>
classMap
,
Map
<
Integer
,
SingleMealMenuRecordRpcResponse
>
menuMap
,
Map
<
Integer
,
SingleMpAccountDinerRefRpcResponse
>
mpAccountDinerRefMap
,
ZonedDateTime
startOfNextWeek
)
{
ZonedDateTime
startOfNextWeek
,
Map
<
Integer
,
SingleDinerMealSuspensionRecordRpcResponse
>
schoolSuspensionMap
,
Map
<
Integer
,
SingleDinerMealSuspensionRecordRpcResponse
>
studentSuspensionMap
,
Map
<
String
,
Integer
>
holidayMap
)
{
final
var
menu
=
menuMap
.
get
(
diner
.
getClientId
());
final
var
client
=
clientMap
.
get
(
diner
.
getClientId
());
final
var
gradeClass
=
classMap
.
get
(
diner
.
getClassId
());
final
var
mpAccountDinerRef
=
mpAccountDinerRefMap
.
get
(
diner
.
getId
());
if
(
menu
==
null
||
client
==
null
||
gradeClass
==
null
)
return
null
;
// 获取停餐信息,优先使用学校级别的
SingleDinerMealSuspensionRecordRpcResponse
suspensionRecord
=
schoolSuspensionMap
.
get
(
diner
.
getClientId
());
if
(
suspensionRecord
==
null
)
{
suspensionRecord
=
studentSuspensionMap
.
get
(
diner
.
getId
());
}
// 构建下周的餐食安排
List
<
MenuSchedule
>
meals
=
buildNextWeekMeals
(
startOfNextWeek
,
suspensionRecord
,
holidayMap
);
return
MealOrderCreation
.
newBuilder
()
.
setClientId
(
diner
.
getClientId
())
.
setMenuId
(
menu
.
getId
())
...
...
@@ -150,24 +253,50 @@ public class AutoCreateMealOrderTask {
.
setClassName
(
gradeClass
.
getClassName
())
.
setStudentNo
(
diner
.
getStudentNo
())
.
setReserveDate
(
Instant
.
now
().
toEpochMilli
())
.
addAllMeals
(
buildNextWeekMeals
(
startOfNextWeek
)
)
.
addAllMeals
(
meals
)
.
build
();
}
private
LocalDate
getThisWeekDay
(
LocalDate
now
,
DayOfWeek
target
)
{
LocalDate
monday
=
now
.
with
(
DayOfWeek
.
MONDAY
);
return
monday
.
plusDays
(
target
.
getValue
()
-
1L
);
}
private
List
<
MenuSchedule
>
buildNextWeekMeals
(
ZonedDateTime
nextWeekStart
)
{
return
IntStream
.
range
(
0
,
5
)
private
List
<
MenuSchedule
>
buildNextWeekMeals
(
ZonedDateTime
nextWeekStart
,
SingleDinerMealSuspensionRecordRpcResponse
suspensionRecord
,
Map
<
String
,
Integer
>
holidayMap
)
{
return
IntStream
.
range
(
0
,
7
)
.
mapToObj
(
i
->
{
final
var
date
=
nextWeekStart
.
plusDays
(
i
);
final
var
dateStr
=
date
.
format
(
DateUtil
.
YYYY_MM_DD
);
// 检查是否为节假日
final
var
status
=
holidayMap
.
get
(
dateStr
);
if
(
status
!=
null
&&
status
!=
0
&&
status
!=
2
)
{
// 如果不是工作日,返回null
return
null
;
}
// 如果有停餐信息,检查当前循环的日期是否在停餐时间范围内
if
(
suspensionRecord
!=
null
)
{
final
var
dateStart
=
date
.
with
(
LocalTime
.
MIN
).
toInstant
().
toEpochMilli
();
final
var
dateEnd
=
date
.
with
(
LocalTime
.
MAX
).
toInstant
().
toEpochMilli
();
final
var
suspensionStart
=
suspensionRecord
.
getStartAt
();
final
var
suspensionEnd
=
suspensionRecord
.
getEndAt
();
// 如果停餐时间范围与当前日期有重叠,返回null
if
(!(
dateEnd
<
suspensionStart
||
dateStart
>
suspensionEnd
))
{
return
null
;
}
}
// 如果是工作日且不在停餐时间内,返回正常菜单
return
MenuSchedule
.
newBuilder
()
.
setDate
(
date
.
format
(
DateUtil
.
YYYY_MM_DD_LEFT_SYMBOL
))
.
setMenu
(
"A"
)
.
build
();
})
.
filter
(
Objects:
:
nonNull
)
// 过滤掉null值
.
toList
();
}
private
LocalDate
getThisWeekDay
(
LocalDate
now
,
DayOfWeek
target
)
{
LocalDate
monday
=
now
.
with
(
DayOfWeek
.
MONDAY
);
return
monday
.
plusDays
(
target
.
getValue
()
-
1L
);
}
}
...
...
src/main/java/com/infoloop/tianting/model/vo/DinerMealSuspensionRecordVO.java
0 → 100644
View file @
5413121
package
com
.
infoloop
.
tianting
.
model
.
vo
;
import
io.swagger.annotations.ApiModel
;
import
io.swagger.annotations.ApiModelProperty
;
import
lombok.Builder
;
import
lombok.Data
;
import
java.util.Date
;
@Data
@Builder
@ApiModel
(
"停餐记录VO"
)
public
class
DinerMealSuspensionRecordVO
{
@ApiModelProperty
(
"ID"
)
private
Long
id
;
@ApiModelProperty
(
"企业ID"
)
private
Long
enterpriseId
;
@ApiModelProperty
(
"客户ID"
)
private
Long
clientId
;
@ApiModelProperty
(
"班级ID"
)
private
Long
classId
;
@ApiModelProperty
(
"年级名称"
)
private
String
gradeName
;
@ApiModelProperty
(
"班级名称"
)
private
String
className
;
@ApiModelProperty
(
"用餐人ID"
)
private
Long
dinerId
;
@ApiModelProperty
(
"用餐人姓名"
)
private
String
dinerName
;
@ApiModelProperty
(
"学号"
)
private
String
studentNo
;
@ApiModelProperty
(
"开始时间"
)
private
Date
startAt
;
@ApiModelProperty
(
"结束时间"
)
private
Date
endAt
;
@ApiModelProperty
(
"备注"
)
private
String
comment
;
}
\ No newline at end of file
src/main/java/com/infoloop/tianting/service/MealOrderService.java
View file @
5413121
...
...
@@ -4,6 +4,7 @@ import com.infoloop.tianting.mealorderservice.SingleMealOrderRpcResponse;
import
com.infoloop.tianting.model.common.CreatedResult
;
import
com.infoloop.tianting.model.dto.MealOrderDTO
;
import
com.infoloop.tianting.model.vo.DeliveryRuleVO
;
import
com.infoloop.tianting.model.vo.DinerMealSuspensionRecordVO
;
import
com.infoloop.tianting.model.vo.MealOrderVO
;
import
java.util.List
;
...
...
@@ -17,4 +18,16 @@ public interface MealOrderService {
MealOrderVO
getMealOrderById
(
SingleMealOrderRpcResponse
mealOrder
);
DeliveryRuleVO
getDeliveryRule
();
/**
* 查询停餐信息
* 先查询学校的停餐信息,再查询学生的停餐信息,学校的停餐信息优先级高于学生停餐信息
*
* @param enterpriseId 企业ID
* @param clientId 客户ID
* @param classId 班级ID
* @param dinerId 用餐人ID
* @return 停餐信息列表
*/
List
<
DinerMealSuspensionRecordVO
>
queryDinerMealSuspensionRecordsByCondition
();
}
...
...
src/main/java/com/infoloop/tianting/service/client/MealOrderServiceRpcClient.java
View file @
5413121
...
...
@@ -47,6 +47,8 @@ import com.infoloop.tianting.mealorderservice.UpdateDinerRpcRequest;
import
com.infoloop.tianting.mealorderservice.UpdateDinerRpcResponse
;
import
com.infoloop.tianting.mealorderservice.UpdateMpAccountRpcRequest
;
import
com.infoloop.tianting.mealorderservice.UpdateMpAccountRpcResponse
;
import
com.infoloop.tianting.mealorderservice.QueryDinerMealSuspensionRecordsByConditionRpcRequest
;
import
com.infoloop.tianting.mealorderservice.SingleDinerMealSuspensionRecordRpcResponse
;
import
lombok.RequiredArgsConstructor
;
import
org.apache.commons.collections4.CollectionUtils
;
import
org.apache.commons.lang3.StringUtils
;
...
...
@@ -274,4 +276,30 @@ public class MealOrderServiceRpcClient {
.
setShouldFilterReserveDateEnd
(
reserveDateEnd
!=
null
).
setReserveDateEnd
(
reserveDateEnd
==
null
?
0
:
reserveDateEnd
)
.
build
()).
getResponsesList
();
}
public
List
<
SingleDinerMealSuspensionRecordRpcResponse
>
queryDinerMealSuspensionRecordsByCondition
(
int
enterpriseId
,
@Nullable
List
<
Integer
>
clientIds
,
@Nullable
List
<
Integer
>
classIds
,
@Nullable
List
<
Integer
>
dinerIds
)
{
var
request
=
QueryDinerMealSuspensionRecordsByConditionRpcRequest
.
newBuilder
()
.
setEnterpriseId
(
enterpriseId
);
if
(
clientIds
!=
null
)
{
request
.
setShouldFilterClientIds
(
true
)
.
addAllClientIds
(
clientIds
);
}
if
(
classIds
!=
null
)
{
request
.
setShouldFilterClassIds
(
true
)
.
addAllClassIds
(
classIds
);
}
if
(
dinerIds
!=
null
)
{
request
.
setShouldFilterDinerIds
(
true
)
.
addAllDinerIds
(
dinerIds
);
}
return
mealOrderServiceRpcBlockingStub
.
queryDinerMealSuspensionRecordsByCondition
(
request
.
build
())
.
getResponsesList
();
}
}
...
...
src/main/java/com/infoloop/tianting/service/impl/MealOrderServiceImpl.java
View file @
5413121
...
...
@@ -4,13 +4,11 @@ import com.infoloop.tianting.context.LoginContextHolder;
import
com.infoloop.tianting.enums.QueryMealOrderStatusEnum
;
import
com.infoloop.tianting.exception.ClientEndExceptions
;
import
com.infoloop.tianting.exception.ErrorCodeEnum
;
import
com.infoloop.tianting.mealorderservice.MealOrderCreation
;
import
com.infoloop.tianting.mealorderservice.MealOrderOrderMethodEnum
;
import
com.infoloop.tianting.mealorderservice.MenuSchedule
;
import
com.infoloop.tianting.mealorderservice.SingleMealOrderRpcResponse
;
import
com.infoloop.tianting.mealorderservice.*
;
import
com.infoloop.tianting.model.common.CreatedResult
;
import
com.infoloop.tianting.model.dto.MealOrderDTO
;
import
com.infoloop.tianting.model.vo.DeliveryRuleVO
;
import
com.infoloop.tianting.model.vo.DinerMealSuspensionRecordVO
;
import
com.infoloop.tianting.model.vo.MealOrderVO
;
import
com.infoloop.tianting.service.MealOrderService
;
import
com.infoloop.tianting.service.client.ClientInventoryServiceRpcClient
;
...
...
@@ -23,12 +21,17 @@ import org.springframework.beans.factory.annotation.Autowired;
import
org.springframework.stereotype.Service
;
import
java.time.DayOfWeek
;
import
java.time.Instant
;
import
java.time.LocalDate
;
import
java.time.LocalDateTime
;
import
java.time.LocalTime
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.Date
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Objects
;
import
java.util.stream.Collectors
;
@Slf4j
@Service
...
...
@@ -77,30 +80,86 @@ public class MealOrderServiceImpl implements MealOrderService {
if
(!
nowWithinRange
)
{
throw
ClientEndExceptions
.
IncorrectRequestValue
.
build
(
ErrorCodeEnum
.
MEAL_ORDER_TIME_NOT_IN_RANGE
);
}
// 1. 获取订餐人信息
final
var
dinerById
=
mealOrderServiceRpcClient
.
getDinerById
(
loginInfo
.
getEnterpriseId
(),
createMealOrderDTO
.
getDinerId
());
if
(
dinerById
==
null
)
{
throw
ClientEndExceptions
.
IncorrectRequestValue
.
build
(
ErrorCodeEnum
.
DINER_NOT_FOUND
);
}
// 2. 校验订餐人关联关系
final
var
mpAccountDinerRefs
=
mealOrderServiceRpcClient
.
queryMpAccountDinerRefsByCondition
(
loginInfo
.
getEnterpriseId
(),
Collections
.
singletonList
(
loginInfo
.
getId
()),
Collections
.
singletonList
(
createMealOrderDTO
.
getDinerId
()));
if
(
mpAccountDinerRefs
.
size
()
!=
1
)
{
throw
ClientEndExceptions
.
IncorrectRequestValue
.
build
(
ErrorCodeEnum
.
DINER_NOT_FOUND
);
}
// 3. 校验客户状态
final
var
clientById
=
clientInventoryServiceRpcClient
.
getClientById
(
loginInfo
.
getEnterpriseId
(),
dinerById
.
getClientId
());
if
(
clientById
.
getClient
().
getStatus
()
!=
1
)
{
throw
ClientEndExceptions
.
IncorrectRequestValue
.
build
(
ErrorCodeEnum
.
CLIENT_NOT_ENABLED
);
}
// 4. 校验班级信息
final
var
gradeClassById
=
mealOrderServiceRpcClient
.
getGradeClassById
(
loginInfo
.
getEnterpriseId
(),
dinerById
.
getClassId
());
if
(
gradeClassById
==
null
)
{
throw
ClientEndExceptions
.
IncorrectRequestValue
.
build
(
ErrorCodeEnum
.
GRADE_CLASS_NOT_FOUND
);
}
// 5. 校验停餐记录
var
currentTime
=
System
.
currentTimeMillis
();
// 5.1 先查询学校级别的停餐信息
var
schoolSuspensionRecords
=
mealOrderServiceRpcClient
.
queryDinerMealSuspensionRecordsByCondition
(
loginInfo
.
getEnterpriseId
(),
List
.
of
(
dinerById
.
getClientId
()),
null
,
null
);
if
(
schoolSuspensionRecords
!=
null
&&
!
schoolSuspensionRecords
.
isEmpty
())
{
var
latestSchoolSuspension
=
schoolSuspensionRecords
.
stream
()
.
max
((
a
,
b
)
->
Long
.
compare
(
a
.
getCreatedAt
(),
b
.
getCreatedAt
()))
.
orElse
(
null
);
if
(
latestSchoolSuspension
!=
null
&&
currentTime
>=
latestSchoolSuspension
.
getStartAt
()
&&
currentTime
<=
latestSchoolSuspension
.
getEndAt
())
{
throw
ClientEndExceptions
.
IncorrectRequestValue
.
build
(
ErrorCodeEnum
.
DINER_MEAL_SUSPENDED
);
}
}
// 5.2 再查询学生级别的停餐信息
var
studentSuspensionRecords
=
mealOrderServiceRpcClient
.
queryDinerMealSuspensionRecordsByCondition
(
loginInfo
.
getEnterpriseId
(),
List
.
of
(
dinerById
.
getClientId
()),
List
.
of
(
dinerById
.
getClassId
()),
List
.
of
(
dinerById
.
getId
())
);
if
(
studentSuspensionRecords
!=
null
&&
!
studentSuspensionRecords
.
isEmpty
())
{
var
latestStudentSuspension
=
studentSuspensionRecords
.
stream
()
.
max
((
a
,
b
)
->
Long
.
compare
(
a
.
getCreatedAt
(),
b
.
getCreatedAt
()))
.
orElse
(
null
);
if
(
latestStudentSuspension
!=
null
&&
currentTime
>=
latestStudentSuspension
.
getStartAt
()
&&
currentTime
<=
latestStudentSuspension
.
getEndAt
())
{
throw
ClientEndExceptions
.
IncorrectRequestValue
.
build
(
ErrorCodeEnum
.
DINER_MEAL_SUSPENDED
);
}
}
// 6. 校验菜单信息
final
var
latestMealMenuRecords
=
mealOrderServiceRpcClient
.
queryLatestMealMenuRecordsByClientIds
(
loginInfo
.
getEnterpriseId
(),
Collections
.
singletonList
(
dinerById
.
getClientId
()));
if
(
latestMealMenuRecords
.
isEmpty
())
{
// throw ClientEndExceptions.IncorrectRequestValue.build(ErrorCodeEnum.MEAL_MENU_NOT_FOUND);
}
// 7. 校验是否已预订
final
var
reserveDinerMealOrders
=
mealOrderServiceRpcClient
.
queryReserveMealOrdersByDinerIds
(
loginInfo
.
getEnterpriseId
(),
Collections
.
singletonList
(
createMealOrderDTO
.
getDinerId
()));
if
(!
reserveDinerMealOrders
.
isEmpty
())
{
throw
ClientEndExceptions
.
IncorrectRequestValue
.
build
(
ErrorCodeEnum
.
DINER_ALREADY_RESERVED
);
}
// 8. 创建订单
final
var
mealOrder
=
mealOrderServiceRpcClient
.
createMealOrder
(
loginInfo
,
MealOrderCreation
.
newBuilder
()
.
setClientId
(
dinerById
.
getClientId
())
.
setMenuId
(
latestMealMenuRecords
.
isEmpty
()
?
0
:
latestMealMenuRecords
.
get
(
0
).
getId
())
...
...
@@ -180,7 +239,7 @@ public class MealOrderServiceImpl implements MealOrderService {
final
var
maxDay
=
Collections
.
max
(
enabledDays
);
final
var
today
=
now
.
toLocalDate
();
final
var
startDateTime
=
getThisWeekDate
(
today
,
minDay
).
atTime
(
startTime
);
final
var
endDateTime
=
getThisWeekDate
(
today
,
maxDay
).
atTime
(
endTime
);
final
var
endDateTime
=
getThisWeekDate
(
today
,
maxDay
).
atTime
(
endTime
);
return
!
now
.
isBefore
(
startDateTime
)
&&
!
now
.
isAfter
(
endDateTime
);
}
...
...
@@ -188,4 +247,136 @@ public class MealOrderServiceImpl implements MealOrderService {
LocalDate
monday
=
now
.
with
(
DayOfWeek
.
MONDAY
);
return
monday
.
plusDays
(
day
.
getValue
()
-
1L
);
// MONDAY 是 1,SUNDAY 是 7
}
@Override
public
List
<
DinerMealSuspensionRecordVO
>
queryDinerMealSuspensionRecordsByCondition
()
{
final
var
loginInfo
=
LoginContextHolder
.
getLoginInfo
();
// 1. 获取当前登录用户关联的所有订餐人
var
mpAccountDinerRefs
=
mealOrderServiceRpcClient
.
queryMpAccountDinerRefsByCondition
(
loginInfo
.
getEnterpriseId
(),
Collections
.
singletonList
(
loginInfo
.
getId
()),
Collections
.
emptyList
()
);
if
(
mpAccountDinerRefs
.
isEmpty
())
{
return
Collections
.
emptyList
();
}
// 2. 获取所有订餐人ID
var
dinerIds
=
mpAccountDinerRefs
.
stream
()
.
map
(
SingleMpAccountDinerRefRpcResponse:
:
getDinerId
)
.
toList
();
// 3. 获取所有订餐人信息
var
diners
=
mealOrderServiceRpcClient
.
getDinersByIds
(
loginInfo
.
getEnterpriseId
(),
dinerIds
);
var
dinerById
=
diners
.
stream
().
collect
(
Collectors
.
toMap
(
SingleDinerRpcResponse:
:
getId
,
diner
->
diner
));
// 4. 获取所有不重复的clientId
var
uniqueClientIds
=
diners
.
stream
()
.
map
(
diner
->
Long
.
valueOf
(
diner
.
getClientId
()))
.
distinct
()
.
toList
();
// 5. 批量获取所有学校的停餐信息
final
var
now
=
Instant
.
now
();
var
schoolSuspensionRecords
=
mealOrderServiceRpcClient
.
queryDinerMealSuspensionRecordsByCondition
(
loginInfo
.
getEnterpriseId
(),
null
,
null
,
null
).
stream
().
filter
(
r
->
r
.
getClassId
()
==
0
).
filter
(
r
->
r
.
getEndAt
()
>
now
.
toEpochMilli
()).
toList
();
// 6. 批量获取所有学生的停餐信息
var
studentSuspensionRecords
=
mealOrderServiceRpcClient
.
queryDinerMealSuspensionRecordsByCondition
(
loginInfo
.
getEnterpriseId
(),
null
,
null
,
dinerIds
).
stream
().
filter
(
r
->
r
.
getEndAt
()
>
now
.
toEpochMilli
()).
toList
();
// 7. 构建学校停餐信息Map
var
schoolSuspensionMap
=
schoolSuspensionRecords
.
stream
()
.
collect
(
Collectors
.
groupingBy
(
SingleDinerMealSuspensionRecordRpcResponse:
:
getClientId
,
Collectors
.
collectingAndThen
(
Collectors
.
maxBy
((
a
,
b
)
->
Long
.
compare
(
a
.
getCreatedAt
(),
b
.
getCreatedAt
())),
opt
->
opt
.
map
(
o
->
convertToVO
(
o
,
dinerById
)).
orElse
(
null
)
)
));
// 8. 构建学生停餐信息Map
var
studentSuspensionMap
=
studentSuspensionRecords
.
stream
()
.
collect
(
Collectors
.
groupingBy
(
SingleDinerMealSuspensionRecordRpcResponse:
:
getDinerId
,
Collectors
.
collectingAndThen
(
Collectors
.
maxBy
((
a
,
b
)
->
Long
.
compare
(
a
.
getCreatedAt
(),
b
.
getCreatedAt
())),
opt
->
opt
.
map
(
o
->
convertToVO
(
o
,
dinerById
)).
orElse
(
null
)
)
));
// 9. 获取每个订餐人的停餐信息
return
diners
.
stream
()
.
map
(
diner
->
{
// 获取学校级别的停餐信息
var
schoolSuspension
=
schoolSuspensionMap
.
get
(
Long
.
valueOf
(
diner
.
getClientId
()).
intValue
());
// 获取学生级别的停餐信息
var
studentSuspension
=
studentSuspensionMap
.
get
(
Long
.
valueOf
(
diner
.
getId
()).
intValue
());
// 如果两个都没有停餐信息,返回null
if
(
schoolSuspension
==
null
&&
studentSuspension
==
null
)
{
return
null
;
}
// 如果只有学校级别的停餐信息
if
(
schoolSuspension
!=
null
&&
studentSuspension
==
null
)
{
return
schoolSuspension
;
}
// 如果只有学生级别的停餐信息
if
(
schoolSuspension
==
null
&&
studentSuspension
!=
null
)
{
return
studentSuspension
;
}
// 如果两个都有停餐信息,合并时间范围
return
DinerMealSuspensionRecordVO
.
builder
()
.
id
(
schoolSuspension
.
getId
())
.
enterpriseId
(
schoolSuspension
.
getEnterpriseId
())
.
clientId
(
schoolSuspension
.
getClientId
())
.
classId
(
studentSuspension
.
getClassId
())
.
dinerId
(
studentSuspension
.
getDinerId
())
.
dinerName
(
studentSuspension
.
getDinerName
())
.
studentNo
(
studentSuspension
.
getStudentNo
())
.
startAt
(
new
Date
(
Math
.
min
(
schoolSuspension
.
getStartAt
().
getTime
(),
studentSuspension
.
getStartAt
().
getTime
())))
.
endAt
(
new
Date
(
Math
.
max
(
schoolSuspension
.
getEndAt
().
getTime
(),
studentSuspension
.
getEndAt
().
getTime
())))
.
comment
(
""
)
.
build
();
})
.
filter
(
Objects:
:
nonNull
)
.
distinct
()
.
toList
();
}
/**
* 将RPC响应转换为VO对象
*/
private
DinerMealSuspensionRecordVO
convertToVO
(
SingleDinerMealSuspensionRecordRpcResponse
response
,
Map
<
Integer
,
SingleDinerRpcResponse
>
dinerById
)
{
if
(
response
==
null
)
{
return
null
;
}
return
DinerMealSuspensionRecordVO
.
builder
()
.
id
(
Long
.
valueOf
(
response
.
getId
()))
.
enterpriseId
(
Long
.
valueOf
(
response
.
getEnterpriseId
()))
.
clientId
(
Long
.
valueOf
(
response
.
getClientId
()))
.
classId
(
Long
.
valueOf
(
response
.
getClassId
()))
.
dinerId
(
Long
.
valueOf
(
response
.
getDinerId
()))
.
dinerName
(
dinerById
.
get
(
response
.
getDinerId
())
!=
null
?
dinerById
.
get
(
response
.
getDinerId
()).
getName
()
:
null
)
.
studentNo
(
dinerById
.
get
(
response
.
getDinerId
())
!=
null
?
dinerById
.
get
(
response
.
getDinerId
()).
getStudentNo
()
:
null
)
.
startAt
(
new
Date
(
response
.
getStartAt
()))
.
endAt
(
new
Date
(
response
.
getEndAt
()))
.
comment
(
response
.
getComment
())
.
build
();
}
}
...
...
src/main/proto/MealOrderService.proto
View file @
5413121
...
...
@@ -31,6 +31,7 @@ service MealOrderServiceRpc {
rpc
UpdateDiner
(
UpdateDinerRpcRequest
)
returns
(
UpdateDinerRpcResponse
)
{}
rpc
BatchSaveOrUpdateDiners
(
BatchSaveOrUpdateDinersRpcRequest
)
returns
(
BatchSaveOrUpdateDinersRpcResponse
)
{}
rpc
DeleteDinersByIds
(
DeleteDinersByIdsRpcRequest
)
returns
(
DeleteDinersRpcResponse
)
{}
rpc
DeleteGraduationDinersByClassIds
(
DeleteGraduationDinersByClassIdsRpcRequest
)
returns
(
DeleteGraduationDinersByClassIdsRpcResponse
)
{}
rpc
GetMpAccountDinerRefsByIds
(
GetMpAccountDinerRefsByIdsRpcRequest
)
returns
(
GetMpAccountDinerRefsByIdsRpcResponse
)
{}
rpc
QueryMpAccountDinerRefsByCondition
(
QueryMpAccountDinerRefsByConditionRpcRequest
)
returns
(
QueryMpAccountDinerRefsByConditionRpcResponse
)
{}
...
...
@@ -46,12 +47,22 @@ service MealOrderServiceRpc {
rpc
BatchSaveOrUpdateGradeClasses
(
BatchSaveOrUpdateGradeClassesRpcRequest
)
returns
(
BatchSaveOrUpdateGradeClassesRpcResponse
)
{}
rpc
DeleteGradeClassesByIds
(
DeleteGradeClassesByIdsRpcRequest
)
returns
(
DeleteGradeClassesRpcResponse
)
{}
rpc
DeleteGradeClassesAndDinersByClientIds
(
DeleteGradeClassesAndDinersByClientIdsRpcRequest
)
returns
(
DeleteGradeClassesAndDinersByClientIdsRpcResponse
)
{}
rpc
DeleteGradeClassesAndDinersByClassIds
(
DeleteGradeClassesAndDinersByClassIdsRpcRequest
)
returns
(
DeleteGradeClassesAndDinersByClassIdsRpcResponse
)
{}
rpc
GetMealMenuRecordById
(
GetMealMenuRecordByIdRpcRequest
)
returns
(
GetMealMenuRecordByIdRpcResponse
)
{}
rpc
GetMealMenuRecordsByIds
(
GetMealMenuRecordsByIdsRpcRequest
)
returns
(
GetMealMenuRecordsByIdsRpcResponse
)
{}
rpc
QueryMealMenuRecordsByCondition
(
QueryMealMenuRecordsByConditionRpcRequest
)
returns
(
QueryMealMenuRecordsByConditionRpcResponse
)
{}
rpc
CreateMealMenuRecord
(
CreateMealMenuRecordRpcRequest
)
returns
(
CreateMealMenuRecordRpcResponse
)
{}
rpc
QueryLatestMealMenuRecordsByClientIds
(
QueryLatestMealMenuRecordsByClientIdsRpcRequest
)
returns
(
QueryLatestMealMenuRecordsByClientIdsRpcResponse
)
{}
// 停餐记录相关服务
rpc
getDinerMealSuspensionRecordById
(
GetDinerMealSuspensionRecordByIdRpcRequest
)
returns
(
GetDinerMealSuspensionRecordByIdRpcResponse
);
rpc
getDinerMealSuspensionRecordsByIds
(
GetDinerMealSuspensionRecordsByIdsRpcRequest
)
returns
(
GetDinerMealSuspensionRecordsByIdsRpcResponse
);
rpc
queryDinerMealSuspensionRecordsByCondition
(
QueryDinerMealSuspensionRecordsByConditionRpcRequest
)
returns
(
QueryDinerMealSuspensionRecordsByConditionRpcResponse
);
rpc
createDinerMealSuspensionRecord
(
CreateDinerMealSuspensionRecordRpcRequest
)
returns
(
CreateDinerMealSuspensionRecordRpcResponse
);
rpc
batchCreateDinerMealSuspensionRecords
(
BatchCreateDinerMealSuspensionRecordsRpcRequest
)
returns
(
BatchCreateDinerMealSuspensionRecordsRpcResponse
);
rpc
updateDinerMealSuspensionRecord
(
UpdateDinerMealSuspensionRecordRpcRequest
)
returns
(
UpdateDinerMealSuspensionRecordRpcResponse
);
rpc
deleteDinerMealSuspensionRecordsByIds
(
DeleteDinerMealSuspensionRecordsByIdsRpcRequest
)
returns
(
DeleteDinerMealSuspensionRecordsRpcResponse
);
}
enum
MealOrderOrderMethodEnum
{
...
...
@@ -357,6 +368,17 @@ message DeleteDinersRpcResponse {
bool
isDeleted
=
1
;
}
message
DeleteGraduationDinersByClassIdsRpcRequest
{
repeated
int32
classIds
=
1
;
int32
enterpriseId
=
2
;
int32
updatedBy
=
3
;
int32
updateSource
=
4
;
}
message
DeleteGraduationDinersByClassIdsRpcResponse
{
bool
isDeleted
=
1
;
}
enum
MpAccountGenderEnum
{
MP_ACCOUNT_GENDER_MAN
=
0
;
MP_ACCOUNT_GENDER_WOMAN
=
1
;
...
...
@@ -613,8 +635,8 @@ message QueryGradeClassesByConditionRpcRequest {
int32
enterpriseId
=
1
;
bool
shouldFilterClientIds
=
2
;
repeated
int32
clientIds
=
3
;
bool
shouldFilterGradeName
=
4
;
string
gradeName
=
5
;
bool
shouldFilterGradeName
s
=
4
;
repeated
string
gradeName
=
5
;
bool
includeDeleted
=
6
;
}
...
...
@@ -721,6 +743,18 @@ message DeleteGradeClassesAndDinersByClientIdsRpcResponse {
bool
isDeleted
=
1
;
}
message
DeleteGradeClassesAndDinersByClassIdsRpcRequest
{
repeated
int32
classIds
=
1
;
int32
enterpriseId
=
2
;
int32
updatedBy
=
3
;
int32
updateSource
=
4
;
}
message
DeleteGradeClassesAndDinersByClassIdsRpcResponse
{
bool
isDeleted
=
1
;
}
message
SingleMealMenuRecordRpcResponse
{
int32
id
=
1
;
int32
enterpriseId
=
2
;
...
...
@@ -734,6 +768,7 @@ message SingleMealMenuRecordRpcResponse {
int64
updatedAt
=
10
;
int32
updateSource
=
11
;
bool
isDeleted
=
12
;
string
operatorName
=
13
;
}
message
GetMealMenuRecordByIdRpcRequest
{
...
...
@@ -781,6 +816,7 @@ message CreateMealMenuRecordRpcRequest {
int32
enterpriseId
=
2
;
int32
createdBy
=
3
;
int32
creationSource
=
4
;
string
operatorName
=
5
;
}
message
CreateMealMenuRecordRpcResponse
{
...
...
@@ -796,3 +832,126 @@ message QueryLatestMealMenuRecordsByClientIdsRpcRequest {
message
QueryLatestMealMenuRecordsByClientIdsRpcResponse
{
repeated
SingleMealMenuRecordRpcResponse
responses
=
1
;
}
// 停餐记录相关消息定义
message
SingleDinerMealSuspensionRecordRpcResponse
{
int32
id
=
1
;
int32
enterpriseId
=
2
;
int32
clientId
=
3
;
int32
classId
=
4
;
int32
dinerId
=
5
;
int64
startAt
=
6
;
int64
endAt
=
7
;
string
comment
=
8
;
int64
createdAt
=
9
;
int32
createdBy
=
10
;
int32
creationSource
=
11
;
int64
updatedAt
=
12
;
int32
updatedBy
=
13
;
int32
updateSource
=
14
;
}
message
GetDinerMealSuspensionRecordByIdRpcRequest
{
int64
id
=
1
;
}
message
GetDinerMealSuspensionRecordByIdRpcResponse
{
SingleDinerMealSuspensionRecordRpcResponse
response
=
1
;
}
message
GetDinerMealSuspensionRecordsByIdsRpcRequest
{
repeated
int32
ids
=
1
;
}
message
GetDinerMealSuspensionRecordsByIdsRpcResponse
{
repeated
SingleDinerMealSuspensionRecordRpcResponse
responses
=
1
;
}
message
QueryDinerMealSuspensionRecordsByConditionRpcRequest
{
int32
enterpriseId
=
1
;
bool
shouldFilterClientIds
=
2
;
repeated
int32
clientIds
=
3
;
bool
shouldFilterClassIds
=
4
;
repeated
int32
classIds
=
5
;
bool
shouldFilterDinerIds
=
6
;
repeated
int32
dinerIds
=
7
;
bool
shouldFilterStartAt
=
8
;
int64
startAt
=
9
;
bool
shouldFilterEndAt
=
10
;
int64
endAt
=
11
;
}
message
QueryDinerMealSuspensionRecordsByConditionRpcResponse
{
repeated
SingleDinerMealSuspensionRecordRpcResponse
responses
=
1
;
}
message
CreateDinerMealSuspensionRecordRpcRequest
{
int32
enterpriseId
=
1
;
int32
createdBy
=
2
;
int32
creationSource
=
3
;
DinerMealSuspensionRecordCreation
creation
=
4
;
}
message
DinerMealSuspensionRecordCreation
{
int32
clientId
=
1
;
int32
classId
=
2
;
int32
dinerId
=
3
;
int64
startAt
=
4
;
int64
endAt
=
5
;
string
comment
=
6
;
}
message
CreateDinerMealSuspensionRecordRpcResponse
{
bool
isCreated
=
1
;
int32
id
=
2
;
}
message
UpdateDinerMealSuspensionRecordRpcRequest
{
int32
enterpriseId
=
1
;
int32
updatedBy
=
2
;
int32
updateSource
=
3
;
DinerMealSuspensionRecordModification
modification
=
4
;
}
message
DinerMealSuspensionRecordModification
{
int32
id
=
1
;
bool
shouldUpdateClientId
=
2
;
int32
clientId
=
3
;
bool
shouldUpdateClassId
=
4
;
int32
classId
=
5
;
bool
shouldUpdateDinerId
=
6
;
int32
dinerId
=
7
;
bool
shouldUpdateStartAt
=
8
;
int64
startAt
=
9
;
bool
shouldUpdateEndAt
=
10
;
int64
endAt
=
11
;
bool
shouldUpdateComment
=
12
;
string
comment
=
13
;
}
message
UpdateDinerMealSuspensionRecordRpcResponse
{
bool
isUpdated
=
1
;
}
message
DeleteDinerMealSuspensionRecordsByIdsRpcRequest
{
repeated
int32
ids
=
1
;
int32
enterpriseId
=
2
;
int32
updatedBy
=
3
;
int32
updateSource
=
4
;
}
message
DeleteDinerMealSuspensionRecordsRpcResponse
{
bool
isDeleted
=
1
;
}
message
BatchCreateDinerMealSuspensionRecordsRpcRequest
{
int32
enterpriseId
=
1
;
int32
createdBy
=
2
;
int32
creationSource
=
3
;
repeated
DinerMealSuspensionRecordCreation
creations
=
4
;
}
message
BatchCreateDinerMealSuspensionRecordsRpcResponse
{
bool
isCreated
=
1
;
repeated
int32
ids
=
2
;
}
...
...
Please
register
or
login
to post a comment