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
zhuyifan
2025-11-17 10:44:09 +0800
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
de053f16b1e3d577663c60c8951724dfb0edbc7a
de053f16
1 parent
32dce8b4
fix(order): optimize dish replacement logic and update payment transaction ID
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
996 additions
and
852 deletions
src/main/java/com/infoloop/tianting/controller/PayController.java
src/main/java/com/infoloop/tianting/model/bo/OrderDetailBO.java
src/main/java/com/infoloop/tianting/model/dto/OrderDbDTO.java
src/main/java/com/infoloop/tianting/model/dto/PayDTO.java
src/main/java/com/infoloop/tianting/model/dto/PaymentCallbackResult.java
src/main/java/com/infoloop/tianting/model/dto/SettlementDTO.java
src/main/java/com/infoloop/tianting/service/client/OrderServiceRpcClient.java
src/main/java/com/infoloop/tianting/service/client/PayServiceClient.java
src/main/java/com/infoloop/tianting/service/impl/SettlementServiceImpl.java
src/main/java/com/infoloop/tianting/utils/JsonUtil.java
src/main/proto/ClientCustomerOrderService.proto
src/main/java/com/infoloop/tianting/controller/PayController.java
View file @
de053f1
...
...
@@ -60,4 +60,5 @@ public class PayController {
public
String
cancel
(
@Valid
@RequestBody
PayDTO
.
PayRefundRequestDto
payRefundRequestDto
)
{
return
payServiceClient
.
orderPayRefund
(
payRefundRequestDto
);
}
}
\ No newline at end of file
...
...
src/main/java/com/infoloop/tianting/model/bo/OrderDetailBO.java
0 → 100644
View file @
de053f1
package
com
.
infoloop
.
tianting
.
model
.
bo
;
import
com.infoloop.tianting.clientcustomerorderservice.ServeStatusEnum
;
import
lombok.Data
;
@Data
public
class
OrderDetailBO
{
private
int
id
;
public
int
skuId
;
private
String
skuName
;
private
Integer
price
;
private
int
count
;
private
String
adjustSkuRemark
;
private
ServeStatusEnum
serveStatus
;
}
src/main/java/com/infoloop/tianting/model/dto/OrderDbDTO.java
View file @
de053f1
...
...
@@ -520,6 +520,7 @@ public class OrderDbDTO {
private
Integer
count
;
private
String
adjustSkuRemark
;
private
String
serveStatus
;
private
Integer
price
;
}
...
...
@@ -730,6 +731,10 @@ public class OrderDbDTO {
@Builder
.
Default
private
Boolean
shouldUpdateServeStatus
=
false
;
@ApiModelProperty
(
value
=
"价格"
)
@Builder
.
Default
private
Integer
price
=
null
;
@ApiModelProperty
(
value
=
"出餐状态: 默认未出餐=1; 不出餐=2; 已出餐=3"
)
@Builder
.
Default
private
ServeStatusEnum
serveStatus
=
ServeStatusEnum
.
SERVE_NOT_START
;
...
...
src/main/java/com/infoloop/tianting/model/dto/PayDTO.java
View file @
de053f1
...
...
@@ -9,6 +9,8 @@ import lombok.Builder;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
import
java.util.List
;
@Data
@ApiModel
(
description
=
"支付DTO"
)
public
class
PayDTO
{
...
...
@@ -31,6 +33,7 @@ public class PayDTO {
@AllArgsConstructor
public
static
class
PayRefundRequestDto
{
private
Integer
orderId
;
private
List
<
Integer
>
orderDetailIds
;
private
String
hospitalCode
;
}
...
...
src/main/java/com/infoloop/tianting/model/dto/PaymentCallbackResult.java
View file @
de053f1
...
...
@@ -18,6 +18,9 @@ public class PaymentCallbackResult {
@JacksonXmlProperty
(
localName
=
"TransSN"
)
private
String
transSN
;
@JacksonXmlProperty
(
localName
=
"TradeReferenceNo"
)
private
String
tradeReferenceNo
;
@JacksonXmlProperty
(
localName
=
"TransType"
)
private
String
transType
;
...
...
src/main/java/com/infoloop/tianting/model/dto/SettlementDTO.java
View file @
de053f1
...
...
@@ -103,6 +103,8 @@ public class SettlementDTO {
private
String
remark
;
private
String
avoidRemark
;
private
String
onlinePay
;
private
String
operationType
;
private
String
transactionId
;
}
@Data
...
...
src/main/java/com/infoloop/tianting/service/client/OrderServiceRpcClient.java
View file @
de053f1
...
...
@@ -22,6 +22,8 @@ import com.infoloop.tianting.clientcustomerorderservice.GetClientCustomerOrderBy
import
com.infoloop.tianting.clientcustomerorderservice.GetClientCustomerOrderDetailsByIdsRpcRequest
;
import
com.infoloop.tianting.clientcustomerorderservice.GetClientCustomerOrderDetailsByOrderIdsRpcRequest
;
import
com.infoloop.tianting.clientcustomerorderservice.GetClientCustomerOrdersByCustomerIdRpcRequest
;
import
com.infoloop.tianting.clientcustomerorderservice.GetOrderOperationRecordsByOrderIdsRequest
;
import
com.infoloop.tianting.clientcustomerorderservice.GetOrderOperationRecordsByOrderIdsResponse
;
import
com.infoloop.tianting.clientcustomerorderservice.MealDetail
;
import
com.infoloop.tianting.clientcustomerorderservice.OnlinePayEnum
;
import
com.infoloop.tianting.clientcustomerorderservice.OrderOperationRecordCreation
;
...
...
@@ -240,8 +242,10 @@ public class OrderServiceRpcClient {
final
var
operator
=
operatorServiceRpcClient
.
getCOperatorById
(
operatorLoginInfo
.
getId
());
final
var
idsOfNeedUpdateMenuDetails
=
new
ArrayList
<
Integer
>();
final
var
idsOfAddCount
=
new
ArrayList
<
Integer
>();
final
var
idsOfNoReject
=
new
ArrayList
<
Integer
>();
List
<
OrderDetailDto
>
originalOrderDetails
=
new
ArrayList
<>();
List
<
OrderDetailDto
>
newOrderDetails
;
final
var
orderDetailsMap
=
orderDetailBatchUpdateDto
.
getDetails
().
stream
().
collect
(
Collectors
.
toMap
(
OrderDbDTO
.
OrderDetailUpdateDto
::
getId
,
Function
.
identity
()));
final
var
modifications
=
orderDetailBatchUpdateDto
.
getDetails
().
stream
().
map
(
d
->
{
var
mealDetail
=
MealDetail
.
newBuilder
().
build
();
Integer
menuDetailId
=
0
;
...
...
@@ -280,9 +284,11 @@ public class OrderServiceRpcClient {
.
build
();
}
}
ServeStatusEnum
serveStatus
=
ServeStatusEnum
.
UNKNOWN_SERVE_STATUS
;
if
(
d
.
getShouldUpdateServeStatus
())
{
if
(
d
.
getServeStatus
()
==
ServeStatusEnum
.
SERVE_REJECT
)
{
idsOfNoReject
.
add
(
d
.
getId
());
}
serveStatus
=
d
.
getServeStatus
();
}
Integer
count
=
0
;
...
...
@@ -319,7 +325,8 @@ public class OrderServiceRpcClient {
.
build
();
final
var
totalIds
=
new
ArrayList
<>(
idsOfNeedUpdateMenuDetails
);
totalIds
.
addAll
(
idsOfAddCount
);
if
(!
idsOfNeedUpdateMenuDetails
.
isEmpty
()
||
!
idsOfAddCount
.
isEmpty
())
{
totalIds
.
addAll
(
idsOfNoReject
);
if
(!
totalIds
.
isEmpty
())
{
final
var
orgionalResponseList
=
getClientCustomerOrderDetailsByIds
(
totalIds
);
originalOrderDetails
=
orgionalResponseList
.
stream
().
map
(
d
->
OrderDetailDto
.
builder
()
.
id
(
d
.
getId
())
...
...
@@ -357,7 +364,7 @@ public class OrderServiceRpcClient {
}
final
var
res
=
orderServiceRpcBlockingStub
.
batchUpdateClientCustomerOrderDetails
(
request
);
if
(
res
.
getIsUpdated
())
{
if
(!
idsOfNeedUpdateMenuDetails
.
isEmpty
()
||
!
idsOfAddCount
.
isEmpty
())
{
if
(!
totalIds
.
isEmpty
())
{
final
var
newResponseList
=
getClientCustomerOrderDetailsByIds
(
totalIds
);
newOrderDetails
=
newResponseList
.
stream
().
map
(
d
->
OrderDetailDto
.
builder
()
...
...
@@ -392,15 +399,21 @@ public class OrderServiceRpcClient {
.
updateSource
(
d
.
getUpdateSource
().
getNumber
())
.
updatedAt
(
DateUtil
.
formatDate
(
d
.
getUpdatedAt
()))
.
updatedBy
(
d
.
getUpdatedBy
())
.
build
()).
collect
(
Collectors
.
toList
()
);
.
build
()).
toList
(
);
// 替换菜品的操作记录
List
<
SingleOperationDto
>
operations
=
new
ArrayList
<>();
for
(
OrderDetailDto
originalDetail
:
originalOrderDetails
)
{
if
(!
totalIds
.
contains
(
originalDetail
.
getId
()))
{
continue
;
}
final
var
orderDetailUpdateDto
=
orderDetailsMap
.
get
(
originalDetail
.
getId
());
OrderOperationType
orderOperationType
=
OrderOperationType
.
UNKNOWN_OPERATION_TYPE
;
if
(
idsOfNeedUpdateMenuDetails
.
contains
(
originalDetail
.
getId
()))
{
orderOperationType
=
OrderOperationType
.
REPLACE_DISHES
;
}
else
if
(
idsOfAddCount
.
contains
(
originalDetail
.
getId
()))
{
orderOperationType
=
OrderOperationType
.
ADD_DISHES
;
}
else
if
(
idsOfNoReject
.
contains
(
originalDetail
.
getId
()))
{
orderOperationType
=
OrderOperationType
.
NOT_SERVE
;
}
String
originalDetailStr
;
String
newDetailStr
=
""
;
...
...
@@ -413,6 +426,7 @@ public class OrderServiceRpcClient {
.
count
(
newDetail
.
get
().
getCount
())
.
adjustSkuRemark
(
newDetail
.
get
().
getAdjustSkuRemark
())
.
serveStatus
(
newDetail
.
get
().
getServeStatus
().
name
())
.
price
(
orderDetailUpdateDto
.
getPrice
()
==
null
?
newDetail
.
get
().
getPrice
()
:
orderDetailUpdateDto
.
getPrice
())
.
build
();
newDetailStr
=
JsonUtil
.
writeAsJson
(
List
.
of
(
newOrderDetailOperation
));
}
...
...
@@ -423,6 +437,7 @@ public class OrderServiceRpcClient {
.
count
(
originalDetail
.
getCount
())
.
adjustSkuRemark
(
originalDetail
.
getAdjustSkuRemark
())
.
serveStatus
(
originalDetail
.
getServeStatus
().
name
())
.
price
(
originalDetail
.
getPrice
())
.
build
();
originalDetailStr
=
JsonUtil
.
writeAsJson
(
List
.
of
(
originalOrderDetailOperation
));
final
var
operation
=
SingleOperationDto
.
builder
()
...
...
@@ -471,7 +486,6 @@ public class OrderServiceRpcClient {
.
setCreationSource
(
batchOperationDto
.
getCreationSource
())
.
build
();
return
orderServiceRpcBlockingStub
.
batchCreateOrderOperationRecords
(
request
);
}
public
QueryClientCustomerOrdersByPaginationRpcResponse
queryClientCustomerOrdersByPagination
(
QueryOrderByPaginationDto
queryOrderDto
)
{
...
...
@@ -489,6 +503,14 @@ public class OrderServiceRpcClient {
return
orderServiceRpcBlockingStub
.
queryClientCustomerOrdersByPagination
(
request
);
}
public
GetOrderOperationRecordsByOrderIdsResponse
getOrderOperationRecordsByOrderIds
(
int
enterpriseId
,
List
<
Integer
>
orderIds
)
{
final
var
request
=
GetOrderOperationRecordsByOrderIdsRequest
.
newBuilder
()
.
setEnterpriseId
(
enterpriseId
)
.
addAllOrderIds
(
orderIds
)
.
build
();
return
orderServiceRpcBlockingStub
.
getOrderOperationRecordsByOrderIds
(
request
);
}
public
QueryClientCustomerOrdersByConditionRpcResponse
queryClientCustomerOrdersByCondition
(
OrderDbDTO
.
QueryOrderDto
queryOrderDto
)
{
final
var
request
=
QueryClientCustomerOrdersByConditionRpcRequest
.
newBuilder
()
.
setShouldFilterStatus
(
true
)
...
...
src/main/java/com/infoloop/tianting/service/client/PayServiceClient.java
View file @
de053f1
...
...
@@ -38,6 +38,8 @@ import lombok.RequiredArgsConstructor;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.codec.binary.Base64
;
import
org.apache.commons.codec.digest.DigestUtils
;
import
org.apache.commons.collections4.CollectionUtils
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.http.HttpEntity
;
import
org.springframework.http.HttpHeaders
;
...
...
@@ -66,333 +68,338 @@ import java.util.stream.Collectors;
@RequiredArgsConstructor
(
onConstructor
=
@__
(
@Autowired
))
public
class
PayServiceClient
{
private
final
RestTemplate
restTemplate
;
private
final
RestTemplate
restTemplate
;
private
final
BusinessConfig
businessConfig
;
private
final
BusinessConfig
businessConfig
;
private
final
OrderServiceRpcClient
orderServiceRpcClient
;
private
final
OrderServiceRpcClient
orderServiceRpcClient
;
private
final
ClientResourceTagServiceRpcClient
clientResourceTagServiceRpcClient
;
private
final
ClientResourceTagServiceRpcClient
clientResourceTagServiceRpcClient
;
private
final
EnterpriseResourceServiceRpcClient
enterpriseResourceServiceRpcClient
;
private
final
EnterpriseResourceServiceRpcClient
enterpriseResourceServiceRpcClient
;
private
final
XmlMapper
xmlMapper
=
new
XmlMapper
();
private
final
XmlMapper
xmlMapper
=
new
XmlMapper
();
public
PayResponseDto
payInform
(
PayInformRequestDto
payRequestDto
)
{
final
var
orderById
=
orderServiceRpcClient
.
getOrderById
(
Integer
.
valueOf
(
payRequestDto
.
getOrderId
()));
if
(
orderById
==
null
||
orderById
.
getPayStatus
()
==
PayStatusEnum
.
PAY_CANCELED
||
orderById
.
getStatus
()
==
OrderStatusEnum
.
ORDER_CANCELED
)
{
log
.
info
(
"Order {} not found or canceled, skipping."
,
payRequestDto
.
getOrderId
());
throw
ClientEndExceptions
.
BusinessException
.
build
(
ErrorCodeEnum
.
ORDER_CANCEL
);
}
String
url
=
MessageFormat
.
format
(
businessConfig
.
getPayUrl
(),
businessConfig
.
getPayClientId
());
String
requestDate
=
DateUtil
.
formatDate
(
LocalDateTime
.
now
(),
DateUtil
.
YMDHMS
);
ThirdPartyPayInformRequestDto
jsonData
=
buildRequestData
(
payRequestDto
,
requestDate
);
String
jsonDataString
;
try
{
ObjectMapper
objectMapper
=
new
ObjectMapper
();
objectMapper
.
configure
(
DeserializationFeature
.
FAIL_ON_UNKNOWN_PROPERTIES
,
false
);
objectMapper
.
setSerializationInclusion
(
JsonInclude
.
Include
.
NON_NULL
);
objectMapper
.
setPropertyNamingStrategy
(
new
PropertyNamingStrategies
.
UpperCamelCaseStrategy
());
jsonDataString
=
objectMapper
.
writeValueAsString
(
jsonData
);
}
catch
(
JsonProcessingException
e
)
{
log
.
error
(
"Failed to serialize request data"
,
e
);
throw
new
IllegalArgumentException
(
"支付信息获取失败: JSON 解析错误"
);
public
PayResponseDto
payInform
(
PayInformRequestDto
payRequestDto
)
{
final
var
orderById
=
orderServiceRpcClient
.
getOrderById
(
Integer
.
valueOf
(
payRequestDto
.
getOrderId
()));
if
(
orderById
==
null
||
orderById
.
getPayStatus
()
==
PayStatusEnum
.
PAY_CANCELED
||
orderById
.
getStatus
()
==
OrderStatusEnum
.
ORDER_CANCELED
)
{
log
.
info
(
"Order {} not found or canceled, skipping."
,
payRequestDto
.
getOrderId
());
throw
ClientEndExceptions
.
BusinessException
.
build
(
ErrorCodeEnum
.
ORDER_CANCEL
);
}
String
url
=
MessageFormat
.
format
(
businessConfig
.
getPayUrl
(),
businessConfig
.
getPayClientId
());
String
requestDate
=
DateUtil
.
formatDate
(
LocalDateTime
.
now
(),
DateUtil
.
YMDHMS
);
ThirdPartyPayInformRequestDto
jsonData
=
buildRequestData
(
payRequestDto
,
requestDate
);
String
jsonDataString
;
try
{
ObjectMapper
objectMapper
=
new
ObjectMapper
();
objectMapper
.
configure
(
DeserializationFeature
.
FAIL_ON_UNKNOWN_PROPERTIES
,
false
);
objectMapper
.
setSerializationInclusion
(
JsonInclude
.
Include
.
NON_NULL
);
objectMapper
.
setPropertyNamingStrategy
(
new
PropertyNamingStrategies
.
UpperCamelCaseStrategy
());
jsonDataString
=
objectMapper
.
writeValueAsString
(
jsonData
);
}
catch
(
JsonProcessingException
e
)
{
log
.
error
(
"Failed to serialize request data"
,
e
);
throw
new
IllegalArgumentException
(
"支付信息获取失败: JSON 解析错误"
);
}
HttpEntity
<
String
>
requestEntity
=
new
HttpEntity
<>(
jsonDataString
,
createHeaders
());
log
.
info
(
"payInform request: {}"
,
jsonDataString
);
ResponseEntity
<
String
>
responseEntity
=
restTemplate
.
exchange
(
url
,
HttpMethod
.
POST
,
requestEntity
,
String
.
class
);
return
processResponse
(
responseEntity
);
}
HttpEntity
<
String
>
requestEntity
=
new
HttpEntity
<>(
jsonDataString
,
createHeaders
());
log
.
info
(
"payInform request: {}"
,
jsonDataString
);
ResponseEntity
<
String
>
responseEntity
=
restTemplate
.
exchange
(
url
,
HttpMethod
.
POST
,
requestEntity
,
String
.
class
);
return
processResponse
(
responseEntity
);
}
private
ThirdPartyPayInformRequestDto
buildRequestData
(
PayInformRequestDto
payRequestDto
,
String
requestDate
)
{
ThirdPartyPayInformRequestDto
jsonData
=
new
ThirdPartyPayInformRequestDto
();
jsonData
.
setClientId
(
businessConfig
.
getPayClientId
());
jsonData
.
setTradeId
(
payRequestDto
.
getOrderId
());
jsonData
.
setRequestDate
(
requestDate
);
jsonData
.
setRequestSource
(
"OFWXApplet"
);
jsonData
.
setPayerOpenId
(
LoginContextHolder
.
getOpenId
());
jsonData
.
setHospitalCode
(
payRequestDto
.
getHospitalCode
());
jsonData
.
setPID
(
LoginContextHolder
.
getOpenId
());
jsonData
.
setRemark
(
""
);
jsonData
.
setTransAmount
(
payRequestDto
.
getPrice
());
jsonData
.
setTradeDesc
(
""
);
jsonData
.
setSign
(
EncryptionUtil
.
sha1Encryption
(
businessConfig
.
getPayClientId
()
+
payRequestDto
.
getOrderId
()
+
requestDate
+
businessConfig
.
getPayClientId
()));
return
jsonData
;
}
private
HttpHeaders
createHeaders
()
{
HttpHeaders
headers
=
new
HttpHeaders
();
headers
.
setContentType
(
MediaType
.
APPLICATION_JSON
);
return
headers
;
}
private
PayResponseDto
processResponse
(
ResponseEntity
<
String
>
responseEntity
)
{
if
(!
responseEntity
.
getStatusCode
().
is2xxSuccessful
()
||
responseEntity
.
getBody
()
==
null
)
{
log
.
error
(
"payInform failed with response: {}"
,
responseEntity
.
getBody
());
throw
new
IllegalArgumentException
(
"支付信息获取失败"
);
}
try
{
log
.
info
(
"processResponse response: {}"
,
responseEntity
.
getBody
());
return
xmlMapper
.
readValue
(
responseEntity
.
getBody
(),
PayResponseDto
.
class
);
}
catch
(
Exception
e
)
{
log
.
error
(
"Failed to parse XML response"
,
e
);
throw
new
RuntimeException
(
"支付信息结果解析失败"
,
e
);
private
ThirdPartyPayInformRequestDto
buildRequestData
(
PayInformRequestDto
payRequestDto
,
String
requestDate
)
{
ThirdPartyPayInformRequestDto
jsonData
=
new
ThirdPartyPayInformRequestDto
();
jsonData
.
setClientId
(
businessConfig
.
getPayClientId
());
jsonData
.
setTradeId
(
payRequestDto
.
getOrderId
());
jsonData
.
setRequestDate
(
requestDate
);
jsonData
.
setRequestSource
(
"OFWXApplet"
);
jsonData
.
setPayerOpenId
(
LoginContextHolder
.
getOpenId
());
jsonData
.
setHospitalCode
(
payRequestDto
.
getHospitalCode
());
jsonData
.
setPID
(
LoginContextHolder
.
getOpenId
());
jsonData
.
setRemark
(
""
);
jsonData
.
setTransAmount
(
payRequestDto
.
getPrice
());
jsonData
.
setTradeDesc
(
""
);
jsonData
.
setSign
(
EncryptionUtil
.
sha1Encryption
(
businessConfig
.
getPayClientId
()
+
payRequestDto
.
getOrderId
()
+
requestDate
+
businessConfig
.
getPayClientId
()));
return
jsonData
;
}
}
public
boolean
callback
(
PaymentCallbackDTO
paymentCallbackDTO
)
{
log
.
info
(
"callback request received: {}"
,
paymentCallbackDTO
);
try
{
final
var
paymentCallbackResult
=
xmlMapper
.
readValue
(
paymentCallbackDTO
.
getPayResult
(),
PaymentCallbackResult
.
class
);
log
.
info
(
"Parsed paymentCallbackResult: {}"
,
paymentCallbackResult
);
final
var
orderId
=
Integer
.
parseInt
(
paymentCallbackResult
.
getTradeId
());
final
var
orderById
=
orderServiceRpcClient
.
getOrderById
(
orderId
);
if
(
orderById
==
null
)
{
log
.
error
(
"Order not found, orderId: {}"
,
orderId
);
return
false
;
}
log
.
info
(
"Order callback, orderId: {}"
,
orderId
);
private
HttpHeaders
createHeaders
()
{
HttpHeaders
headers
=
new
HttpHeaders
();
headers
.
setContentType
(
MediaType
.
APPLICATION_JSON
);
return
headers
;
}
final
var
transType
=
paymentCallbackResult
.
getTransType
();
if
(
transType
.
equals
(
"00"
))
{
if
(
orderById
.
getPayStatus
()
!=
PayStatusEnum
.
TO_PAY
&&
orderById
.
getPayStatus
()
!=
PayStatusEnum
.
IN_PROGRESS
)
{
log
.
error
(
"Order status is not TO_PAY or IN_PROGRESS, orderId: {}"
,
orderId
);
return
true
;
private
PayResponseDto
processResponse
(
ResponseEntity
<
String
>
responseEntity
)
{
if
(!
responseEntity
.
getStatusCode
().
is2xxSuccessful
()
||
responseEntity
.
getBody
()
==
null
)
{
log
.
error
(
"payInform failed with response: {}"
,
responseEntity
.
getBody
());
throw
new
IllegalArgumentException
(
"支付信息获取失败"
);
}
long
payTime
;
try
{
payTime
=
DateUtil
.
parseDate
(
paymentCallbackResult
.
getTransDate
(),
"yyyyMMddHHmmss"
).
getTime
(
);
}
catch
(
Parse
Exception
e
)
{
log
.
error
(
"Failed to parse TransDate: {}"
,
paymentCallbackResult
.
getTransDate
()
,
e
);
throw
new
IllegalArgumentException
(
"支付时间格式错误: "
+
paymentCallbackResult
.
getTransDate
()
,
e
);
log
.
info
(
"processResponse response: {}"
,
responseEntity
.
getBody
());
return
xmlMapper
.
readValue
(
responseEntity
.
getBody
(),
PayResponseDto
.
class
);
}
catch
(
Exception
e
)
{
log
.
error
(
"Failed to parse XML response"
,
e
);
throw
new
RuntimeException
(
"支付信息结果解析失败"
,
e
);
}
BigDecimal
realAmount
;
}
public
boolean
callback
(
PaymentCallbackDTO
paymentCallbackDTO
)
{
log
.
info
(
"callback request received: {}"
,
paymentCallbackDTO
);
try
{
realAmount
=
Convert
.
toBigDecimal
(
paymentCallbackResult
.
getRealAmount
());
if
(
realAmount
==
null
)
{
throw
new
NumberFormatException
(
"RealAmount is null or empty"
);
}
}
catch
(
NumberFormatException
e
)
{
log
.
error
(
"Invalid RealAmount value: {}"
,
paymentCallbackResult
.
getRealAmount
(),
e
);
throw
new
IllegalArgumentException
(
"支付金额错误: "
+
paymentCallbackResult
.
getRealAmount
(),
e
);
}
final
var
build
=
ClientCustomerOrderModification
.
newBuilder
()
.
setId
(
orderId
)
.
setShouldUpdatePayTime
(
true
)
.
setPayTime
(
payTime
)
.
setShouldUpdatePayPrice
(
true
)
.
setPayPrice
(
realAmount
.
multiply
(
new
BigDecimal
(
"100"
)).
intValue
())
.
setShouldUpdatePayStatus
(
true
)
.
setPayStatus
(
PayStatusEnum
.
SUCCEED
)
.
setShouldUpdateStatus
(
true
)
.
setStatus
(
OrderStatusEnum
.
PREPARING
)
.
setShouldUpdateTransactionId
(
true
)
.
setTransactionId
(
paymentCallbackResult
.
getTransSN
())
.
build
();
final
var
updateResponse
=
orderServiceRpcClient
.
updateClientCustomerOrderPaymentResult
(
orderById
,
build
);
log
.
info
(
"callback updateClientCustomerOrder result: {}"
,
updateResponse
.
getIsUpdated
());
if
(
updateResponse
.
getIsUpdated
())
{
String
createdAt
=
Instant
.
ofEpochMilli
(
orderById
.
getCreatedAt
())
.
atZone
(
DateUtil
.
CHINA_ZONE
)
.
minusHours
(
8
)
.
format
(
DateUtil
.
Y_M_D_H_M_S
);
String
payTimed
=
Instant
.
ofEpochMilli
(
orderById
.
getPayTime
())
.
atZone
(
DateUtil
.
CHINA_ZONE
)
.
minusHours
(
8
)
.
format
(
DateUtil
.
Y_M_D_H_M_S
);
final
var
orderPaymentSuccessData
=
OrderPaymentSuccessData
.
builder
()
.
orderId
(
orderById
.
getId
())
.
orderCode
(
orderById
.
getOrderCode
())
.
createTime
(
createdAt
)
.
payTime
(
payTimed
)
.
build
();
final
var
data
=
SocketMessage
.<
OrderPaymentSuccessData
>
builder
()
.
type
(
MessageTypeEnum
.
ORDER
)
.
noticeType
(
NoticeTypeEnum
.
ORDER_PAYMENT_SUCCESS
)
.
subject
(
NoticeTypeEnum
.
ORDER_PAYMENT_SUCCESS
.
getDescription
())
.
message
(
"您的订单:"
+
orderById
.
getOrderCode
()
+
" 支付成功啦,快去查看吧~"
)
.
data
(
orderPaymentSuccessData
)
.
build
();
WebSocketServer
.
sendMessageToUser
(
UserSessionKey
.
builder
()
.
userId
(
orderById
.
getOpenId
())
.
userType
(
UserTypeEnum
.
MICRO
)
.
build
(),
data
);
if
(
LocalDate
.
now
().
equals
(
DateUtil
.
toLocalDate
(
orderById
.
getMealTime
())))
{
final
var
orderCreateSuccessData
=
OrderCreateSuccessData
.
builder
().
orderId
(
orderById
.
getId
()).
build
();
final
var
createOrderData
=
SocketMessage
.<
OrderCreateSuccessData
>
builder
()
.
type
(
MessageTypeEnum
.
ORDER
)
.
noticeType
(
NoticeTypeEnum
.
ORDER_CREATED
)
.
subject
(
NoticeTypeEnum
.
ORDER_CREATED
.
getDescription
())
.
message
(
"有新的订单下单成功啦,快去查看吧~"
)
.
data
(
orderCreateSuccessData
)
.
build
();
final
var
clientOperatorIds
=
clientResourceTagServiceRpcClient
.
getOperatorIdsByStallIds
(
List
.
of
(
orderById
.
getStallId
())).
stream
()
.
map
(
SingleResourceLabelEntityRefsResponse:
:
getEntityId
)
.
distinct
()
.
collect
(
Collectors
.
toList
());
final
var
enterpriseOperatorIds
=
enterpriseResourceServiceRpcClient
.
getOperatorIdsByStallId
(
orderById
.
getEnterpriseId
(),
orderById
.
getStallId
());
final
var
userAuthData
=
new
ArrayList
<
UserAuthData
>();
userAuthData
.
addAll
(
clientOperatorIds
.
stream
()
.
map
(
e
->
UserAuthData
.
builder
()
.
operatorId
(
e
)
.
userType
(
UserTypeEnum
.
CLIENT
)
.
build
())
.
collect
(
Collectors
.
toList
()));
userAuthData
.
addAll
(
enterpriseOperatorIds
.
stream
()
.
map
(
e
->
UserAuthData
.
builder
().
operatorId
(
e
).
userType
(
UserTypeEnum
.
KDS
).
build
())
.
collect
(
Collectors
.
toList
()));
log
.
info
(
"received userAuthData:{}"
,
JsonUtil
.
writeAsJson
(
userAuthData
));
try
{
WebSocketServer
.
sendMessageByUserTypes
(
List
.
of
(
UserTypeEnum
.
CLIENT
,
UserTypeEnum
.
KDS
),
userAuthData
,
createOrderData
);
}
catch
(
IOException
e
)
{
log
.
error
(
"Failed to send message to user"
,
e
);
final
var
paymentCallbackResult
=
xmlMapper
.
readValue
(
paymentCallbackDTO
.
getPayResult
(),
PaymentCallbackResult
.
class
);
log
.
info
(
"Parsed paymentCallbackResult: {}"
,
paymentCallbackResult
);
final
var
orderId
=
Integer
.
parseInt
(
paymentCallbackResult
.
getTradeId
());
final
var
orderById
=
orderServiceRpcClient
.
getOrderById
(
orderId
);
if
(
orderById
==
null
)
{
log
.
error
(
"Order not found, orderId: {}"
,
orderId
);
return
false
;
}
}
log
.
info
(
"Order callback, orderId: {}"
,
orderId
);
final
var
transType
=
paymentCallbackResult
.
getTransType
();
if
(
transType
.
equals
(
"00"
))
{
if
(
orderById
.
getPayStatus
()
!=
PayStatusEnum
.
TO_PAY
&&
orderById
.
getPayStatus
()
!=
PayStatusEnum
.
IN_PROGRESS
)
{
log
.
error
(
"Order status is not TO_PAY or IN_PROGRESS, orderId: {}"
,
orderId
);
return
true
;
}
long
payTime
;
try
{
payTime
=
DateUtil
.
parseDate
(
paymentCallbackResult
.
getTransDate
(),
"yyyyMMddHHmmss"
).
getTime
();
}
catch
(
ParseException
e
)
{
log
.
error
(
"Failed to parse TransDate: {}"
,
paymentCallbackResult
.
getTransDate
(),
e
);
throw
new
IllegalArgumentException
(
"支付时间格式错误: "
+
paymentCallbackResult
.
getTransDate
(),
e
);
}
BigDecimal
realAmount
;
try
{
realAmount
=
Convert
.
toBigDecimal
(
paymentCallbackResult
.
getRealAmount
());
if
(
realAmount
==
null
)
{
throw
new
NumberFormatException
(
"RealAmount is null or empty"
);
}
}
catch
(
NumberFormatException
e
)
{
log
.
error
(
"Invalid RealAmount value: {}"
,
paymentCallbackResult
.
getRealAmount
(),
e
);
throw
new
IllegalArgumentException
(
"支付金额错误: "
+
paymentCallbackResult
.
getRealAmount
(),
e
);
}
final
var
build
=
ClientCustomerOrderModification
.
newBuilder
()
.
setId
(
orderId
)
.
setShouldUpdatePayTime
(
true
)
.
setPayTime
(
payTime
)
.
setShouldUpdatePayPrice
(
true
)
.
setPayPrice
(
realAmount
.
multiply
(
new
BigDecimal
(
"100"
)).
intValue
())
.
setShouldUpdatePayStatus
(
true
)
.
setPayStatus
(
PayStatusEnum
.
SUCCEED
)
.
setShouldUpdateStatus
(
true
)
.
setStatus
(
OrderStatusEnum
.
PREPARING
)
.
setShouldUpdateTransactionId
(
StringUtils
.
isNotEmpty
(
paymentCallbackResult
.
getTradeReferenceNo
()))
.
setTransactionId
(
StringUtils
.
isNotEmpty
(
paymentCallbackResult
.
getTradeReferenceNo
())
?
paymentCallbackResult
.
getTradeReferenceNo
()
:
""
)
.
build
();
final
var
updateResponse
=
orderServiceRpcClient
.
updateClientCustomerOrderPaymentResult
(
orderById
,
build
);
log
.
info
(
"callback updateClientCustomerOrder result: {}"
,
updateResponse
.
getIsUpdated
());
if
(
updateResponse
.
getIsUpdated
())
{
String
createdAt
=
Instant
.
ofEpochMilli
(
orderById
.
getCreatedAt
())
.
atZone
(
DateUtil
.
CHINA_ZONE
)
.
minusHours
(
8
)
.
format
(
DateUtil
.
Y_M_D_H_M_S
);
String
payTimed
=
Instant
.
ofEpochMilli
(
orderById
.
getPayTime
())
.
atZone
(
DateUtil
.
CHINA_ZONE
)
.
minusHours
(
8
)
.
format
(
DateUtil
.
Y_M_D_H_M_S
);
final
var
orderPaymentSuccessData
=
OrderPaymentSuccessData
.
builder
()
.
orderId
(
orderById
.
getId
())
.
orderCode
(
orderById
.
getOrderCode
())
.
createTime
(
createdAt
)
.
payTime
(
payTimed
)
.
build
();
final
var
data
=
SocketMessage
.<
OrderPaymentSuccessData
>
builder
()
.
type
(
MessageTypeEnum
.
ORDER
)
.
noticeType
(
NoticeTypeEnum
.
ORDER_PAYMENT_SUCCESS
)
.
subject
(
NoticeTypeEnum
.
ORDER_PAYMENT_SUCCESS
.
getDescription
())
.
message
(
"您的订单:"
+
orderById
.
getOrderCode
()
+
" 支付成功啦,快去查看吧~"
)
.
data
(
orderPaymentSuccessData
)
.
build
();
WebSocketServer
.
sendMessageToUser
(
UserSessionKey
.
builder
()
.
userId
(
orderById
.
getOpenId
())
.
userType
(
UserTypeEnum
.
MICRO
)
.
build
(),
data
);
if
(
LocalDate
.
now
().
equals
(
DateUtil
.
toLocalDate
(
orderById
.
getMealTime
())))
{
final
var
orderCreateSuccessData
=
OrderCreateSuccessData
.
builder
().
orderId
(
orderById
.
getId
()).
build
();
final
var
createOrderData
=
SocketMessage
.<
OrderCreateSuccessData
>
builder
()
.
type
(
MessageTypeEnum
.
ORDER
)
.
noticeType
(
NoticeTypeEnum
.
ORDER_CREATED
)
.
subject
(
NoticeTypeEnum
.
ORDER_CREATED
.
getDescription
())
.
message
(
"有新的订单下单成功啦,快去查看吧~"
)
.
data
(
orderCreateSuccessData
)
.
build
();
final
var
clientOperatorIds
=
clientResourceTagServiceRpcClient
.
getOperatorIdsByStallIds
(
List
.
of
(
orderById
.
getStallId
())).
stream
()
.
map
(
SingleResourceLabelEntityRefsResponse:
:
getEntityId
)
.
distinct
()
.
collect
(
Collectors
.
toList
());
final
var
enterpriseOperatorIds
=
enterpriseResourceServiceRpcClient
.
getOperatorIdsByStallId
(
orderById
.
getEnterpriseId
(),
orderById
.
getStallId
());
final
var
userAuthData
=
new
ArrayList
<
UserAuthData
>();
userAuthData
.
addAll
(
clientOperatorIds
.
stream
()
.
map
(
e
->
UserAuthData
.
builder
()
.
operatorId
(
e
)
.
userType
(
UserTypeEnum
.
CLIENT
)
.
build
())
.
collect
(
Collectors
.
toList
()));
userAuthData
.
addAll
(
enterpriseOperatorIds
.
stream
()
.
map
(
e
->
UserAuthData
.
builder
().
operatorId
(
e
).
userType
(
UserTypeEnum
.
KDS
).
build
())
.
collect
(
Collectors
.
toList
()));
log
.
info
(
"received userAuthData:{}"
,
JsonUtil
.
writeAsJson
(
userAuthData
));
try
{
WebSocketServer
.
sendMessageByUserTypes
(
List
.
of
(
UserTypeEnum
.
CLIENT
,
UserTypeEnum
.
KDS
),
userAuthData
,
createOrderData
);
}
catch
(
IOException
e
)
{
log
.
error
(
"Failed to send message to user"
,
e
);
}
}
}
return
updateResponse
.
getIsUpdated
();
}
else
{
final
var
build
=
ClientCustomerOrderModification
.
newBuilder
()
.
setId
(
orderId
)
.
setShouldUpdatePayStatus
(
true
)
.
setPayStatus
(
PayStatusEnum
.
REFUND
)
.
build
();
final
var
updateResponse
=
orderServiceRpcClient
.
updateClientCustomerOrderPaymentResult
(
orderById
,
build
);
log
.
info
(
"callback updateClientCustomerOrder result: {}"
,
updateResponse
.
getIsUpdated
());
return
updateResponse
.
getIsUpdated
();
}
}
catch
(
JsonProcessingException
e
)
{
log
.
error
(
"Failed to parse XML response, raw XML: {}"
,
paymentCallbackDTO
.
getPayResult
(),
e
);
throw
new
RuntimeException
(
"支付/退款通知结果解析失败"
,
e
);
}
catch
(
Exception
e
)
{
log
.
error
(
"Unexpected error in callback, request: {}"
,
paymentCallbackDTO
,
e
);
throw
new
RuntimeException
(
"支付/退款通知处理失败"
,
e
);
}
}
public
boolean
waiting
(
Integer
orderId
)
{
final
var
orderById
=
orderServiceRpcClient
.
getOrderById
(
orderId
);
if
(
orderById
==
null
)
{
log
.
error
(
"waiting Order not found, orderId: {}"
,
orderId
);
return
false
;
}
if
(
orderById
.
getPayStatus
()
!=
PayStatusEnum
.
TO_PAY
)
{
log
.
info
(
"waiting Order {} already processed, skipping."
,
orderId
);
return
false
;
}
return
updateResponse
.
getIsUpdated
();
}
else
{
final
var
build
=
ClientCustomerOrderModification
.
newBuilder
()
.
setId
(
orderId
)
.
setShouldUpdatePayStatus
(
true
)
.
setPayStatus
(
PayStatusEnum
.
REFUND
)
.
build
();
ClientCustomerOrderModification
.
newBuilder
()
.
setId
(
orderId
)
.
setShouldUpdatePayStatus
(
true
)
.
setPayStatus
(
PayStatusEnum
.
IN_PROGRESS
)
.
build
();
final
var
updateResponse
=
orderServiceRpcClient
.
updateClientCustomerOrderPaymentResult
(
orderById
,
build
);
log
.
info
(
"
callback
updateClientCustomerOrder result: {}"
,
updateResponse
.
getIsUpdated
());
orderServiceRpcClient
.
updateClientCustomerOrderPaymentResult
(
orderById
,
build
);
log
.
info
(
"
waiting
updateClientCustomerOrder result: {}"
,
updateResponse
.
getIsUpdated
());
return
updateResponse
.
getIsUpdated
();
}
}
catch
(
JsonProcessingException
e
)
{
log
.
error
(
"Failed to parse XML response, raw XML: {}"
,
paymentCallbackDTO
.
getPayResult
(),
e
);
throw
new
RuntimeException
(
"支付/退款通知结果解析失败"
,
e
);
}
catch
(
Exception
e
)
{
log
.
error
(
"Unexpected error in callback, request: {}"
,
paymentCallbackDTO
,
e
);
throw
new
RuntimeException
(
"支付/退款通知处理失败"
,
e
);
}
}
public
boolean
waiting
(
Integer
orderId
)
{
final
var
orderById
=
orderServiceRpcClient
.
getOrderById
(
orderId
);
if
(
orderById
==
null
)
{
log
.
error
(
"waiting Order not found, orderId: {}"
,
orderId
);
return
false
;
}
if
(
orderById
.
getPayStatus
()
!=
PayStatusEnum
.
TO_PAY
)
{
log
.
info
(
"waiting Order {} already processed, skipping."
,
orderId
);
return
false
;
}
final
var
build
=
ClientCustomerOrderModification
.
newBuilder
()
.
setId
(
orderId
)
.
setShouldUpdatePayStatus
(
true
)
.
setPayStatus
(
PayStatusEnum
.
IN_PROGRESS
)
.
build
();
final
var
updateResponse
=
orderServiceRpcClient
.
updateClientCustomerOrderPaymentResult
(
orderById
,
build
);
log
.
info
(
"waiting updateClientCustomerOrder result: {}"
,
updateResponse
.
getIsUpdated
());
return
updateResponse
.
getIsUpdated
();
}
public
String
orderPayRefund
(
PayRefundRequestDto
payRefundRequestDto
)
{
Integer
orderId
=
payRefundRequestDto
.
getOrderId
();
final
var
orderById
=
orderServiceRpcClient
.
getOrderById
(
orderId
);
if
(
orderById
==
null
)
{
log
.
error
(
"Order not found, orderId: {}"
,
orderId
);
throw
ClientEndExceptions
.
BusinessException
.
build
(
ErrorCodeEnum
.
ORDER_NOT_FOUND
);
}
if
(
orderById
.
getOnlinePay
()
!=
OnlinePayEnum
.
ONLINE
)
{
log
.
info
(
"Order {} is not online pay."
,
orderId
);
throw
ClientEndExceptions
.
BusinessException
.
build
(
ErrorCodeEnum
.
ORDER_NOT_ONLINE_PAY
);
}
if
(
orderById
.
getPayStatus
()
!=
PayStatusEnum
.
SUCCEED
)
{
log
.
info
(
"Order {} pay is not succeed."
,
orderId
);
throw
ClientEndExceptions
.
BusinessException
.
build
(
ErrorCodeEnum
.
ORDER_NOT_SUCCESS
);
}
LocalDate
today
=
LocalDate
.
now
();
LocalDate
tomorrow
=
today
.
plusDays
(
1
);
LocalDateTime
tomorrowZero
=
tomorrow
.
atStartOfDay
();
LocalDateTime
orderPayTime
=
DateUtil
.
toLocalDateTime
(
orderById
.
getPayTime
()).
minusHours
(
8
);
if
(!
orderPayTime
.
isBefore
(
tomorrowZero
))
{
log
.
info
(
"Order {} pay is beyond cancel time."
,
orderId
);
throw
ClientEndExceptions
.
BusinessException
.
build
(
ErrorCodeEnum
.
ORDER_PAY_REFUND_FAILED
);
}
public
String
orderPayRefund
(
PayRefundRequestDto
payRefundRequestDto
)
{
Integer
orderId
=
payRefundRequestDto
.
getOrderId
();
final
var
orderById
=
orderServiceRpcClient
.
getOrderById
(
orderId
);
if
(
orderById
==
null
)
{
log
.
error
(
"Order not found, orderId: {}"
,
orderId
);
throw
ClientEndExceptions
.
BusinessException
.
build
(
ErrorCodeEnum
.
ORDER_NOT_FOUND
);
}
if
(
orderById
.
getOnlinePay
()
!=
OnlinePayEnum
.
ONLINE
)
{
log
.
info
(
"Order {} is not online pay."
,
orderId
);
throw
ClientEndExceptions
.
BusinessException
.
build
(
ErrorCodeEnum
.
ORDER_NOT_ONLINE_PAY
);
}
if
(
orderById
.
getPayStatus
()
!=
PayStatusEnum
.
SUCCEED
)
{
log
.
info
(
"Order {} pay is not succeed."
,
orderId
);
throw
ClientEndExceptions
.
BusinessException
.
build
(
ErrorCodeEnum
.
ORDER_NOT_SUCCESS
);
}
LocalDate
today
=
LocalDate
.
now
();
LocalDate
tomorrow
=
today
.
plusDays
(
1
);
LocalDateTime
tomorrowZero
=
tomorrow
.
atStartOfDay
();
LocalDateTime
orderPayTime
=
DateUtil
.
toLocalDateTime
(
orderById
.
getPayTime
()).
minusHours
(
8
);
if
(!
orderPayTime
.
isBefore
(
tomorrowZero
))
{
log
.
info
(
"Order {} pay is beyond cancel time."
,
orderId
);
throw
ClientEndExceptions
.
BusinessException
.
build
(
ErrorCodeEnum
.
ORDER_PAY_REFUND_FAILED
);
}
BigDecimal
detailPrice
=
BigDecimal
.
ZERO
;
if
(
CollectionUtils
.
isNotEmpty
(
payRefundRequestDto
.
getOrderDetailIds
()))
{
final
var
orderDetails
=
orderServiceRpcClient
.
getClientCustomerOrderDetailsByIds
(
payRefundRequestDto
.
getOrderDetailIds
());
detailPrice
=
orderDetails
.
stream
().
filter
(
e
->
e
.
getPrice
()
>
0
).
map
(
e
->
new
BigDecimal
(
e
.
getPrice
()).
divide
(
new
BigDecimal
(
100
),
2
,
RoundingMode
.
HALF_UP
)).
reduce
(
BigDecimal
.
ZERO
,
BigDecimal:
:
add
);
}
String
appId
=
businessConfig
.
getPayClientId
();
String
appId
=
businessConfig
.
getPayClientId
();
// 构建paycontent
String
payTime
=
Instant
.
ofEpochMilli
(
orderById
.
getPayTime
())
.
atZone
(
DateUtil
.
CHINA_ZONE
)
.
minusHours
(
8
)
.
format
(
DateUtil
.
YMDHMS
);
// 构建paycontent
String
payTime
=
Instant
.
ofEpochMilli
(
orderById
.
getPayTime
())
.
atZone
(
DateUtil
.
CHINA_ZONE
)
.
minusHours
(
8
)
.
format
(
DateUtil
.
YMDHMS
);
BigDecimal
price
=
new
BigDecimal
(
orderById
.
getPayPrice
()
)
.
divide
(
new
BigDecimal
(
100
),
2
,
RoundingMode
.
HALF_UP
)
.
negate
();
BigDecimal
price
=
detailPrice
.
compareTo
(
BigDecimal
.
ZERO
)
==
0
?
new
BigDecimal
(
orderById
.
getPayPrice
()).
divide
(
new
BigDecimal
(
100
),
2
,
RoundingMode
.
HALF_UP
).
negate
(
)
:
detailPrice
.
negate
();
String
payContentStr
=
orderById
.
getId
()
+
"^"
+
"01"
+
"^"
+
"^"
+
orderById
.
getOpenId
()
+
"^"
+
orderById
.
getOrderCode
()
+
"^"
+
price
+
"^"
+
payTime
+
"^"
+
orderById
.
getTransactionId
()
+
"^"
+
payRefundRequestDto
.
getHospitalCode
()
+
"^"
+
"^"
+
LoginContextHolder
.
getId
()
+
"^"
+
LoginContextHolder
.
getName
();
String
payContent
=
URLEncoder
.
encode
(
Base64
.
encodeBase64String
(
payContentStr
.
getBytes
()),
StandardCharsets
.
UTF_8
);
String
payContentStr
=
orderById
.
getId
()
+
"^"
+
"01"
+
"^"
+
"^"
+
orderById
.
getOpenId
()
+
"^"
+
orderById
.
getOrderCode
()
+
"^"
+
price
+
"^"
+
payTime
+
"^"
+
orderById
.
getTransactionId
()
+
"^"
+
payRefundRequestDto
.
getHospitalCode
()
+
"^"
+
"^"
+
LoginContextHolder
.
getId
()
+
"^"
+
LoginContextHolder
.
getName
();
String
payContent
=
URLEncoder
.
encode
(
Base64
.
encodeBase64String
(
payContentStr
.
getBytes
()),
StandardCharsets
.
UTF_8
);
// 构建signinfo
String
signInfoStr
=
appId
+
orderById
.
getId
()
+
payTime
+
businessConfig
.
getRefundSecurityKey
();
String
signInfo
=
DigestUtils
.
sha1Hex
(
signInfoStr
.
getBytes
());
// 构建signinfo
String
signInfoStr
=
appId
+
orderById
.
getId
()
+
payTime
+
businessConfig
.
getRefundSecurityKey
();
String
signInfo
=
DigestUtils
.
sha1Hex
(
signInfoStr
.
getBytes
());
// 构建请求
try
{
String
url
=
businessConfig
.
getCancelPayUrl
()
+
"?"
+
"appid="
+
appId
+
"&paycontent="
+
payContent
+
"&signinfo="
+
signInfo
;
log
.
info
(
"cancel order pay url:{}"
,
url
);
// 构建请求
try
{
String
url
=
businessConfig
.
getCancelPayUrl
()
+
"?"
+
"appid="
+
appId
+
"&paycontent="
+
payContent
+
"&signinfo="
+
signInfo
;
log
.
info
(
"cancel order pay url:{}"
,
url
);
// Request request =
// new Request.Builder().url(url).get().build();
// Response payResponse = client.newCall(request).execute();
...
...
@@ -400,10 +407,10 @@ public class PayServiceClient {
// throw ClientEndExceptions.BusinessException.build(ErrorCodeEnum.ORDER_PAY_REFUND_FAILED);
// }
// String htmlContent = payResponse.body().string();
return
url
;
}
catch
(
Exception
e
)
{
log
.
error
(
e
.
getMessage
());
throw
ClientEndExceptions
.
BusinessException
.
build
(
ErrorCodeEnum
.
ORDER_PAY_REFUND_FAILED
);
return
url
;
}
catch
(
Exception
e
)
{
log
.
error
(
e
.
getMessage
());
throw
ClientEndExceptions
.
BusinessException
.
build
(
ErrorCodeEnum
.
ORDER_PAY_REFUND_FAILED
);
}
}
}
}
...
...
src/main/java/com/infoloop/tianting/service/impl/SettlementServiceImpl.java
View file @
de053f1
...
...
@@ -2,8 +2,11 @@ package com.infoloop.tianting.service.impl;
import
cn.hutool.core.collection.CollectionUtil
;
import
cn.hutool.core.date.LocalDateTimeUtil
;
import
com.fasterxml.jackson.core.type.TypeReference
;
import
com.infoloop.tianting.SingleDishSkuByIdsRpcResponse
;
import
com.infoloop.tianting.clientcustomerorderservice.OnlinePayEnum
;
import
com.infoloop.tianting.clientcustomerorderservice.OrderOperationRecord
;
import
com.infoloop.tianting.clientcustomerorderservice.OrderOperationType
;
import
com.infoloop.tianting.clientcustomerorderservice.OrderStatusEnum
;
import
com.infoloop.tianting.clientcustomerorderservice.PayStatusEnum
;
import
com.infoloop.tianting.clientcustomerorderservice.ServeStatusEnum
;
...
...
@@ -17,6 +20,7 @@ import com.infoloop.tianting.exception.ClientEndExceptions.BusinessException;
import
com.infoloop.tianting.exception.ErrorCodeEnum
;
import
com.infoloop.tianting.menuservice.SingleMenuDetailRpcResponse
;
import
com.infoloop.tianting.menuservice.SingleMenuRpcResponse
;
import
com.infoloop.tianting.model.bo.OrderDetailBO
;
import
com.infoloop.tianting.model.dto.OrderDbDTO.QueryOrderByConditionDto
;
import
com.infoloop.tianting.model.dto.OrderDbDTO.QueryOrderDto
;
import
com.infoloop.tianting.model.dto.SettlementDTO
;
...
...
@@ -39,8 +43,10 @@ import com.infoloop.tianting.service.client.OrderServiceRpcClient;
import
com.infoloop.tianting.service.client.SkuServiceRpcClient
;
import
com.infoloop.tianting.setmealscheduleservice.SingleMealRpcResponse
;
import
com.infoloop.tianting.utils.DateUtil
;
import
com.infoloop.tianting.utils.JsonUtil
;
import
lombok.RequiredArgsConstructor
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.lang3.StringUtils
;
import
org.apache.poi.ss.usermodel.BorderStyle
;
import
org.apache.poi.ss.usermodel.Cell
;
import
org.apache.poi.ss.usermodel.CellStyle
;
...
...
@@ -71,7 +77,9 @@ import java.util.HashMap;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Objects
;
import
java.util.function.Function
;
import
java.util.stream.Collectors
;
import
java.util.stream.Stream
;
@Slf4j
@Service
...
...
@@ -295,6 +303,408 @@ public class SettlementServiceImpl implements SettlementService {
return
dateList
;
}
/**
* 按订单维度生成Excel
*/
private
static
ByteArrayOutputStream
writeToExcelByOrder
(
SettlementDTO
.
SettlementDataByOrderDto
settlementDataDto
)
throws
IOException
{
Workbook
workbook
=
new
XSSFWorkbook
();
Sheet
sheet
=
workbook
.
createSheet
(
"客人结算"
);
// 创建表头样式(黑色边框)
CellStyle
headerStyle
=
workbook
.
createCellStyle
();
headerStyle
.
setBorderTop
(
BorderStyle
.
THIN
);
headerStyle
.
setBorderBottom
(
BorderStyle
.
THIN
);
headerStyle
.
setBorderLeft
(
BorderStyle
.
THIN
);
headerStyle
.
setBorderRight
(
BorderStyle
.
THIN
);
headerStyle
.
setTopBorderColor
(
IndexedColors
.
BLACK
.
getIndex
());
headerStyle
.
setBottomBorderColor
(
IndexedColors
.
BLACK
.
getIndex
());
headerStyle
.
setLeftBorderColor
(
IndexedColors
.
BLACK
.
getIndex
());
headerStyle
.
setRightBorderColor
(
IndexedColors
.
BLACK
.
getIndex
());
// 创建数据行样式(浅灰色边框)
CellStyle
dataStyle
=
workbook
.
createCellStyle
();
dataStyle
.
setBorderTop
(
BorderStyle
.
THIN
);
dataStyle
.
setBorderBottom
(
BorderStyle
.
THIN
);
dataStyle
.
setBorderLeft
(
BorderStyle
.
THIN
);
dataStyle
.
setBorderRight
(
BorderStyle
.
THIN
);
dataStyle
.
setTopBorderColor
(
IndexedColors
.
GREY_25_PERCENT
.
getIndex
());
dataStyle
.
setBottomBorderColor
(
IndexedColors
.
GREY_25_PERCENT
.
getIndex
());
dataStyle
.
setLeftBorderColor
(
IndexedColors
.
GREY_25_PERCENT
.
getIndex
());
dataStyle
.
setRightBorderColor
(
IndexedColors
.
GREY_25_PERCENT
.
getIndex
());
int
rowNum
=
0
;
// 创建表头
Row
titleRow
=
sheet
.
createRow
(
rowNum
++);
int
columnNum
=
0
;
Cell
cell0
=
titleRow
.
createCell
(
columnNum
++);
cell0
.
setCellValue
(
"用餐时间"
);
cell0
.
setCellStyle
(
headerStyle
);
Cell
cell1
=
titleRow
.
createCell
(
columnNum
++);
cell1
.
setCellValue
(
"订单号"
);
cell1
.
setCellStyle
(
headerStyle
);
Cell
cell2
=
titleRow
.
createCell
(
columnNum
++);
cell2
.
setCellValue
(
"餐别"
);
cell2
.
setCellStyle
(
headerStyle
);
Cell
cell3
=
titleRow
.
createCell
(
columnNum
++);
cell3
.
setCellValue
(
"房间号"
);
cell3
.
setCellStyle
(
headerStyle
);
Cell
cell4
=
titleRow
.
createCell
(
columnNum
++);
cell4
.
setCellValue
(
"客户姓名"
);
cell4
.
setCellStyle
(
headerStyle
);
Cell
cell5
=
titleRow
.
createCell
(
columnNum
++);
cell5
.
setCellValue
(
"客户腕带号"
);
cell5
.
setCellStyle
(
headerStyle
);
Cell
cell6
=
titleRow
.
createCell
(
columnNum
++);
cell6
.
setCellValue
(
"忌口信息"
);
cell6
.
setCellStyle
(
headerStyle
);
Cell
cell7
=
titleRow
.
createCell
(
columnNum
++);
cell7
.
setCellValue
(
"医嘱信息"
);
cell7
.
setCellStyle
(
headerStyle
);
Cell
cell8
=
titleRow
.
createCell
(
columnNum
++);
cell8
.
setCellValue
(
"餐单名称"
);
cell8
.
setCellStyle
(
headerStyle
);
Cell
cell9
=
titleRow
.
createCell
(
columnNum
++);
cell9
.
setCellValue
(
"菜品名称"
);
cell9
.
setCellStyle
(
headerStyle
);
Cell
cell10
=
titleRow
.
createCell
(
columnNum
++);
cell10
.
setCellValue
(
"菜品份数"
);
cell10
.
setCellStyle
(
headerStyle
);
Cell
cell11
=
titleRow
.
createCell
(
columnNum
++);
cell11
.
setCellValue
(
"菜品单价"
);
cell11
.
setCellStyle
(
headerStyle
);
Cell
cell12
=
titleRow
.
createCell
(
columnNum
++);
cell12
.
setCellValue
(
"菜品金额"
);
cell12
.
setCellStyle
(
headerStyle
);
Cell
cell13
=
titleRow
.
createCell
(
columnNum
++);
cell13
.
setCellValue
(
"菜品状态"
);
cell13
.
setCellStyle
(
headerStyle
);
Cell
cell14
=
titleRow
.
createCell
(
columnNum
++);
cell14
.
setCellValue
(
"交易码"
);
cell14
.
setCellStyle
(
headerStyle
);
Cell
cell15
=
titleRow
.
createCell
(
columnNum
++);
cell15
.
setCellValue
(
"备注"
);
cell15
.
setCellStyle
(
headerStyle
);
Cell
cell16
=
titleRow
.
createCell
(
columnNum
++);
cell16
.
setCellValue
(
"支付方式"
);
cell16
.
setCellStyle
(
headerStyle
);
// 填充数据
final
var
classifyOrders
=
settlementDataDto
.
getClassifyOrders
();
if
(
classifyOrders
!=
null
)
{
for
(
SettlementDTO
.
SettlementOrderDetail
orderDetail
:
classifyOrders
)
{
Row
dataRow
=
sheet
.
createRow
(
rowNum
++);
columnNum
=
0
;
Cell
dataCell0
=
dataRow
.
createCell
(
columnNum
++);
dataCell0
.
setCellValue
(
orderDetail
.
getMealTime
()
!=
null
?
orderDetail
.
getMealTime
()
:
""
);
dataCell0
.
setCellStyle
(
dataStyle
);
Cell
dataCell1
=
dataRow
.
createCell
(
columnNum
++);
dataCell1
.
setCellValue
(
orderDetail
.
getCode
()
!=
null
?
orderDetail
.
getCode
()
:
""
);
dataCell1
.
setCellStyle
(
dataStyle
);
Cell
dataCell2
=
dataRow
.
createCell
(
columnNum
++);
dataCell2
.
setCellValue
(
orderDetail
.
getMealName
()
!=
null
?
orderDetail
.
getMealName
()
:
""
);
dataCell2
.
setCellStyle
(
dataStyle
);
Cell
dataCell3
=
dataRow
.
createCell
(
columnNum
++);
dataCell3
.
setCellValue
(
orderDetail
.
getRoomNo
()
!=
null
?
orderDetail
.
getRoomNo
()
:
""
);
dataCell3
.
setCellStyle
(
dataStyle
);
Cell
dataCell4
=
dataRow
.
createCell
(
columnNum
++);
dataCell4
.
setCellValue
(
orderDetail
.
getCustomerName
()
!=
null
?
orderDetail
.
getCustomerName
()
:
""
);
dataCell4
.
setCellStyle
(
dataStyle
);
Cell
dataCell5
=
dataRow
.
createCell
(
columnNum
++);
dataCell5
.
setCellValue
(
orderDetail
.
getHISCustomerNo
()
!=
null
?
orderDetail
.
getHISCustomerNo
()
:
""
);
dataCell5
.
setCellStyle
(
dataStyle
);
// 忌口列表转字符串
String
avoidsStr
=
orderDetail
.
getAvoids
()
!=
null
?
String
.
join
(
", "
,
orderDetail
.
getAvoids
())
:
""
;
Cell
dataCell6
=
dataRow
.
createCell
(
columnNum
++);
dataCell6
.
setCellValue
(
avoidsStr
);
dataCell6
.
setCellStyle
(
dataStyle
);
// 医嘱列表转字符串
String
doctorsStr
=
orderDetail
.
getDoctors
()
!=
null
?
String
.
join
(
", "
,
orderDetail
.
getDoctors
())
:
""
;
Cell
dataCell7
=
dataRow
.
createCell
(
columnNum
++);
dataCell7
.
setCellValue
(
doctorsStr
);
dataCell7
.
setCellStyle
(
dataStyle
);
Cell
dataCell8
=
dataRow
.
createCell
(
columnNum
++);
dataCell8
.
setCellValue
(
orderDetail
.
getMenuName
()
!=
null
?
orderDetail
.
getMenuName
()
:
""
);
dataCell8
.
setCellStyle
(
dataStyle
);
Cell
dataCell9
=
dataRow
.
createCell
(
columnNum
++);
dataCell9
.
setCellValue
(
orderDetail
.
getSkuName
()
!=
null
?
orderDetail
.
getSkuName
()
:
""
);
dataCell9
.
setCellStyle
(
dataStyle
);
Cell
dataCell10
=
dataRow
.
createCell
(
columnNum
++);
dataCell10
.
setCellValue
(
orderDetail
.
getCount
()
!=
null
?
orderDetail
.
getCount
()
:
0
);
dataCell10
.
setCellStyle
(
dataStyle
);
// 价格
Cell
dataCell11
=
dataRow
.
createCell
(
columnNum
++);
if
(
orderDetail
.
getPrice
()
!=
null
)
{
dataCell11
.
setCellValue
(
orderDetail
.
getPrice
().
doubleValue
());
}
else
{
dataCell11
.
setCellValue
(
0.0
);
}
dataCell11
.
setCellStyle
(
dataStyle
);
// 总价
Cell
dataCell12
=
dataRow
.
createCell
(
columnNum
++);
if
(
orderDetail
.
getTotalPrice
()
!=
null
)
{
dataCell12
.
setCellValue
(
orderDetail
.
getTotalPrice
().
doubleValue
());
}
else
{
dataCell12
.
setCellValue
(
0.0
);
}
dataCell12
.
setCellStyle
(
dataStyle
);
// 状态
Cell
dataCell13
=
dataRow
.
createCell
(
columnNum
++);
dataCell13
.
setCellValue
(
orderDetail
.
getOperationType
());
dataCell13
.
setCellStyle
(
dataStyle
);
Cell
dataCell14
=
dataRow
.
createCell
(
columnNum
++);
dataCell14
.
setCellValue
(
orderDetail
.
getTransactionId
()
!=
null
?
orderDetail
.
getTransactionId
()
:
""
);
dataCell14
.
setCellStyle
(
dataStyle
);
// 合并备注和忌口备注,用分号分割,备注在前
String
remark
=
orderDetail
.
getRemark
()
!=
null
?
orderDetail
.
getRemark
()
:
""
;
String
avoidRemark
=
orderDetail
.
getAvoidRemark
()
!=
null
?
orderDetail
.
getAvoidRemark
()
:
""
;
String
combinedRemark
=
""
;
if
(!
remark
.
isEmpty
()
&&
!
avoidRemark
.
isEmpty
())
{
combinedRemark
=
remark
+
";"
+
avoidRemark
;
}
else
if
(!
remark
.
isEmpty
())
{
combinedRemark
=
remark
;
}
else
if
(!
avoidRemark
.
isEmpty
())
{
combinedRemark
=
avoidRemark
;
}
Cell
dataCell15
=
dataRow
.
createCell
(
columnNum
++);
dataCell15
.
setCellValue
(
combinedRemark
);
dataCell15
.
setCellStyle
(
dataStyle
);
Cell
dataCell16
=
dataRow
.
createCell
(
columnNum
++);
dataCell16
.
setCellValue
(
orderDetail
.
getOnlinePay
()
!=
null
?
orderDetail
.
getOnlinePay
()
:
""
);
dataCell16
.
setCellStyle
(
dataStyle
);
}
}
// 自动调整列宽
for
(
int
i
=
0
;
i
<
17
;
i
++)
{
sheet
.
autoSizeColumn
(
i
);
}
// 将工作簿内容写入字节数组输出流
ByteArrayOutputStream
outputStream
=
new
ByteArrayOutputStream
();
workbook
.
write
(
outputStream
);
workbook
.
close
();
return
outputStream
;
}
/**
* 生成分餐表Excel
*/
private
static
ByteArrayOutputStream
writeToExcelBySeparateMeal
(
SeparateMealDataDto
separateMealDataDto
)
throws
IOException
{
Workbook
workbook
=
new
XSSFWorkbook
();
Sheet
sheet
=
workbook
.
createSheet
(
"分餐表"
);
// 创建标题样式(合并单元格标题)
CellStyle
titleStyle
=
workbook
.
createCellStyle
();
titleStyle
.
setAlignment
(
HorizontalAlignment
.
CENTER
);
titleStyle
.
setVerticalAlignment
(
VerticalAlignment
.
CENTER
);
titleStyle
.
setBorderTop
(
BorderStyle
.
THIN
);
titleStyle
.
setBorderBottom
(
BorderStyle
.
THIN
);
titleStyle
.
setBorderLeft
(
BorderStyle
.
THIN
);
titleStyle
.
setBorderRight
(
BorderStyle
.
THIN
);
titleStyle
.
setTopBorderColor
(
IndexedColors
.
BLACK
.
getIndex
());
titleStyle
.
setBottomBorderColor
(
IndexedColors
.
BLACK
.
getIndex
());
titleStyle
.
setLeftBorderColor
(
IndexedColors
.
BLACK
.
getIndex
());
titleStyle
.
setRightBorderColor
(
IndexedColors
.
BLACK
.
getIndex
());
Font
titleFont
=
workbook
.
createFont
();
titleFont
.
setBold
(
true
);
titleFont
.
setFontHeightInPoints
((
short
)
16
);
titleStyle
.
setFont
(
titleFont
);
// 创建表头样式(黑色边框)
CellStyle
headerStyle
=
workbook
.
createCellStyle
();
headerStyle
.
setBorderTop
(
BorderStyle
.
THIN
);
headerStyle
.
setBorderBottom
(
BorderStyle
.
THIN
);
headerStyle
.
setBorderLeft
(
BorderStyle
.
THIN
);
headerStyle
.
setBorderRight
(
BorderStyle
.
THIN
);
headerStyle
.
setTopBorderColor
(
IndexedColors
.
BLACK
.
getIndex
());
headerStyle
.
setBottomBorderColor
(
IndexedColors
.
BLACK
.
getIndex
());
headerStyle
.
setLeftBorderColor
(
IndexedColors
.
BLACK
.
getIndex
());
headerStyle
.
setRightBorderColor
(
IndexedColors
.
BLACK
.
getIndex
());
// 创建数据行样式(浅灰色边框)
CellStyle
dataStyle
=
workbook
.
createCellStyle
();
dataStyle
.
setBorderTop
(
BorderStyle
.
THIN
);
dataStyle
.
setBorderBottom
(
BorderStyle
.
THIN
);
dataStyle
.
setBorderLeft
(
BorderStyle
.
THIN
);
dataStyle
.
setBorderRight
(
BorderStyle
.
THIN
);
dataStyle
.
setTopBorderColor
(
IndexedColors
.
GREY_25_PERCENT
.
getIndex
());
dataStyle
.
setBottomBorderColor
(
IndexedColors
.
GREY_25_PERCENT
.
getIndex
());
dataStyle
.
setLeftBorderColor
(
IndexedColors
.
GREY_25_PERCENT
.
getIndex
());
dataStyle
.
setRightBorderColor
(
IndexedColors
.
GREY_25_PERCENT
.
getIndex
());
int
rowNum
=
0
;
// 第一行:创建合并单元格标题
Row
mainTitleRow
=
sheet
.
createRow
(
rowNum
++);
Cell
mainTitleCell
=
mainTitleRow
.
createCell
(
0
);
mainTitleCell
.
setCellValue
(
"住院客户分餐表"
);
mainTitleCell
.
setCellStyle
(
titleStyle
);
// 合并第一行的8列
CellRangeAddress
titleRegion
=
new
CellRangeAddress
(
0
,
0
,
0
,
8
);
sheet
.
addMergedRegion
(
titleRegion
);
// 为合并区域设置边框
RegionUtil
.
setBorderTop
(
BorderStyle
.
THIN
,
titleRegion
,
sheet
);
RegionUtil
.
setBorderBottom
(
BorderStyle
.
THIN
,
titleRegion
,
sheet
);
RegionUtil
.
setBorderLeft
(
BorderStyle
.
THIN
,
titleRegion
,
sheet
);
RegionUtil
.
setBorderRight
(
BorderStyle
.
THIN
,
titleRegion
,
sheet
);
RegionUtil
.
setTopBorderColor
(
IndexedColors
.
BLACK
.
getIndex
(),
titleRegion
,
sheet
);
RegionUtil
.
setBottomBorderColor
(
IndexedColors
.
BLACK
.
getIndex
(),
titleRegion
,
sheet
);
RegionUtil
.
setLeftBorderColor
(
IndexedColors
.
BLACK
.
getIndex
(),
titleRegion
,
sheet
);
RegionUtil
.
setRightBorderColor
(
IndexedColors
.
BLACK
.
getIndex
(),
titleRegion
,
sheet
);
// 第二行:创建表头
Row
titleRow
=
sheet
.
createRow
(
rowNum
++);
int
columnNum
=
0
;
Cell
cell0
=
titleRow
.
createCell
(
columnNum
++);
cell0
.
setCellValue
(
"餐别"
);
cell0
.
setCellStyle
(
headerStyle
);
Cell
cell1
=
titleRow
.
createCell
(
columnNum
++);
cell1
.
setCellValue
(
"房间号"
);
cell1
.
setCellStyle
(
headerStyle
);
Cell
cell2
=
titleRow
.
createCell
(
columnNum
++);
cell2
.
setCellValue
(
"客户姓名"
);
cell2
.
setCellStyle
(
headerStyle
);
Cell
cell3
=
titleRow
.
createCell
(
columnNum
++);
cell3
.
setCellValue
(
"医嘱信息"
);
cell3
.
setCellStyle
(
headerStyle
);
Cell
cell4
=
titleRow
.
createCell
(
columnNum
++);
cell4
.
setCellValue
(
"餐单名称"
);
cell4
.
setCellStyle
(
headerStyle
);
Cell
cell5
=
titleRow
.
createCell
(
columnNum
++);
cell5
.
setCellValue
(
"菜品名称"
);
cell5
.
setCellStyle
(
headerStyle
);
Cell
cell6
=
titleRow
.
createCell
(
columnNum
++);
cell6
.
setCellValue
(
"菜品数量"
);
cell6
.
setCellStyle
(
headerStyle
);
Cell
cell7
=
titleRow
.
createCell
(
columnNum
++);
cell7
.
setCellValue
(
"忌口信息"
);
cell7
.
setCellStyle
(
headerStyle
);
Cell
cell8
=
titleRow
.
createCell
(
columnNum
++);
cell8
.
setCellValue
(
"备注"
);
cell8
.
setCellStyle
(
headerStyle
);
// 填充数据
final
var
mealDetails
=
separateMealDataDto
.
getMealDetails
();
if
(
mealDetails
!=
null
)
{
for
(
SeparateMealDetail
mealDetail
:
mealDetails
)
{
Row
dataRow
=
sheet
.
createRow
(
rowNum
++);
columnNum
=
0
;
Cell
dataCell0
=
dataRow
.
createCell
(
columnNum
++);
dataCell0
.
setCellValue
(
mealDetail
.
getMealName
()
!=
null
?
mealDetail
.
getMealName
()
:
""
);
dataCell0
.
setCellStyle
(
dataStyle
);
Cell
dataCell1
=
dataRow
.
createCell
(
columnNum
++);
dataCell1
.
setCellValue
(
mealDetail
.
getRoomNo
()
!=
null
?
mealDetail
.
getRoomNo
()
:
""
);
dataCell1
.
setCellStyle
(
dataStyle
);
Cell
dataCell2
=
dataRow
.
createCell
(
columnNum
++);
dataCell2
.
setCellValue
(
mealDetail
.
getCustomerName
()
!=
null
?
mealDetail
.
getCustomerName
()
:
""
);
dataCell2
.
setCellStyle
(
dataStyle
);
Cell
dataCell3
=
dataRow
.
createCell
(
columnNum
++);
dataCell3
.
setCellValue
(
mealDetail
.
getDoctors
()
!=
null
?
mealDetail
.
getDoctors
()
:
""
);
dataCell3
.
setCellStyle
(
dataStyle
);
Cell
dataCell4
=
dataRow
.
createCell
(
columnNum
++);
dataCell4
.
setCellValue
(
mealDetail
.
getMenuName
()
!=
null
?
mealDetail
.
getMenuName
()
:
""
);
dataCell4
.
setCellStyle
(
dataStyle
);
Cell
dataCell5
=
dataRow
.
createCell
(
columnNum
++);
dataCell5
.
setCellValue
(
mealDetail
.
getSkuName
()
!=
null
?
mealDetail
.
getSkuName
()
:
""
);
dataCell5
.
setCellStyle
(
dataStyle
);
Cell
dataCell6
=
dataRow
.
createCell
(
columnNum
++);
dataCell6
.
setCellValue
(
mealDetail
.
getCount
()
!=
null
?
mealDetail
.
getCount
()
:
0
);
dataCell6
.
setCellStyle
(
dataStyle
);
Cell
dataCell7
=
dataRow
.
createCell
(
columnNum
++);
dataCell7
.
setCellValue
(
mealDetail
.
getAvoids
()
!=
null
?
mealDetail
.
getAvoids
()
:
""
);
dataCell7
.
setCellStyle
(
dataStyle
);
Cell
dataCell8
=
dataRow
.
createCell
(
columnNum
++);
dataCell8
.
setCellValue
(
mealDetail
.
getRemark
()
!=
null
?
mealDetail
.
getRemark
()
:
""
);
dataCell8
.
setCellStyle
(
dataStyle
);
}
}
// 自动调整列宽
for
(
int
i
=
0
;
i
<
9
;
i
++)
{
sheet
.
autoSizeColumn
(
i
);
}
// 将工作簿内容写入字节数组输出流
ByteArrayOutputStream
outputStream
=
new
ByteArrayOutputStream
();
workbook
.
write
(
outputStream
);
workbook
.
close
();
return
outputStream
;
}
/**
* 创建空的分餐表Excel(无数据)
*/
private
static
ByteArrayOutputStream
createEmptyExcelBySeparateMeal
()
{
try
{
SeparateMealDataDto
emptyData
=
SeparateMealDataDto
.
builder
()
.
mealDetails
(
new
ArrayList
<>())
.
build
();
return
writeToExcelBySeparateMeal
(
emptyData
);
}
catch
(
IOException
e
)
{
log
.
error
(
"创建空分餐表Excel失败"
,
e
);
throw
BusinessException
.
build
(
ErrorCodeEnum
.
GENERATE_EXCEL_ERROR
);
}
}
@Override
public
ByteArrayOutputStream
generateOrderSettlementExcel
(
SettlementRequestDto
settlementRequest
)
{
if
(
settlementRequest
.
getDimension
().
equals
(
SettlementDimensionEnum
.
BY_SKU
))
{
...
...
@@ -369,13 +779,11 @@ public class SettlementServiceImpl implements SettlementService {
.
collect
(
Collectors
.
toList
());
if
(
orderIds
.
isEmpty
())
{
log
.
warn
(
"筛选后无有效订单,enterpriseId: {}"
,
enterpriseId
);
return
createEmptyExcelByOrder
();
}
// 构建订单映射
final
var
orderMap
=
orderList
.
stream
()
.
filter
(
o
->
o
.
getId
()
!=
0
)
final
var
orderMap
=
orderList
.
stream
().
filter
(
o
->
o
.
getId
()
!=
0
)
.
collect
(
Collectors
.
toMap
(
SingleClientCustomerOrderRpcResponse:
:
getId
,
o
->
o
,
(
o1
,
o2
)
->
o1
));
// 查询订单详情
...
...
@@ -384,86 +792,60 @@ public class SettlementServiceImpl implements SettlementService {
log
.
warn
(
"未查询到订单详情数据,orderIds: {}"
,
orderIds
);
return
createEmptyExcelByOrder
();
}
// 订单详情按订单ID分组
final
var
orderDetailGroupByOrderId
=
orderDetailList
.
stream
()
.
filter
(
Objects:
:
nonNull
)
.
filter
(
d
->
!
d
.
getServeStatus
().
equals
(
ServeStatusEnum
.
SERVE_REJECT
))
.
collect
(
Collectors
.
groupingBy
(
SingleClientCustomerOrderDetailRpcResponse:
:
getOrderId
));
// 获取SKU数据
List
<
Integer
>
skuIds
=
orderDetailList
.
stream
()
.
filter
(
Objects:
:
nonNull
)
.
filter
(
d
->
!
d
.
getServeStatus
().
equals
(
ServeStatusEnum
.
SERVE_REJECT
))
.
map
(
SingleClientCustomerOrderDetailRpcResponse:
:
getSkuId
)
final
var
orderDetailGroupByOrderId
=
orderDetailList
.
stream
().
filter
(
Objects:
:
nonNull
).
collect
(
Collectors
.
groupingBy
(
SingleClientCustomerOrderDetailRpcResponse:
:
getOrderId
));
final
var
orderOperationRecordsByOrderIds
=
orderServiceRpcClient
.
getOrderOperationRecordsByOrderIds
(
LoginContextHolder
.
getEnterpriseId
(),
orderIds
).
getResponsesList
();
// 订单操作记录按订单ID分组
final
var
orderOperationRecordByOrderId
=
orderOperationRecordsByOrderIds
.
stream
().
filter
(
Objects:
:
nonNull
).
collect
(
Collectors
.
groupingBy
(
OrderOperationRecord:
:
getOrderId
));
List
<
Integer
>
skuIds
=
Stream
.
concat
(
orderOperationRecordsByOrderIds
.
stream
()
.
filter
(
e
->
StringUtils
.
isNoneBlank
(
e
.
getOriginalOrderDetailJson
()))
.
flatMap
(
e
->
JsonUtil
.
readJsonAs
(
e
.
getOriginalOrderDetailJson
(),
new
TypeReference
<
List
<
OrderDetailBO
>>()
{}).
stream
())
.
map
(
OrderDetailBO:
:
getSkuId
),
orderDetailList
.
stream
()
.
filter
(
Objects:
:
nonNull
)
.
map
(
SingleClientCustomerOrderDetailRpcResponse:
:
getSkuId
)
)
.
distinct
()
.
collect
(
Collectors
.
toList
());
final
var
skuResponse
=
skuServiceRpcClient
.
getDishSkusByIds
(
skuIds
);
final
List
<
SingleDishSkuByIdsRpcResponse
>
skus
=
skuResponse
!=
null
?
skuResponse
.
getResponseList
()
:
new
ArrayList
<>();
final
var
skuMap
=
skus
.
stream
()
.
filter
(
Objects:
:
nonNull
)
.
filter
(
s
->
s
.
getId
()
!=
0
)
.
collect
(
Collectors
.
toMap
(
SingleDishSkuByIdsRpcResponse:
:
getId
,
s
->
s
,
(
s1
,
s2
)
->
s1
));
final
List
<
SingleDishSkuByIdsRpcResponse
>
skus
=
skuResponse
.
getResponseList
();
final
var
skuMap
=
skus
.
stream
().
collect
(
Collectors
.
toMap
(
SingleDishSkuByIdsRpcResponse:
:
getId
,
s
->
s
,
(
s1
,
s2
)
->
s1
));
// 获取餐别数据
final
var
mealResponse
=
mealServiceRpcClient
.
getAllMeals
(
enterpriseId
);
final
List
<
SingleMealRpcResponse
>
meals
=
mealResponse
!=
null
?
mealResponse
.
getResponsesList
()
:
new
ArrayList
<>();
final
var
mealMap
=
meals
.
stream
()
.
filter
(
Objects:
:
nonNull
)
.
filter
(
m
->
m
.
getId
()
!=
0
)
.
collect
(
Collectors
.
toMap
(
SingleMealRpcResponse:
:
getId
,
m
->
m
,
(
m1
,
m2
)
->
m1
));
final
var
mealMap
=
meals
.
stream
().
collect
(
Collectors
.
toMap
(
SingleMealRpcResponse:
:
getId
,
m
->
m
,
(
m1
,
m2
)
->
m1
));
// 获取菜单数据
List
<
Integer
>
menuIds
=
orderList
.
stream
()
.
filter
(
Objects:
:
nonNull
)
.
map
(
SingleClientCustomerOrderRpcResponse:
:
getMenuId
)
.
filter
(
id
->
id
!=
0
)
.
distinct
()
.
collect
(
Collectors
.
toList
());
List
<
Integer
>
menuIds
=
orderList
.
stream
().
map
(
SingleClientCustomerOrderRpcResponse:
:
getMenuId
).
distinct
().
collect
(
Collectors
.
toList
());
final
var
menuResponse
=
menuServiceRpcClient
.
getMenusByIds
(
enterpriseId
,
menuIds
);
final
List
<
SingleMenuRpcResponse
>
menuList
=
menuResponse
!=
null
?
menuResponse
.
getResponsesList
()
:
new
ArrayList
<>();
final
var
menuMap
=
menuList
.
stream
()
.
filter
(
Objects:
:
nonNull
)
.
filter
(
m
->
m
.
getId
()
!=
0
)
.
collect
(
Collectors
.
toMap
(
SingleMenuRpcResponse:
:
getId
,
m
->
m
,
(
m1
,
m2
)
->
m1
));
final
var
menuMap
=
menuList
.
stream
().
collect
(
Collectors
.
toMap
(
SingleMenuRpcResponse:
:
getId
,
m
->
m
,
(
m1
,
m2
)
->
m1
));
// 获取菜单详情数据
final
var
menuDetailResponse
=
menuServiceRpcClient
.
queryMenuDetailsByMenuIds
(
enterpriseId
,
menuIds
);
final
List
<
SingleMenuDetailRpcResponse
>
menuDetailList
=
menuDetailResponse
!=
null
?
menuDetailResponse
.
getResponsesList
()
:
new
ArrayList
<>();
final
var
menuDetailMap
=
menuDetailList
.
stream
()
.
filter
(
Objects:
:
nonNull
)
.
filter
(
m
->
m
.
getId
()
!=
0
)
.
collect
(
Collectors
.
toMap
(
SingleMenuDetailRpcResponse:
:
getId
,
m
->
m
,
(
m1
,
m2
)
->
m1
));
final
List
<
SingleMenuDetailRpcResponse
>
menuDetailList
=
menuDetailResponse
.
getResponsesList
();
final
var
menuDetailMap
=
menuDetailList
.
stream
().
collect
(
Collectors
.
toMap
(
SingleMenuDetailRpcResponse:
:
getId
,
m
->
m
,
(
m1
,
m2
)
->
m1
));
// 获取客户数据
List
<
Integer
>
customerIds
=
orderList
.
stream
()
.
filter
(
Objects:
:
nonNull
)
.
map
(
SingleClientCustomerOrderRpcResponse:
:
getCustomerId
)
.
filter
(
id
->
id
!=
0
)
.
distinct
()
.
collect
(
Collectors
.
toList
());
List
<
Integer
>
customerIds
=
orderList
.
stream
().
map
(
SingleClientCustomerOrderRpcResponse:
:
getCustomerId
).
distinct
().
collect
(
Collectors
.
toList
());
final
var
customerResponse
=
clientCustomerServiceRpcClient
.
getClientCustomersByIds
(
enterpriseId
,
customerIds
);
final
List
<
SingleClientCustomerRpcResponse
>
customers
=
customerResponse
!=
null
?
customerResponse
.
getResponsesList
()
:
new
ArrayList
<>();
final
var
customerMap
=
customers
.
stream
()
.
filter
(
Objects:
:
nonNull
)
.
filter
(
c
->
c
.
getId
()
!=
0
)
.
collect
(
Collectors
.
toMap
(
SingleClientCustomerRpcResponse:
:
getId
,
c
->
c
,
(
c1
,
c2
)
->
c1
));
final
List
<
SingleClientCustomerRpcResponse
>
customers
=
customerResponse
.
getResponsesList
();
final
var
customerMap
=
customers
.
stream
().
collect
(
Collectors
.
toMap
(
SingleClientCustomerRpcResponse:
:
getId
,
c
->
c
,
(
c1
,
c2
)
->
c1
));
// 构建结算订单明细
final
var
classifyOrders
=
new
ArrayList
<
SettlementDTO
.
SettlementOrderDetail
>();
for
(
Integer
orderId
:
orderIds
)
{
final
var
orderDetails
=
orderDetailGroupByOrderId
.
getOrDefault
(
orderId
,
Collections
.
emptyList
());
final
var
order
=
orderMap
.
get
(
orderId
);
// 订单为空则跳过
if
(
order
==
null
)
{
log
.
warn
(
"订单不存在,orderId: {}"
,
orderId
);
continue
;
}
// 获取菜单信息
final
var
menu
=
menuMap
.
get
(
order
.
getMenuId
());
final
String
menuName
=
menu
!=
null
?
menu
.
getName
()
:
""
;
...
...
@@ -473,52 +855,76 @@ public class SettlementServiceImpl implements SettlementService {
final
String
customerName
=
customer
!=
null
?
customer
.
getName
()
:
""
;
final
String
hisCustomerNo
=
customer
!=
null
?
customer
.
getHISCustomerNo
()
:
""
;
// 处理每个订单详情
for
(
SingleClientCustomerOrderDetailRpcResponse
orderDetail
:
orderDetails
)
{
if
(
orderDetail
==
null
)
{
continue
;
}
final
var
orderOperationRecords
=
orderOperationRecordByOrderId
.
getOrDefault
(
orderId
,
Collections
.
emptyList
());
// 安全获取餐别名称
String
mealName
=
getMealNameSafely
(
orderDetail
,
menuDetailMap
,
mealMap
);
Map
<
Integer
,
OrderDetailBO
>
addOriginalDetailMap
=
orderOperationRecords
.
stream
()
.
filter
(
e
->
e
.
getType
()
==
OrderOperationType
.
ADD_DISHES
)
.
flatMap
(
e
->
JsonUtil
.
readJsonAs
(
e
.
getOriginalOrderDetailJson
(),
new
TypeReference
<
List
<
OrderDetailBO
>>()
{
}).
stream
())
.
collect
(
Collectors
.
toMap
(
OrderDetailBO:
:
getId
,
Function
.
identity
(),
(
a
,
b
)
->
a
));
// 安全获取SKU名称
String
skuName
=
getSkuNameSafely
(
orderDetail
,
skuMap
);
Map
<
Integer
,
OrderDetailBO
>
replaceOriginalDetailMap
=
orderOperationRecords
.
stream
()
.
filter
(
e
->
e
.
getType
()
==
OrderOperationType
.
REPLACE_DISHES
)
.
flatMap
(
e
->
JsonUtil
.
readJsonAs
(
e
.
getOriginalOrderDetailJson
(),
new
TypeReference
<
List
<
OrderDetailBO
>>()
{
}).
stream
())
.
collect
(
Collectors
.
toMap
(
OrderDetailBO:
:
getId
,
Function
.
identity
(),
(
a
,
b
)
->
a
));
// 安全获取房间号
String
roomNo
=
getRoomNoSafely
(
order
);
Map
<
Integer
,
OrderDetailBO
>
replaceAdjustDetailMap
=
orderOperationRecords
.
stream
()
.
filter
(
e
->
e
.
getType
()
==
OrderOperationType
.
REPLACE_DISHES
)
.
flatMap
(
e
->
JsonUtil
.
readJsonAs
(
e
.
getAdjustOrderDetailJson
(),
new
TypeReference
<
List
<
OrderDetailBO
>>()
{
}).
stream
())
.
collect
(
Collectors
.
toMap
(
OrderDetailBO:
:
getId
,
Function
.
identity
(),
(
a
,
b
)
->
a
));
// 安全获取忌口和医嘱
List
<
String
>
avoids
=
getAvoidsSafely
(
order
);
List
<
String
>
doctors
=
getDoctorsSafely
(
order
);
for
(
SingleClientCustomerOrderDetailRpcResponse
orderDetail
:
orderDetails
)
{
// 1. 先处理加餐
if
(
addOriginalDetailMap
.
containsKey
(
orderDetail
.
getId
())
&&
addOriginalDetailMap
.
get
(
orderDetail
.
getId
()).
getCount
()
!=
orderDetail
.
getCount
())
{
final
var
orderDetailBO
=
addOriginalDetailMap
.
get
(
orderDetail
.
getId
());
SettlementDTO
.
SettlementOrderDetail
beforeChange
=
buildSettlementOrderDetail
(
order
,
orderDetail
.
getMenuDetailId
(),
orderDetailBO
.
getSkuId
(),
orderDetailBO
.
getCount
(),
orderDetail
.
getPrice
(),
"订餐"
,
menuName
,
customerName
,
hisCustomerNo
,
menuDetailMap
,
mealMap
,
skuMap
);
classifyOrders
.
add
(
beforeChange
);
SettlementDTO
.
SettlementOrderDetail
afterChange
=
buildSettlementOrderDetail
(
order
,
orderDetail
.
getMenuDetailId
(),
orderDetailBO
.
getSkuId
(),
orderDetail
.
getCount
()
-
orderDetailBO
.
getCount
(),
orderDetail
.
getPrice
(),
"加餐"
,
menuName
,
customerName
,
hisCustomerNo
,
menuDetailMap
,
mealMap
,
skuMap
);
classifyOrders
.
add
(
afterChange
);
}
// 安全获取在线支付描述
String
onlinePayDesc
=
getOnlinePayDescSafely
(
order
);
// 2. 再处理换菜
if
(
replaceOriginalDetailMap
.
containsKey
(
orderDetail
.
getId
())
&&
!
Objects
.
equals
(
replaceOriginalDetailMap
.
get
(
orderDetail
.
getId
()).
getSkuId
(),
orderDetail
.
getSkuId
()))
{
final
var
orderDetailBO
=
replaceOriginalDetailMap
.
get
(
orderDetail
.
getId
());
final
var
orderDetailAdjustBO
=
replaceAdjustDetailMap
.
get
(
orderDetail
.
getId
());
SettlementDTO
.
SettlementOrderDetail
beforeChange
=
buildSettlementOrderDetail
(
order
,
orderDetail
.
getMenuDetailId
(),
orderDetailBO
.
getSkuId
(),
orderDetailBO
.
getCount
(),
orderDetailBO
.
getPrice
(),
"换菜前"
,
menuName
,
customerName
,
hisCustomerNo
,
menuDetailMap
,
mealMap
,
skuMap
);
classifyOrders
.
add
(
beforeChange
);
SettlementDTO
.
SettlementOrderDetail
afterChange
=
buildSettlementOrderDetail
(
order
,
orderDetail
.
getMenuDetailId
(),
orderDetail
.
getSkuId
(),
orderDetail
.
getCount
(),
orderDetailAdjustBO
.
getPrice
(),
"换菜后"
,
menuName
,
customerName
,
hisCustomerNo
,
menuDetailMap
,
mealMap
,
skuMap
);
classifyOrders
.
add
(
afterChange
);
}
// 构建订单详情
order
.
getOrderCode
();
order
.
getRemark
();
order
.
getAvoidRemark
();
SettlementDTO
.
SettlementOrderDetail
settlementOrderDetail
=
SettlementDTO
.
SettlementOrderDetail
.
builder
()
.
mealTime
(
order
.
getMealTime
()
!=
0L
?
LocalDateTimeUtil
.
of
(
order
.
getMealTime
()).
format
(
DateUtil
.
YYYY_MM_DD_LEFT_SYMBOL
)
:
""
)
.
code
(
order
.
getOrderCode
())
.
mealName
(
mealName
)
.
roomNo
(
roomNo
)
.
customerName
(
customerName
)
.
HISCustomerNo
(
hisCustomerNo
)
.
avoids
(
avoids
)
.
doctors
(
doctors
)
.
menuName
(
menuName
)
.
skuName
(
skuName
)
.
count
(
orderDetail
.
getCount
()
!=
0
?
orderDetail
.
getCount
()
:
0
)
.
price
(
calculatePrice
(
orderDetail
.
getPrice
()))
.
totalPrice
(
calculateTotalPrice
(
orderDetail
.
getPrice
(),
orderDetail
.
getCount
()))
.
remark
(
order
.
getRemark
())
.
avoidRemark
(
order
.
getAvoidRemark
())
.
onlinePay
(
onlinePayDesc
)
.
build
();
classifyOrders
.
add
(
settlementOrderDetail
);
// 3. 判断已退款
if
(
orderDetail
.
getServeStatus
()
==
ServeStatusEnum
.
SERVE_REJECT
)
{
SettlementDTO
.
SettlementOrderDetail
refundRecord1
=
buildSettlementOrderDetail
(
order
,
orderDetail
.
getMenuDetailId
(),
orderDetail
.
getSkuId
(),
orderDetail
.
getCount
(),
orderDetail
.
getPrice
(),
"订餐"
,
menuName
,
customerName
,
hisCustomerNo
,
menuDetailMap
,
mealMap
,
skuMap
);
classifyOrders
.
add
(
refundRecord1
);
SettlementDTO
.
SettlementOrderDetail
refundRecord2
=
buildSettlementOrderDetail
(
order
,
orderDetail
.
getMenuDetailId
(),
orderDetail
.
getSkuId
(),
-
orderDetail
.
getCount
(),
orderDetail
.
getPrice
(),
"已退款"
,
menuName
,
customerName
,
hisCustomerNo
,
menuDetailMap
,
mealMap
,
skuMap
);
classifyOrders
.
add
(
refundRecord2
);
}
// 4. 如果既不是加餐,也不是换菜,也不是退款,才记录“订餐”
boolean
isNormal
=
!(
addOriginalDetailMap
.
containsKey
(
orderDetail
.
getId
())
&&
addOriginalDetailMap
.
get
(
orderDetail
.
getId
()).
getCount
()
!=
orderDetail
.
getCount
())
&&
!(
replaceOriginalDetailMap
.
containsKey
(
orderDetail
.
getId
())
&&
!
Objects
.
equals
(
replaceOriginalDetailMap
.
get
(
orderDetail
.
getId
()).
getSkuId
(),
orderDetail
.
getSkuId
()))
&&
orderDetail
.
getServeStatus
()
!=
ServeStatusEnum
.
SERVE_REJECT
;
if
(
isNormal
)
{
SettlementDTO
.
SettlementOrderDetail
normalRecord
=
buildSettlementOrderDetail
(
order
,
orderDetail
.
getMenuDetailId
(),
orderDetail
.
getSkuId
(),
orderDetail
.
getCount
(),
orderDetail
.
getPrice
(),
"订餐"
,
menuName
,
customerName
,
hisCustomerNo
,
menuDetailMap
,
mealMap
,
skuMap
);
classifyOrders
.
add
(
normalRecord
);
}
}
}
// 构建结算数据
...
...
@@ -535,17 +941,57 @@ public class SettlementServiceImpl implements SettlementService {
}
}
private
SettlementDTO
.
SettlementOrderDetail
buildSettlementOrderDetail
(
SingleClientCustomerOrderRpcResponse
order
,
int
menuDetailId
,
int
skuId
,
int
count
,
Integer
price
,
String
operationType
,
String
menuName
,
String
customerName
,
String
hisCustomerNo
,
Map
<
Integer
,
SingleMenuDetailRpcResponse
>
menuDetailMap
,
Map
<
Integer
,
SingleMealRpcResponse
>
mealMap
,
Map
<
Integer
,
SingleDishSkuByIdsRpcResponse
>
skuMap
)
{
String
mealName
=
getMealNameSafely
(
menuDetailId
,
menuDetailMap
,
mealMap
);
String
skuName
=
getSkuNameSafely
(
skuId
,
skuMap
);
String
roomNo
=
getRoomNoSafely
(
order
);
List
<
String
>
avoids
=
getAvoidsSafely
(
order
);
List
<
String
>
doctors
=
getDoctorsSafely
(
order
);
String
onlinePayDesc
=
getOnlinePayDescSafely
(
order
);
return
SettlementDTO
.
SettlementOrderDetail
.
builder
()
.
mealTime
(
order
.
getMealTime
()
!=
0L
?
LocalDateTimeUtil
.
of
(
order
.
getMealTime
()).
format
(
DateUtil
.
YYYY_MM_DD_LEFT_SYMBOL
)
:
""
)
.
code
(
order
.
getOrderCode
())
.
mealName
(
mealName
)
.
roomNo
(
roomNo
)
.
customerName
(
customerName
)
.
HISCustomerNo
(
hisCustomerNo
)
.
avoids
(
avoids
)
.
doctors
(
doctors
)
.
menuName
(
menuName
)
.
skuName
(
skuName
)
.
count
(
count
)
.
price
(
calculatePrice
(
price
))
.
totalPrice
(
calculateTotalPrice
(
price
,
count
))
.
remark
(
order
.
getRemark
())
.
avoidRemark
(
order
.
getAvoidRemark
())
.
onlinePay
(
onlinePayDesc
)
.
operationType
(
operationType
)
.
transactionId
(
operationType
.
equals
(
"已退款"
)
?
""
:
order
.
getTransactionId
())
.
build
();
}
/**
* 安全获取餐别名称
*/
private
String
getMealNameSafely
(
SingleClientCustomerOrderDetailRpcResponse
orderDetail
,
Map
<
Integer
,
SingleMenuDetailRpcResponse
>
menuDetailMap
,
Map
<
Integer
,
SingleMealRpcResponse
>
mealMap
)
{
if
(
orderDetail
==
null
||
orderDetail
.
getMenuDetailId
()
==
0
)
{
private
String
getMealNameSafely
(
int
menuDetailId
,
Map
<
Integer
,
SingleMenuDetailRpcResponse
>
menuDetailMap
,
Map
<
Integer
,
SingleMealRpcResponse
>
mealMap
)
{
if
(
menuDetailId
==
0
)
{
return
""
;
}
final
var
menuDetail
=
menuDetailMap
.
get
(
orderDetail
.
getMenuDetailId
()
);
final
var
menuDetail
=
menuDetailMap
.
get
(
menuDetailId
);
if
(
menuDetail
==
null
||
menuDetail
.
getMealId
()
==
0
)
{
return
""
;
}
...
...
@@ -557,13 +1003,12 @@ public class SettlementServiceImpl implements SettlementService {
/**
* 安全获取SKU名称
*/
private
String
getSkuNameSafely
(
SingleClientCustomerOrderDetailRpcResponse
orderDetail
,
Map
<
Integer
,
SingleDishSkuByIdsRpcResponse
>
skuMap
)
{
if
(
orderDetail
==
null
||
orderDetail
.
getSkuId
()
==
0
)
{
private
String
getSkuNameSafely
(
int
skuId
,
Map
<
Integer
,
SingleDishSkuByIdsRpcResponse
>
skuMap
)
{
if
(
skuId
==
0
)
{
return
""
;
}
final
var
sku
=
skuMap
.
get
(
orderDetail
.
getSkuId
());
final
var
sku
=
skuMap
.
get
(
skuId
);
return
sku
!=
null
?
sku
.
getName
()
:
""
;
}
...
...
@@ -598,268 +1043,65 @@ public class SettlementServiceImpl implements SettlementService {
* 安全获取医嘱列表
*/
private
List
<
String
>
getDoctorsSafely
(
SingleClientCustomerOrderRpcResponse
order
)
{
if
(
order
==
null
)
{
return
Collections
.
emptyList
();
}
return
order
.
getCustomerNoticeJson
().
getDoctorsList
();
}
/**
* 安全获取在线支付描述
*/
private
String
getOnlinePayDescSafely
(
SingleClientCustomerOrderRpcResponse
order
)
{
if
(
order
==
null
)
{
return
""
;
}
try
{
String
desc
=
BaseProtoDescEnum
.
getDescByProtoEnum
(
order
.
getOnlinePay
(),
OnlinePayDescEnum
.
class
);
return
desc
!=
null
?
desc
:
""
;
}
catch
(
Exception
e
)
{
log
.
warn
(
"获取在线支付描述失败,orderId: {}"
,
order
.
getId
(),
e
);
return
""
;
}
}
/**
* 计算单价
*/
private
BigDecimal
calculatePrice
(
Integer
price
)
{
if
(
price
==
null
)
{
return
BigDecimal
.
ZERO
;
}
return
new
BigDecimal
(
price
).
divide
(
new
BigDecimal
(
100
),
2
,
RoundingMode
.
HALF_UP
);
}
/**
* 计算总价
*/
private
BigDecimal
calculateTotalPrice
(
Integer
price
,
Integer
count
)
{
if
(
price
==
null
||
count
==
null
)
{
return
BigDecimal
.
ZERO
;
}
return
new
BigDecimal
(
price
)
.
multiply
(
new
BigDecimal
(
count
))
.
divide
(
new
BigDecimal
(
100
),
2
,
RoundingMode
.
HALF_UP
);
}
/**
* 创建空的订单Excel
*/
private
ByteArrayOutputStream
createEmptyExcelByOrder
()
{
try
{
final
var
emptyData
=
SettlementDTO
.
SettlementDataByOrderDto
.
builder
()
.
classifyOrders
(
Collections
.
emptyList
())
.
build
();
return
writeToExcelByOrder
(
emptyData
);
}
catch
(
IOException
e
)
{
log
.
error
(
"创建空Excel失败"
,
e
);
throw
BusinessException
.
build
(
ErrorCodeEnum
.
GENERATE_EXCEL_ERROR
);
}
}
/**
* 按订单维度生成Excel
*/
private
static
ByteArrayOutputStream
writeToExcelByOrder
(
SettlementDTO
.
SettlementDataByOrderDto
settlementDataDto
)
throws
IOException
{
Workbook
workbook
=
new
XSSFWorkbook
();
Sheet
sheet
=
workbook
.
createSheet
(
"客人结算"
);
// 创建表头样式(黑色边框)
CellStyle
headerStyle
=
workbook
.
createCellStyle
();
headerStyle
.
setBorderTop
(
BorderStyle
.
THIN
);
headerStyle
.
setBorderBottom
(
BorderStyle
.
THIN
);
headerStyle
.
setBorderLeft
(
BorderStyle
.
THIN
);
headerStyle
.
setBorderRight
(
BorderStyle
.
THIN
);
headerStyle
.
setTopBorderColor
(
IndexedColors
.
BLACK
.
getIndex
());
headerStyle
.
setBottomBorderColor
(
IndexedColors
.
BLACK
.
getIndex
());
headerStyle
.
setLeftBorderColor
(
IndexedColors
.
BLACK
.
getIndex
());
headerStyle
.
setRightBorderColor
(
IndexedColors
.
BLACK
.
getIndex
());
// 创建数据行样式(浅灰色边框)
CellStyle
dataStyle
=
workbook
.
createCellStyle
();
dataStyle
.
setBorderTop
(
BorderStyle
.
THIN
);
dataStyle
.
setBorderBottom
(
BorderStyle
.
THIN
);
dataStyle
.
setBorderLeft
(
BorderStyle
.
THIN
);
dataStyle
.
setBorderRight
(
BorderStyle
.
THIN
);
dataStyle
.
setTopBorderColor
(
IndexedColors
.
GREY_25_PERCENT
.
getIndex
());
dataStyle
.
setBottomBorderColor
(
IndexedColors
.
GREY_25_PERCENT
.
getIndex
());
dataStyle
.
setLeftBorderColor
(
IndexedColors
.
GREY_25_PERCENT
.
getIndex
());
dataStyle
.
setRightBorderColor
(
IndexedColors
.
GREY_25_PERCENT
.
getIndex
());
int
rowNum
=
0
;
// 创建表头
Row
titleRow
=
sheet
.
createRow
(
rowNum
++);
int
columnNum
=
0
;
Cell
cell0
=
titleRow
.
createCell
(
columnNum
++);
cell0
.
setCellValue
(
"用餐时间"
);
cell0
.
setCellStyle
(
headerStyle
);
Cell
cell1
=
titleRow
.
createCell
(
columnNum
++);
cell1
.
setCellValue
(
"订单号"
);
cell1
.
setCellStyle
(
headerStyle
);
Cell
cell2
=
titleRow
.
createCell
(
columnNum
++);
cell2
.
setCellValue
(
"餐别"
);
cell2
.
setCellStyle
(
headerStyle
);
Cell
cell3
=
titleRow
.
createCell
(
columnNum
++);
cell3
.
setCellValue
(
"房间号"
);
cell3
.
setCellStyle
(
headerStyle
);
Cell
cell4
=
titleRow
.
createCell
(
columnNum
++);
cell4
.
setCellValue
(
"客户姓名"
);
cell4
.
setCellStyle
(
headerStyle
);
Cell
cell5
=
titleRow
.
createCell
(
columnNum
++);
cell5
.
setCellValue
(
"客户腕带号"
);
cell5
.
setCellStyle
(
headerStyle
);
Cell
cell6
=
titleRow
.
createCell
(
columnNum
++);
cell6
.
setCellValue
(
"忌口信息"
);
cell6
.
setCellStyle
(
headerStyle
);
Cell
cell7
=
titleRow
.
createCell
(
columnNum
++);
cell7
.
setCellValue
(
"医嘱信息"
);
cell7
.
setCellStyle
(
headerStyle
);
Cell
cell8
=
titleRow
.
createCell
(
columnNum
++);
cell8
.
setCellValue
(
"餐单名称"
);
cell8
.
setCellStyle
(
headerStyle
);
Cell
cell9
=
titleRow
.
createCell
(
columnNum
++);
cell9
.
setCellValue
(
"菜品名称"
);
cell9
.
setCellStyle
(
headerStyle
);
Cell
cell10
=
titleRow
.
createCell
(
columnNum
++);
cell10
.
setCellValue
(
"菜品份数"
);
cell10
.
setCellStyle
(
headerStyle
);
Cell
cell11
=
titleRow
.
createCell
(
columnNum
++);
cell11
.
setCellValue
(
"菜品单价"
);
cell11
.
setCellStyle
(
headerStyle
);
Cell
cell12
=
titleRow
.
createCell
(
columnNum
++);
cell12
.
setCellValue
(
"菜品金额"
);
cell12
.
setCellStyle
(
headerStyle
);
Cell
cell13
=
titleRow
.
createCell
(
columnNum
++);
cell13
.
setCellValue
(
"备注"
);
cell13
.
setCellStyle
(
headerStyle
);
Cell
cell14
=
titleRow
.
createCell
(
columnNum
++);
cell14
.
setCellValue
(
"支付方式"
);
cell14
.
setCellStyle
(
headerStyle
);
// 填充数据
final
var
classifyOrders
=
settlementDataDto
.
getClassifyOrders
();
if
(
classifyOrders
!=
null
)
{
for
(
SettlementDTO
.
SettlementOrderDetail
orderDetail
:
classifyOrders
)
{
Row
dataRow
=
sheet
.
createRow
(
rowNum
++);
columnNum
=
0
;
Cell
dataCell0
=
dataRow
.
createCell
(
columnNum
++);
dataCell0
.
setCellValue
(
orderDetail
.
getMealTime
()
!=
null
?
orderDetail
.
getMealTime
()
:
""
);
dataCell0
.
setCellStyle
(
dataStyle
);
Cell
dataCell1
=
dataRow
.
createCell
(
columnNum
++);
dataCell1
.
setCellValue
(
orderDetail
.
getCode
()
!=
null
?
orderDetail
.
getCode
()
:
""
);
dataCell1
.
setCellStyle
(
dataStyle
);
Cell
dataCell2
=
dataRow
.
createCell
(
columnNum
++);
dataCell2
.
setCellValue
(
orderDetail
.
getMealName
()
!=
null
?
orderDetail
.
getMealName
()
:
""
);
dataCell2
.
setCellStyle
(
dataStyle
);
Cell
dataCell3
=
dataRow
.
createCell
(
columnNum
++);
dataCell3
.
setCellValue
(
orderDetail
.
getRoomNo
()
!=
null
?
orderDetail
.
getRoomNo
()
:
""
);
dataCell3
.
setCellStyle
(
dataStyle
);
Cell
dataCell4
=
dataRow
.
createCell
(
columnNum
++);
dataCell4
.
setCellValue
(
orderDetail
.
getCustomerName
()
!=
null
?
orderDetail
.
getCustomerName
()
:
""
);
dataCell4
.
setCellStyle
(
dataStyle
);
Cell
dataCell5
=
dataRow
.
createCell
(
columnNum
++);
dataCell5
.
setCellValue
(
orderDetail
.
getHISCustomerNo
()
!=
null
?
orderDetail
.
getHISCustomerNo
()
:
""
);
dataCell5
.
setCellStyle
(
dataStyle
);
// 忌口列表转字符串
String
avoidsStr
=
orderDetail
.
getAvoids
()
!=
null
?
String
.
join
(
", "
,
orderDetail
.
getAvoids
())
:
""
;
Cell
dataCell6
=
dataRow
.
createCell
(
columnNum
++);
dataCell6
.
setCellValue
(
avoidsStr
);
dataCell6
.
setCellStyle
(
dataStyle
);
// 医嘱列表转字符串
String
doctorsStr
=
orderDetail
.
getDoctors
()
!=
null
?
String
.
join
(
", "
,
orderDetail
.
getDoctors
())
:
""
;
Cell
dataCell7
=
dataRow
.
createCell
(
columnNum
++);
dataCell7
.
setCellValue
(
doctorsStr
);
dataCell7
.
setCellStyle
(
dataStyle
);
Cell
dataCell8
=
dataRow
.
createCell
(
columnNum
++);
dataCell8
.
setCellValue
(
orderDetail
.
getMenuName
()
!=
null
?
orderDetail
.
getMenuName
()
:
""
);
dataCell8
.
setCellStyle
(
dataStyle
);
Cell
dataCell9
=
dataRow
.
createCell
(
columnNum
++);
dataCell9
.
setCellValue
(
orderDetail
.
getSkuName
()
!=
null
?
orderDetail
.
getSkuName
()
:
""
);
dataCell9
.
setCellStyle
(
dataStyle
);
Cell
dataCell10
=
dataRow
.
createCell
(
columnNum
++);
dataCell10
.
setCellValue
(
orderDetail
.
getCount
()
!=
null
?
orderDetail
.
getCount
()
:
0
);
dataCell10
.
setCellStyle
(
dataStyle
);
// 价格
Cell
dataCell11
=
dataRow
.
createCell
(
columnNum
++);
if
(
orderDetail
.
getPrice
()
!=
null
)
{
dataCell11
.
setCellValue
(
orderDetail
.
getPrice
().
doubleValue
());
}
else
{
dataCell11
.
setCellValue
(
0.0
);
}
dataCell11
.
setCellStyle
(
dataStyle
);
// 总价
Cell
dataCell12
=
dataRow
.
createCell
(
columnNum
++);
if
(
orderDetail
.
getTotalPrice
()
!=
null
)
{
dataCell12
.
setCellValue
(
orderDetail
.
getTotalPrice
().
doubleValue
());
}
else
{
dataCell12
.
setCellValue
(
0.0
);
}
dataCell12
.
setCellStyle
(
dataStyle
);
if
(
order
==
null
)
{
return
Collections
.
emptyList
();
}
// 合并备注和忌口备注,用分号分割,备注在前
String
remark
=
orderDetail
.
getRemark
()
!=
null
?
orderDetail
.
getRemark
()
:
""
;
String
avoidRemark
=
orderDetail
.
getAvoidRemark
()
!=
null
?
orderDetail
.
getAvoidRemark
()
:
""
;
String
combinedRemark
=
""
;
if
(!
remark
.
isEmpty
()
&&
!
avoidRemark
.
isEmpty
())
{
combinedRemark
=
remark
+
";"
+
avoidRemark
;
}
else
if
(!
remark
.
isEmpty
())
{
combinedRemark
=
remark
;
}
else
if
(!
avoidRemark
.
isEmpty
())
{
combinedRemark
=
avoidRemark
;
}
Cell
dataCell13
=
dataRow
.
createCell
(
columnNum
++);
dataCell13
.
setCellValue
(
combinedRemark
);
dataCell13
.
setCellStyle
(
dataStyle
);
return
order
.
getCustomerNoticeJson
().
getDoctorsList
();
}
Cell
dataCell14
=
dataRow
.
createCell
(
columnNum
++);
dataCell14
.
setCellValue
(
orderDetail
.
getOnlinePay
()
!=
null
?
orderDetail
.
getOnlinePay
()
:
""
);
dataCell14
.
setCellStyle
(
dataStyle
);
}
/**
* 安全获取在线支付描述
*/
private
String
getOnlinePayDescSafely
(
SingleClientCustomerOrderRpcResponse
order
)
{
if
(
order
==
null
)
{
return
""
;
}
// 自动调整列宽
for
(
int
i
=
0
;
i
<
15
;
i
++)
{
sheet
.
autoSizeColumn
(
i
);
try
{
String
desc
=
BaseProtoDescEnum
.
getDescByProtoEnum
(
order
.
getOnlinePay
(),
OnlinePayDescEnum
.
class
);
return
desc
!=
null
?
desc
:
""
;
}
catch
(
Exception
e
)
{
log
.
warn
(
"获取在线支付描述失败,orderId: {}"
,
order
.
getId
(),
e
);
return
""
;
}
}
// 将工作簿内容写入字节数组输出流
ByteArrayOutputStream
outputStream
=
new
ByteArrayOutputStream
();
workbook
.
write
(
outputStream
);
workbook
.
close
();
/**
* 计算单价
*/
private
BigDecimal
calculatePrice
(
Integer
price
)
{
if
(
price
==
null
)
{
return
BigDecimal
.
ZERO
;
}
return
new
BigDecimal
(
price
).
divide
(
new
BigDecimal
(
100
),
2
,
RoundingMode
.
HALF_UP
);
}
return
outputStream
;
/**
* 计算总价
*/
private
BigDecimal
calculateTotalPrice
(
Integer
price
,
Integer
count
)
{
if
(
price
==
null
||
count
==
null
)
{
return
BigDecimal
.
ZERO
;
}
return
new
BigDecimal
(
price
)
.
multiply
(
new
BigDecimal
(
count
))
.
divide
(
new
BigDecimal
(
100
),
2
,
RoundingMode
.
HALF_UP
);
}
/**
* 创建空的订单Excel
*/
private
ByteArrayOutputStream
createEmptyExcelByOrder
()
{
try
{
final
var
emptyData
=
SettlementDTO
.
SettlementDataByOrderDto
.
builder
()
.
classifyOrders
(
Collections
.
emptyList
())
.
build
();
return
writeToExcelByOrder
(
emptyData
);
}
catch
(
IOException
e
)
{
log
.
error
(
"创建空Excel失败"
,
e
);
throw
BusinessException
.
build
(
ErrorCodeEnum
.
GENERATE_EXCEL_ERROR
);
}
}
public
ByteArrayOutputStream
generateOrderSettlementExcelBySku
(
SettlementRequestDto
settlementRequest
)
{
...
...
@@ -1249,10 +1491,10 @@ public class SettlementServiceImpl implements SettlementService {
}
// 安全获取餐别名称
String
mealName
=
getMealNameSafely
(
orderDetail
,
menuDetailMap
,
mealMap
);
String
mealName
=
getMealNameSafely
(
orderDetail
.
getMenuDetailId
()
,
menuDetailMap
,
mealMap
);
// 安全获取SKU名称
String
skuName
=
getSkuNameSafely
(
orderDetail
,
skuMap
);
String
skuName
=
getSkuNameSafely
(
orderDetail
.
getSkuId
()
,
skuMap
);
// 安全获取忌口信息(列表转字符串)
List
<
String
>
avoidsList
=
getAvoidsSafely
(
order
);
...
...
@@ -1304,186 +1546,4 @@ public class SettlementServiceImpl implements SettlementService {
}
}
/**
* 生成分餐表Excel
*/
private
static
ByteArrayOutputStream
writeToExcelBySeparateMeal
(
SeparateMealDataDto
separateMealDataDto
)
throws
IOException
{
Workbook
workbook
=
new
XSSFWorkbook
();
Sheet
sheet
=
workbook
.
createSheet
(
"分餐表"
);
// 创建标题样式(合并单元格标题)
CellStyle
titleStyle
=
workbook
.
createCellStyle
();
titleStyle
.
setAlignment
(
HorizontalAlignment
.
CENTER
);
titleStyle
.
setVerticalAlignment
(
VerticalAlignment
.
CENTER
);
titleStyle
.
setBorderTop
(
BorderStyle
.
THIN
);
titleStyle
.
setBorderBottom
(
BorderStyle
.
THIN
);
titleStyle
.
setBorderLeft
(
BorderStyle
.
THIN
);
titleStyle
.
setBorderRight
(
BorderStyle
.
THIN
);
titleStyle
.
setTopBorderColor
(
IndexedColors
.
BLACK
.
getIndex
());
titleStyle
.
setBottomBorderColor
(
IndexedColors
.
BLACK
.
getIndex
());
titleStyle
.
setLeftBorderColor
(
IndexedColors
.
BLACK
.
getIndex
());
titleStyle
.
setRightBorderColor
(
IndexedColors
.
BLACK
.
getIndex
());
Font
titleFont
=
workbook
.
createFont
();
titleFont
.
setBold
(
true
);
titleFont
.
setFontHeightInPoints
((
short
)
16
);
titleStyle
.
setFont
(
titleFont
);
// 创建表头样式(黑色边框)
CellStyle
headerStyle
=
workbook
.
createCellStyle
();
headerStyle
.
setBorderTop
(
BorderStyle
.
THIN
);
headerStyle
.
setBorderBottom
(
BorderStyle
.
THIN
);
headerStyle
.
setBorderLeft
(
BorderStyle
.
THIN
);
headerStyle
.
setBorderRight
(
BorderStyle
.
THIN
);
headerStyle
.
setTopBorderColor
(
IndexedColors
.
BLACK
.
getIndex
());
headerStyle
.
setBottomBorderColor
(
IndexedColors
.
BLACK
.
getIndex
());
headerStyle
.
setLeftBorderColor
(
IndexedColors
.
BLACK
.
getIndex
());
headerStyle
.
setRightBorderColor
(
IndexedColors
.
BLACK
.
getIndex
());
// 创建数据行样式(浅灰色边框)
CellStyle
dataStyle
=
workbook
.
createCellStyle
();
dataStyle
.
setBorderTop
(
BorderStyle
.
THIN
);
dataStyle
.
setBorderBottom
(
BorderStyle
.
THIN
);
dataStyle
.
setBorderLeft
(
BorderStyle
.
THIN
);
dataStyle
.
setBorderRight
(
BorderStyle
.
THIN
);
dataStyle
.
setTopBorderColor
(
IndexedColors
.
GREY_25_PERCENT
.
getIndex
());
dataStyle
.
setBottomBorderColor
(
IndexedColors
.
GREY_25_PERCENT
.
getIndex
());
dataStyle
.
setLeftBorderColor
(
IndexedColors
.
GREY_25_PERCENT
.
getIndex
());
dataStyle
.
setRightBorderColor
(
IndexedColors
.
GREY_25_PERCENT
.
getIndex
());
int
rowNum
=
0
;
// 第一行:创建合并单元格标题
Row
mainTitleRow
=
sheet
.
createRow
(
rowNum
++);
Cell
mainTitleCell
=
mainTitleRow
.
createCell
(
0
);
mainTitleCell
.
setCellValue
(
"住院客户分餐表"
);
mainTitleCell
.
setCellStyle
(
titleStyle
);
// 合并第一行的8列
CellRangeAddress
titleRegion
=
new
CellRangeAddress
(
0
,
0
,
0
,
8
);
sheet
.
addMergedRegion
(
titleRegion
);
// 为合并区域设置边框
RegionUtil
.
setBorderTop
(
BorderStyle
.
THIN
,
titleRegion
,
sheet
);
RegionUtil
.
setBorderBottom
(
BorderStyle
.
THIN
,
titleRegion
,
sheet
);
RegionUtil
.
setBorderLeft
(
BorderStyle
.
THIN
,
titleRegion
,
sheet
);
RegionUtil
.
setBorderRight
(
BorderStyle
.
THIN
,
titleRegion
,
sheet
);
RegionUtil
.
setTopBorderColor
(
IndexedColors
.
BLACK
.
getIndex
(),
titleRegion
,
sheet
);
RegionUtil
.
setBottomBorderColor
(
IndexedColors
.
BLACK
.
getIndex
(),
titleRegion
,
sheet
);
RegionUtil
.
setLeftBorderColor
(
IndexedColors
.
BLACK
.
getIndex
(),
titleRegion
,
sheet
);
RegionUtil
.
setRightBorderColor
(
IndexedColors
.
BLACK
.
getIndex
(),
titleRegion
,
sheet
);
// 第二行:创建表头
Row
titleRow
=
sheet
.
createRow
(
rowNum
++);
int
columnNum
=
0
;
Cell
cell0
=
titleRow
.
createCell
(
columnNum
++);
cell0
.
setCellValue
(
"餐别"
);
cell0
.
setCellStyle
(
headerStyle
);
Cell
cell1
=
titleRow
.
createCell
(
columnNum
++);
cell1
.
setCellValue
(
"房间号"
);
cell1
.
setCellStyle
(
headerStyle
);
Cell
cell2
=
titleRow
.
createCell
(
columnNum
++);
cell2
.
setCellValue
(
"客户姓名"
);
cell2
.
setCellStyle
(
headerStyle
);
Cell
cell3
=
titleRow
.
createCell
(
columnNum
++);
cell3
.
setCellValue
(
"医嘱信息"
);
cell3
.
setCellStyle
(
headerStyle
);
Cell
cell4
=
titleRow
.
createCell
(
columnNum
++);
cell4
.
setCellValue
(
"餐单名称"
);
cell4
.
setCellStyle
(
headerStyle
);
Cell
cell5
=
titleRow
.
createCell
(
columnNum
++);
cell5
.
setCellValue
(
"菜品名称"
);
cell5
.
setCellStyle
(
headerStyle
);
Cell
cell6
=
titleRow
.
createCell
(
columnNum
++);
cell6
.
setCellValue
(
"菜品数量"
);
cell6
.
setCellStyle
(
headerStyle
);
Cell
cell7
=
titleRow
.
createCell
(
columnNum
++);
cell7
.
setCellValue
(
"忌口信息"
);
cell7
.
setCellStyle
(
headerStyle
);
Cell
cell8
=
titleRow
.
createCell
(
columnNum
++);
cell8
.
setCellValue
(
"备注"
);
cell8
.
setCellStyle
(
headerStyle
);
// 填充数据
final
var
mealDetails
=
separateMealDataDto
.
getMealDetails
();
if
(
mealDetails
!=
null
)
{
for
(
SeparateMealDetail
mealDetail
:
mealDetails
)
{
Row
dataRow
=
sheet
.
createRow
(
rowNum
++);
columnNum
=
0
;
Cell
dataCell0
=
dataRow
.
createCell
(
columnNum
++);
dataCell0
.
setCellValue
(
mealDetail
.
getMealName
()
!=
null
?
mealDetail
.
getMealName
()
:
""
);
dataCell0
.
setCellStyle
(
dataStyle
);
Cell
dataCell1
=
dataRow
.
createCell
(
columnNum
++);
dataCell1
.
setCellValue
(
mealDetail
.
getRoomNo
()
!=
null
?
mealDetail
.
getRoomNo
()
:
""
);
dataCell1
.
setCellStyle
(
dataStyle
);
Cell
dataCell2
=
dataRow
.
createCell
(
columnNum
++);
dataCell2
.
setCellValue
(
mealDetail
.
getCustomerName
()
!=
null
?
mealDetail
.
getCustomerName
()
:
""
);
dataCell2
.
setCellStyle
(
dataStyle
);
Cell
dataCell3
=
dataRow
.
createCell
(
columnNum
++);
dataCell3
.
setCellValue
(
mealDetail
.
getDoctors
()
!=
null
?
mealDetail
.
getDoctors
()
:
""
);
dataCell3
.
setCellStyle
(
dataStyle
);
Cell
dataCell4
=
dataRow
.
createCell
(
columnNum
++);
dataCell4
.
setCellValue
(
mealDetail
.
getMenuName
()
!=
null
?
mealDetail
.
getMenuName
()
:
""
);
dataCell4
.
setCellStyle
(
dataStyle
);
Cell
dataCell5
=
dataRow
.
createCell
(
columnNum
++);
dataCell5
.
setCellValue
(
mealDetail
.
getSkuName
()
!=
null
?
mealDetail
.
getSkuName
()
:
""
);
dataCell5
.
setCellStyle
(
dataStyle
);
Cell
dataCell6
=
dataRow
.
createCell
(
columnNum
++);
dataCell6
.
setCellValue
(
mealDetail
.
getCount
()
!=
null
?
mealDetail
.
getCount
()
:
0
);
dataCell6
.
setCellStyle
(
dataStyle
);
Cell
dataCell7
=
dataRow
.
createCell
(
columnNum
++);
dataCell7
.
setCellValue
(
mealDetail
.
getAvoids
()
!=
null
?
mealDetail
.
getAvoids
()
:
""
);
dataCell7
.
setCellStyle
(
dataStyle
);
Cell
dataCell8
=
dataRow
.
createCell
(
columnNum
++);
dataCell8
.
setCellValue
(
mealDetail
.
getRemark
()
!=
null
?
mealDetail
.
getRemark
()
:
""
);
dataCell8
.
setCellStyle
(
dataStyle
);
}
}
// 自动调整列宽
for
(
int
i
=
0
;
i
<
9
;
i
++)
{
sheet
.
autoSizeColumn
(
i
);
}
// 将工作簿内容写入字节数组输出流
ByteArrayOutputStream
outputStream
=
new
ByteArrayOutputStream
();
workbook
.
write
(
outputStream
);
workbook
.
close
();
return
outputStream
;
}
/**
* 创建空的分餐表Excel(无数据)
*/
private
static
ByteArrayOutputStream
createEmptyExcelBySeparateMeal
()
{
try
{
SeparateMealDataDto
emptyData
=
SeparateMealDataDto
.
builder
()
.
mealDetails
(
new
ArrayList
<>())
.
build
();
return
writeToExcelBySeparateMeal
(
emptyData
);
}
catch
(
IOException
e
)
{
log
.
error
(
"创建空分餐表Excel失败"
,
e
);
throw
BusinessException
.
build
(
ErrorCodeEnum
.
GENERATE_EXCEL_ERROR
);
}
}
}
...
...
src/main/java/com/infoloop/tianting/utils/JsonUtil.java
View file @
de053f1
...
...
@@ -2,6 +2,7 @@ package com.infoloop.tianting.utils;
import
com.fasterxml.jackson.annotation.JsonInclude
;
import
com.fasterxml.jackson.core.JsonProcessingException
;
import
com.fasterxml.jackson.core.type.TypeReference
;
import
com.fasterxml.jackson.databind.DeserializationFeature
;
import
com.fasterxml.jackson.databind.JsonNode
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
...
...
@@ -41,6 +42,14 @@ public class JsonUtil {
}
}
public
static
<
T
>
T
readJsonAs
(
final
String
json
,
final
TypeReference
<
T
>
typeRef
)
{
try
{
return
OBJECT_MAPPER
.
readValue
(
json
,
typeRef
);
}
catch
(
IOException
e
)
{
throw
new
RuntimeException
(
e
);
}
}
public
static
<
T
>
T
convertValue
(
final
Object
object
,
final
Class
<
T
>
clazz
)
{
return
OBJECT_MAPPER
.
convertValue
(
object
,
clazz
);
}
...
...
src/main/proto/ClientCustomerOrderService.proto
View file @
de053f1
...
...
@@ -32,6 +32,7 @@ service ClientCustomerOrderServiceRpc {
// 操作记录
rpc
GetOrderOperationRecordsByOrderId
(
GetOrderOperationRecordsByOrderIdRequest
)
returns
(
GetOrderOperationRecordsByOrderIdResponse
)
{}
rpc
GetOrderOperationRecordsByOrderIds
(
GetOrderOperationRecordsByOrderIdsRequest
)
returns
(
GetOrderOperationRecordsByOrderIdsResponse
)
{}
rpc
BatchCreateOrderOperationRecords
(
BatchCreateOrderOperationRecordsRequest
)
returns
(
BatchCreateOrderOperationRecordsResponse
)
{}
...
...
@@ -624,6 +625,15 @@ message GetOrderOperationRecordsByOrderIdResponse {
repeated
OrderOperationRecord
responses
=
1
;
}
message
GetOrderOperationRecordsByOrderIdsRequest
{
int32
enterpriseId
=
1
;
repeated
int32
orderIds
=
2
;
}
message
GetOrderOperationRecordsByOrderIdsResponse
{
repeated
OrderOperationRecord
responses
=
1
;
}
message
OrderOperationRecordCreation
{
int32
orderId
=
1
;
OrderOperationType
type
=
2
;
...
...
Please
register
or
login
to post a comment