zhuyifan

菜品售卖量接口

Showing 21 changed files with 643 additions and 49 deletions
package com.infoloop.tianting.controller;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import com.infoloop.tianting.annotation.RepeatSubmit;
import com.infoloop.tianting.model.dto.OrderDbDTO;
import com.infoloop.tianting.model.dto.OrderDbDTO.BatchUpdateOrderDetailResponse;
import com.infoloop.tianting.model.dto.OrderDbDTO.CreateOrderDto;
......@@ -67,6 +68,7 @@ public class OrderController {
@ApiOperation(value = "创建订单")
@PostMapping("/orders")
@ResponseStatus(HttpStatus.OK)
@RepeatSubmit(prefix = "createOrder")
public CreateOrderResponse createOrder(@Valid @RequestBody CreateOrderDto createOrderDto) {
return orderService.createOrder(createOrderDto);
}
......@@ -74,12 +76,11 @@ public class OrderController {
@ApiOperation(value = "院区端创建订单")
@PostMapping("/operator/orders")
@ResponseStatus(HttpStatus.OK)
public CreateOrderResponse createOrderByOperator(
@Valid @RequestBody OrderDbDTO.OperatorCreateOrderDto createOrderDto) {
@RepeatSubmit(prefix = "createOrder")
public CreateOrderResponse createOrderByOperator(@Valid @RequestBody OrderDbDTO.OperatorCreateOrderDto createOrderDto) {
return orderService.orderCreation(createOrderDto);
}
// @SaIgnore
@ApiOperation(value = "修改订单")
@PatchMapping("/orders/modification")
@ResponseStatus(HttpStatus.OK)
......@@ -87,12 +88,10 @@ public class OrderController {
return orderService.updateOrder(updateOrderDto);
}
// @SaIgnore
@ApiOperation(value = "批量修改订单详情")
@PatchMapping("/order_details/modification")
@ResponseStatus(HttpStatus.OK)
public BatchUpdateOrderDetailResponse batchUpdateOrderDetails(
@Valid @RequestBody OrderDbDTO.OrderDetailBatchUpdateDto updateDto) {
public BatchUpdateOrderDetailResponse batchUpdateOrderDetails(@Valid @RequestBody OrderDbDTO.OrderDetailBatchUpdateDto updateDto) {
return orderService.batchUpdateOrderDetails(updateDto);
}
......
......@@ -8,7 +8,6 @@ import com.infoloop.tianting.model.dto.SkuSellQuantityDTO;
import com.infoloop.tianting.model.vo.SkuSellQuantityStatisticsVO;
import com.infoloop.tianting.model.vo.SkuSellQuantityVO;
import com.infoloop.tianting.service.SkuService;
import com.infoloop.tianting.utils.PageUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
......@@ -25,7 +24,6 @@ import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
import java.util.Collections;
import java.util.List;
@Api(tags = "sku")
......@@ -41,7 +39,7 @@ public class SkuController {
@ApiOperation(value = "根据sku ids获取")
@PostMapping("/skus")
@ResponseStatus(HttpStatus.OK)
public List<SkuDto> getOrderByCustomerId(@Valid @RequestBody SkuIdsDto skuIdsDto) {
public List<SkuDto> getSkusByIds(@Valid @RequestBody SkuIdsDto skuIdsDto) {
return skuService.getSkusByIds(skuIdsDto.getIds());
}
......@@ -49,29 +47,28 @@ public class SkuController {
@GetMapping("/stall/{stallId}/skusellquantities/statistics")
@ResponseStatus(HttpStatus.OK)
public SkuSellQuantityStatisticsVO querySkuSellQuantityStatistics(@PathVariable("stallId") int stallId) {
return SkuSellQuantityStatisticsVO.builder().build();
return skuService.querySkuSellQuantityStatistics(stallId);
}
@ApiOperation(value = "分页查询菜品售卖量")
@PostMapping("/skusellquantities/query")
@ResponseStatus(HttpStatus.OK)
public PageResult<SkuSellQuantityVO> querySkuSellQuantity(@Valid @RequestBody SkuSellQuantityDTO.QuerySkuSellQuantityDTO querySkuSellQuantityDTO) {
SkuSellQuantityVO skuSellQuantityVO = SkuSellQuantityVO.builder().build();
return PageUtil.buildEmpty(skuSellQuantityVO);
return skuService.querySkuSellQuantity(querySkuSellQuantityDTO);
}
@ApiOperation(value = "批量设置菜品售卖量")
@PutMapping("/stall/{stallId}/skusellquantities/batchset")
@ResponseStatus(HttpStatus.CREATED)
public void batchSetSkuSellQuantity(@PathVariable("stallId") int stallId,
public boolean batchSetSkuSellQuantity(@PathVariable("stallId") int stallId,
@Valid @RequestBody SkuSellQuantityDTO.BatchSetSkuSellQuantityDTO batchSetSkuSellQuantityDTO) {
return skuService.batchSetSkuSellQuantity(stallId, batchSetSkuSellQuantityDTO);
}
@ApiOperation(value = "根据菜品ids批量查询菜品售卖量")
@PostMapping("/skusellquantities/querybyskuids")
@ResponseStatus(HttpStatus.OK)
public List<SkuSellQuantityVO> querySkuSellQuantityBySkuIds(@Valid @RequestBody SkuSellQuantityDTO.QuerySkuSellQuantityBySkuIdsDTO querySkuSellQuantityBySkuIdsDTO) {
return Collections.emptyList();
return skuService.querySkuSellQuantityBySkuIds(querySkuSellQuantityBySkuIdsDTO);
}
}
......
......@@ -29,6 +29,10 @@ public enum ErrorCodeEnum implements BaseEnum {
ORDER_COUNT_LIMIT(406000005, "已超过该餐单预定次数"),
QUERY_CLIENT_CUSTOMER_ERROR(406000006, "获取当日在住客户失败"),
SKUS_SOLD_OUT_TODAY(406000007, "下单菜品今日售罄"),
ORDER_CANCEL(406000008, "订单已自动取消")
;
private final int code;
......
package com.infoloop.tianting.logic.delay;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBlockingQueue;
import org.redisson.api.RedissonClient;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
@Slf4j
public class DelayTaskQueueExecutor<T> {
private final RedissonClient redissonClient;
private final RBlockingQueue<T> blockingDeque;
private final Processor<T> processor;
private final ExecutorService executorService;
private volatile boolean running = true;
public interface Processor<T> {
void process(T task) throws InterruptedException;
}
public DelayTaskQueueExecutor(String threadName, RedissonClient redissonClient, RBlockingQueue<T> blockingDeque, Processor<T> processor) {
this.redissonClient = redissonClient;
this.blockingDeque = blockingDeque;
this.processor = processor;
this.executorService = Executors.newSingleThreadExecutor(r -> {
Thread t = new Thread(r);
t.setName(threadName);
return t;
});
this.executorService.submit(this::looper);
}
public void looper() {
while (running) {
try {
if (redissonClient.isShutdown()) {
shutdown();
return;
}
T task = blockingDeque.take();
processor.process(task);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
} catch (Exception e) {
log.error("Task processing error in thread: {}", Thread.currentThread().getName(), e);
}
}
}
public void shutdown() {
running = false;
executorService.shutdown();
try {
if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {
log.warn("Executor did not terminate in the specified time.");
executorService.shutdownNow();
}
} catch (InterruptedException e) {
log.error("Shutdown interrupted", e);
executorService.shutdownNow();
Thread.currentThread().interrupt();
}
}
}
package com.infoloop.tianting.logic.delay;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBlockingQueue;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
@Slf4j
@Service
@RequiredArgsConstructor
public class DelayedQueue<T> {
private final RedissonClient redissonClient;
private final Map<String, RDelayedQueue<T>> delayedQueues = new ConcurrentHashMap<>();
/**
* 初始化队列,传入队列名称和处理逻辑
*/
public void initQueue(String queueName, Consumer<T> processMessage) {
RBlockingQueue<T> blockingQueue = redissonClient.getBlockingQueue(queueName);
RDelayedQueue<T> delayedQueue = redissonClient.getDelayedQueue(blockingQueue);
delayedQueues.put(queueName, delayedQueue);
DelayTaskQueueExecutor.Processor<T> processor = task -> {
try {
processMessage.accept(task);
} catch (Exception e) {
log.error("Error processing task: {}", task, e);
}
};
new DelayTaskQueueExecutor<>(queueName + " DELAY TASK", redissonClient, blockingQueue, processor);
log.info("Initialized delay queue for {}", queueName);
}
public void addToQueue(String queueName, T message, long delay, TimeUnit timeUnit) {
RDelayedQueue<T> queue = getDelayedQueue(queueName);
queue.offer(message, delay, timeUnit);
log.info("Added to queue: {}, msg: {}, delay: {} {}", queueName, message, delay, timeUnit);
}
public void addToQueue(String queueName, List<T> messages, long delay, TimeUnit timeUnit) {
RDelayedQueue<T> queue = getDelayedQueue(queueName);
messages.forEach(message -> {
queue.offer(message, delay, timeUnit);
log.info("Added to queue: {}, msg: {}, delay: {} {}", queueName, message, delay, timeUnit);
});
}
private RDelayedQueue<T> getDelayedQueue(String queueName) {
RDelayedQueue<T> queue = delayedQueues.get(queueName);
if (queue == null) {
throw new IllegalArgumentException("Queue not initialized: " + queueName);
}
return queue;
}
}
package com.infoloop.tianting.logic.delay;
import com.infoloop.tianting.clientcustomerorderservice.PayStatusEnum;
import com.infoloop.tianting.logic.delay.param.AutoCancelParam;
import com.infoloop.tianting.model.bo.AddSkusSellQuantityBO;
import com.infoloop.tianting.service.client.OrderServiceRpcClient;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.stream.Collectors;
@Slf4j
@Component
@RequiredArgsConstructor
public class OrderAutoCancelDelayTask {
private final DelayedQueue<AutoCancelParam> delayedQueue;
private final OrderServiceRpcClient orderServiceRpcClient;
public static final String AUTO_CANCEL_ORDER_DELAY_QUEUE = "AUTO_CANCEL_ORDER_QUEUE";
@PostConstruct
public void init() {
delayedQueue.initQueue(AUTO_CANCEL_ORDER_DELAY_QUEUE, this::execute);
}
private void execute(AutoCancelParam param) {
try {
final var orderById = orderServiceRpcClient.getOrderById(param.getOrderId());
if (orderById == null) {
log.error("Order not found, orderId: {}", param.getOrderId());
return;
}
if (orderById.getPayStatus() == PayStatusEnum.PAY_CANCELED) {
log.info("Order {} already canceled, skipping.", param.getOrderId());
return;
}
if (orderById.getPayStatus() == PayStatusEnum.IN_PROGRESS || orderById.getPayStatus() == PayStatusEnum.SUCCEED) {
log.info("Order {} already successful, skipping.", param.getOrderId());
return;
}
final var isUpdated = orderServiceRpcClient.updateClientCustomerOrderCancel(orderById.getEnterpriseId(), orderById.getId());
if (isUpdated) {
final var orderDetails = orderServiceRpcClient.getOrderDetailsByOrderId(orderById.getId());
final var isSuccess = orderServiceRpcClient.addSkusSellQuantities(orderById.getEnterpriseId(), orderById.getStallId(), orderDetails.stream().map(e -> AddSkusSellQuantityBO.builder()
.skuId(e.getSkuId())
.quantity(-e.getCount())
.build()).collect(Collectors.toList()));
log.info("Order {} addSkusSellQuantities result: {}", param.getOrderId(), isSuccess);
}
} catch (Exception e) {
log.error("OrderAutoCancelDelayTask execute error", e);
}
}
}
package com.infoloop.tianting.logic.delay.param;
import lombok.Data;
@Data
public class AutoCancelParam {
private int orderId;
}
package com.infoloop.tianting.model.bo;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class AddSkusSellQuantityBO {
private int skuId;
private int quantity;
}
package com.infoloop.tianting.model.bo;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class SkuSellQuantityBO {
private Integer id;
private int skuId;
private int maxSellQuantity;
}
......@@ -41,6 +41,9 @@ public class SkuSellQuantityDTO {
@ApiModelProperty("菜品售卖状态")
@NotNull
private SkuSellQuantityStatus status;
@ApiModelProperty("关键字")
private String keyword;
}
@Data
......
......@@ -11,7 +11,7 @@ import lombok.Data;
public class SkuSellQuantityStatisticsVO {
@ApiModelProperty("全部")
private Long total;
private int total;
@ApiModelProperty("售罄")
private Long soldOut;
......
......@@ -6,6 +6,7 @@ import com.infoloop.tianting.model.dto.MenuDbDTO.BatchCreateMenuRefsResponseDto;
import com.infoloop.tianting.model.dto.MenuDbDTO.MenuDetailDto;
import com.infoloop.tianting.model.dto.MenuDbDTO.MenuDto;
import com.infoloop.tianting.model.dto.MenuDbDTO.MenuRefDto;
import java.util.List;
public interface MenuService {
......@@ -21,4 +22,6 @@ public interface MenuService {
List<MenuRefDto> getClientCustomerMenuRefsByCustomerId(Integer enterpriseId, Integer customerId);
BatchCreateMenuRefsResponseDto batchCreateMenuRefs(BatchCreateMenuRefsDto batchCreateMenuRefsDto);
List<Integer> queryMenuSkuIdsByStallId(int enterpriseId, int stallId);
}
......
package com.infoloop.tianting.service;
import com.infoloop.tianting.model.common.OrderPageResult;
import com.infoloop.tianting.model.common.PageResult;
import com.infoloop.tianting.model.dto.OrderDbDTO.BatchUpdateOrderDetailResponse;
import com.infoloop.tianting.model.dto.OrderDbDTO.getMenuOrderCountDto;
import com.infoloop.tianting.model.dto.OrderDbDTO.CreateOrderDto;
import com.infoloop.tianting.model.dto.OrderDbDTO.CreateOrderResponse;
import com.infoloop.tianting.model.dto.OrderDbDTO.OperatorCreateOrderDto;
......@@ -15,6 +13,8 @@ import com.infoloop.tianting.model.dto.OrderDbDTO.QueryOrderByConditionDto;
import com.infoloop.tianting.model.dto.OrderDbDTO.QueryOrderByPaginationDto;
import com.infoloop.tianting.model.dto.OrderDbDTO.UpdateOrderDto;
import com.infoloop.tianting.model.dto.OrderDbDTO.UpdateOrderResponse;
import com.infoloop.tianting.model.dto.OrderDbDTO.getMenuOrderCountDto;
import java.util.List;
public interface OrderService {
......
package com.infoloop.tianting.service;
import com.infoloop.tianting.model.common.PageResult;
import com.infoloop.tianting.model.dto.SkuDbDTO.SkuDto;
import com.infoloop.tianting.model.dto.SkuSellQuantityDTO;
import com.infoloop.tianting.model.vo.SkuSellQuantityStatisticsVO;
import com.infoloop.tianting.model.vo.SkuSellQuantityVO;
import javax.validation.Valid;
import java.util.List;
public interface SkuService {
List<SkuDto> getSkusByIds(List<Integer> ids);
SkuSellQuantityStatisticsVO querySkuSellQuantityStatistics(int stallId);
PageResult<SkuSellQuantityVO> querySkuSellQuantity(SkuSellQuantityDTO.QuerySkuSellQuantityDTO querySkuSellQuantityDTO);
boolean batchSetSkuSellQuantity(int stallId, SkuSellQuantityDTO.BatchSetSkuSellQuantityDTO batchSetSkuSellQuantityDTO);
List<SkuSellQuantityVO> querySkuSellQuantityBySkuIds(SkuSellQuantityDTO.@Valid QuerySkuSellQuantityBySkuIdsDTO querySkuSellQuantityBySkuIdsDTO);
}
......
......@@ -2,8 +2,10 @@ package com.infoloop.tianting.service.client;
import com.infoloop.tianting.SingleResponse;
import com.infoloop.tianting.SingleSpecialResponse;
import com.infoloop.tianting.clientcustomerorderservice.AddSkusSellQuantitiesRpcRequest;
import com.infoloop.tianting.clientcustomerorderservice.BatchCreateOrderOperationRecordsRequest;
import com.infoloop.tianting.clientcustomerorderservice.BatchCreateOrderOperationRecordsResponse;
import com.infoloop.tianting.clientcustomerorderservice.BatchSaveSkuSellQuantitiesRpcRequest;
import com.infoloop.tianting.clientcustomerorderservice.BatchUpdateClientCustomerOrderDetailsRpcRequest;
import com.infoloop.tianting.clientcustomerorderservice.BatchUpdateClientCustomerOrderDetailsRpcResponse;
import com.infoloop.tianting.clientcustomerorderservice.ClientCustomerOrderCreation;
......@@ -13,7 +15,6 @@ import com.infoloop.tianting.clientcustomerorderservice.ClientCustomerOrderModif
import com.infoloop.tianting.clientcustomerorderservice.ClientCustomerOrderServiceRpcGrpc;
import com.infoloop.tianting.clientcustomerorderservice.CloseTimeType;
import com.infoloop.tianting.clientcustomerorderservice.CreateClientCustomerOrderRpcRequest;
import com.infoloop.tianting.clientcustomerorderservice.CreateClientCustomerOrderRpcResponse;
import com.infoloop.tianting.clientcustomerorderservice.CustomerNotice;
import com.infoloop.tianting.clientcustomerorderservice.GetClientCustomerOrderByIdRpcRequest;
import com.infoloop.tianting.clientcustomerorderservice.GetClientCustomerOrderDetailsByIdsRpcRequest;
......@@ -28,13 +29,26 @@ import com.infoloop.tianting.clientcustomerorderservice.PayStatusEnum;
import com.infoloop.tianting.clientcustomerorderservice.QueryClientCustomerOrdersByConditionRpcRequest;
import com.infoloop.tianting.clientcustomerorderservice.QueryClientCustomerOrdersByPaginationRpcRequest;
import com.infoloop.tianting.clientcustomerorderservice.QueryClientCustomerOrdersByPaginationRpcResponse;
import com.infoloop.tianting.clientcustomerorderservice.QuerySkuSellQuantitiesByStallAndSkuIdsRpcRequest;
import com.infoloop.tianting.clientcustomerorderservice.QuerySkuSellQuantitiesByStallRpcRequest;
import com.infoloop.tianting.clientcustomerorderservice.ServeStatusEnum;
import com.infoloop.tianting.clientcustomerorderservice.SingleClientCustomerOrderDetailRpcResponse;
import com.infoloop.tianting.clientcustomerorderservice.SingleClientCustomerOrderRpcResponse;
import com.infoloop.tianting.clientcustomerorderservice.SingleSkuSellQuantityRpcResponse;
import com.infoloop.tianting.clientcustomerorderservice.SkuSellQuantity;
import com.infoloop.tianting.clientcustomerorderservice.SkuSellQuantityModification;
import com.infoloop.tianting.clientcustomerorderservice.UpdateClientCustomerOrderRpcRequest;
import com.infoloop.tianting.clientcustomerorderservice.UpdateClientCustomerOrderRpcResponse;
import com.infoloop.tianting.context.LoginContextHolder;
import com.infoloop.tianting.enums.OrderTypeEnum;
import com.infoloop.tianting.exception.ClientEndExceptions;
import com.infoloop.tianting.exception.ErrorCodeEnum;
import com.infoloop.tianting.logic.delay.DelayedQueue;
import com.infoloop.tianting.logic.delay.OrderAutoCancelDelayTask;
import com.infoloop.tianting.logic.delay.param.AutoCancelParam;
import com.infoloop.tianting.menuservice.CloseTimeTypeEnum;
import com.infoloop.tianting.model.bo.AddSkusSellQuantityBO;
import com.infoloop.tianting.model.bo.SkuSellQuantityBO;
import com.infoloop.tianting.model.dto.OperationDTO.BatchOperationDto;
import com.infoloop.tianting.model.dto.OperationDTO.SingleOperationDto;
import com.infoloop.tianting.model.dto.OrderDbDTO.CreateOrderDetailDto;
......@@ -60,6 +74,8 @@ import java.time.LocalDate;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;
@Slf4j
......@@ -72,6 +88,7 @@ public class OrderServiceRpcClient {
private final SkuServiceRpcClient skuServiceRpcClient;
private final OperatorServiceRpcClient operatorServiceRpcClient;
private final RedissonClient redissonClient;
private final DelayedQueue<AutoCancelParam> delayedQueue;
@Nullable
public SingleClientCustomerOrderRpcResponse getOrderById(Integer orderId) {
......@@ -149,6 +166,23 @@ public class OrderServiceRpcClient {
return orderServiceRpcBlockingStub.updateClientCustomerOrder(request);
}
public boolean updateClientCustomerOrderCancel(int enterpriseId, int id) {
final var modification = ClientCustomerOrderModification.newBuilder()
.setId(id)
.setShouldUpdateStatus(true)
.setStatus(OrderStatusEnum.ORDER_CANCELED)
.setShouldUpdatePayStatus(true)
.setPayStatus(PayStatusEnum.PAY_CANCELED)
.build();
final var request = UpdateClientCustomerOrderRpcRequest.newBuilder()
.setEnterpriseId(enterpriseId)
.setUpdatedBy(0)
.setUpdateSource(OrderSourceEnum.STALL)
.setModification(modification)
.build();
return orderServiceRpcBlockingStub.updateClientCustomerOrder(request).getIsUpdated();
}
public UpdateClientCustomerOrderRpcResponse updateClientCustomerOrderPaymentResult(SingleClientCustomerOrderRpcResponse order, ClientCustomerOrderModification modification) {
final var request = UpdateClientCustomerOrderRpcRequest.newBuilder()
.setEnterpriseId(order.getEnterpriseId())
......@@ -164,12 +198,12 @@ public class OrderServiceRpcClient {
OrderDetailBatchUpdateDto orderDetailBatchUpdateDto) {
final var operatorLoginInfo = LoginContextHolder.getLoginInfo();
final var operator = operatorServiceRpcClient.getCOperatorById(operatorLoginInfo.getId());
List<Integer> idsOfNeedUpdateMenuDetails = new ArrayList<>();
List<Integer> idsOfAddCount = new ArrayList<>();
List<OrderDetailDto> orgionalOrderDetails = new ArrayList<>();
final var idsOfNeedUpdateMenuDetails = new ArrayList<Integer>();
final var idsOfAddCount = new ArrayList<Integer>();
List<OrderDetailDto> originalOrderDetails = new ArrayList<>();
List<OrderDetailDto> newOrderDetails;
final var modifications = orderDetailBatchUpdateDto.getDetails().stream().map(d -> {
MealDetail mealDetail = MealDetail.newBuilder().build();
var mealDetail = MealDetail.newBuilder().build();
Integer menuDetailId = 0;
int mealId = 0;
int categoryId = 0;
......@@ -178,8 +212,7 @@ public class OrderServiceRpcClient {
if (d.getShouldUpdateMenuDetailId()) {
idsOfNeedUpdateMenuDetails.add(d.getId());
menuDetailId = d.getMenuDetailId();
final var menuDetail = menuServiceRpcClient.getMenuDetailById(
operatorLoginInfo.getEnterpriseId(), menuDetailId).getResponse();
final var menuDetail = menuServiceRpcClient.getMenuDetailById(operatorLoginInfo.getEnterpriseId(), menuDetailId).getResponse();
mealId = menuDetail.getMealId();
categoryId = menuDetail.getCategoryId();
skuId = menuDetail.getSkuId();
......@@ -249,7 +282,7 @@ public class OrderServiceRpcClient {
totalIds.addAll(idsOfAddCount);
if (!idsOfNeedUpdateMenuDetails.isEmpty() || !idsOfAddCount.isEmpty()) {
final var orgionalResponseList = getClientCustomerOrderDetailsByIds(totalIds);
orgionalOrderDetails = orgionalResponseList.stream().map(d ->
originalOrderDetails = orgionalResponseList.stream().map(d ->
OrderDetailDto.builder()
.id(d.getId())
.count(d.getCount())
......@@ -326,16 +359,16 @@ public class OrderServiceRpcClient {
// 替换菜品的操作记录
List<SingleOperationDto> operations = new ArrayList<>();
for (OrderDetailDto orgionalDetail : orgionalOrderDetails) {
for (OrderDetailDto originalDetail : originalOrderDetails) {
OrderOperationType orderOperationType = OrderOperationType.UNKNOWN_OPERATION_TYPE;
if (idsOfNeedUpdateMenuDetails.contains(orgionalDetail.getId())) {
if (idsOfNeedUpdateMenuDetails.contains(originalDetail.getId())) {
orderOperationType = OrderOperationType.REPLACE_DISHES;
} else if (idsOfAddCount.contains(orgionalDetail.getId())) {
} else if (idsOfAddCount.contains(originalDetail.getId())) {
orderOperationType = OrderOperationType.ADD_DISHES;
}
String orgionalDetailStr = "";
String originalDetailStr = "";
String newDetailStr = "";
final var newDetail = newOrderDetails.stream().filter(n -> n.getId().equals(orgionalDetail.getId())).findFirst();
final var newDetail = newOrderDetails.stream().filter(n -> n.getId().equals(originalDetail.getId())).findFirst();
if (newDetail.isPresent()) {
final var newOrderDetailOperation = OrderDetailOperationDto.builder()
.id(newDetail.get().getId())
......@@ -347,23 +380,23 @@ public class OrderServiceRpcClient {
.build();
newDetailStr = JsonUtil.writeAsJson(List.of(newOrderDetailOperation));
}
final var orgionalOrderDetailOperation = OrderDetailOperationDto.builder()
.id(orgionalDetail.getId())
.skuId(orgionalDetail.getSkuId())
.skuName(orgionalDetail.getShowName())
.count(orgionalDetail.getCount())
.adjustSkuRemark(orgionalDetail.getAdjustSkuRemark())
.serveStatus(orgionalDetail.getServeStatus().name())
final var originalOrderDetailOperation = OrderDetailOperationDto.builder()
.id(originalDetail.getId())
.skuId(originalDetail.getSkuId())
.skuName(originalDetail.getShowName())
.count(originalDetail.getCount())
.adjustSkuRemark(originalDetail.getAdjustSkuRemark())
.serveStatus(originalDetail.getServeStatus().name())
.build();
orgionalDetailStr = JsonUtil.writeAsJson(List.of(orgionalOrderDetailOperation));
originalDetailStr = JsonUtil.writeAsJson(List.of(originalOrderDetailOperation));
final var operation = SingleOperationDto.builder()
.orderId(orgionalDetail.getOrderId())
.orderId(originalDetail.getOrderId())
.shouldCreateAdjustOrderDetailJson(true)
.shouldCreateOriginalOrderDetailJson(true)
.shouldCreateAdjustOrderJson(false)
.shouldCreateOriginalOrderJson(false)
.adjustOrderDetailJson(newDetailStr)
.originalOrderDetailJson(orgionalDetailStr)
.originalOrderDetailJson(originalDetailStr)
.type(orderOperationType)
.build();
operations.add(operation);
......@@ -381,9 +414,7 @@ public class OrderServiceRpcClient {
return res;
}
public BatchCreateOrderOperationRecordsResponse batchCreateOrderOperationRecords(
BatchOperationDto batchOperationDto) {
public BatchCreateOrderOperationRecordsResponse batchCreateOrderOperationRecords(BatchOperationDto batchOperationDto) {
final var request = BatchCreateOrderOperationRecordsRequest.newBuilder()
.addAllCreations(batchOperationDto.getCreations().stream().map(c ->
OrderOperationRecordCreation.newBuilder()
......@@ -536,14 +567,81 @@ public class OrderServiceRpcClient {
.setShouldCreateOrderDetails(true)
.addAllOrderDetails(orderDetails)
.build();
CreateClientCustomerOrderRpcResponse orderResponse = orderServiceRpcBlockingStub
final var menuById = menuServiceRpcClient.getMenuById(createOrderDto.getEnterpriseId(), createOrderDto.getMenuId());
if (menuById.getResponse().getOrderRuleJson().getCloseTimeType() == CloseTimeTypeEnum.IMMEDIATELY) {
final var skuIds = createOrderDto.getOrderDetailDtos().stream().map(CreateOrderDetailDto::getSkuId).collect(Collectors.toList());
final var skuSellQuantities = this.querySkuSellQuantitiesByStallAndSkuIds(createOrderDto.getEnterpriseId(), createOrderDto.getStallId(), skuIds);
final var skuSellQuantityMap = skuSellQuantities.stream().collect(Collectors.toMap(SingleSkuSellQuantityRpcResponse::getSkuId, Function.identity()));
for (var orderDetail : createOrderDto.getOrderDetailDtos()) {
final var skuSellQuantityRpcResponse = skuSellQuantityMap.get(orderDetail.getSkuId());
if (skuSellQuantityRpcResponse == null) {
throw ClientEndExceptions.BusinessException.build(ErrorCodeEnum.SKUS_SOLD_OUT_TODAY);
}
if ((skuSellQuantityRpcResponse.getTodaySellQuantity() + orderDetail.getSkuId()) > skuSellQuantityRpcResponse.getMaxSellQuantity()) {
throw ClientEndExceptions.BusinessException.build(ErrorCodeEnum.SKUS_SOLD_OUT_TODAY);
}
}
}
final var orderResponse = orderServiceRpcBlockingStub
.createClientCustomerOrder(CreateClientCustomerOrderRpcRequest.newBuilder()
.setCreation(creation)
.setCreationSource(OrderSourceEnum.forNumber(createOrderDto.getCreationSource()))
.setEnterpriseId(createOrderDto.getEnterpriseId())
.setCreatedBy(createOrderDto.getCreatedBy())
.build());
if (orderResponse.getIsCreated() && menuById.getResponse().getOrderRuleJson().getCloseTimeType() == CloseTimeTypeEnum.IMMEDIATELY) {
final var isSuccess = this.addSkusSellQuantities(createOrderDto.getEnterpriseId(), createOrderDto.getStallId(),
orderDetails.stream().map(e -> AddSkusSellQuantityBO.builder()
.skuId(e.getSkuId())
.quantity(e.getCount())
.build()).collect(Collectors.toList()));
if (isSuccess) {
final var autoCancelParam = new AutoCancelParam();
autoCancelParam.setOrderId(orderResponse.getId());
delayedQueue.addToQueue(OrderAutoCancelDelayTask.AUTO_CANCEL_ORDER_DELAY_QUEUE, autoCancelParam, 15, TimeUnit.MINUTES);
}
}
return CreateOrderResponse.builder().id(orderResponse.getId()).isCreated(true).build();
}
public List<SingleSkuSellQuantityRpcResponse> querySkuSellQuantitiesByStall(int enterpriseId, int stallId) {
return orderServiceRpcBlockingStub.querySkuSellQuantitiesByStall(QuerySkuSellQuantitiesByStallRpcRequest.newBuilder()
.setEnterpriseId(enterpriseId)
.setStallId(stallId)
.build()).getResponsesList();
}
public List<SingleSkuSellQuantityRpcResponse> querySkuSellQuantitiesByStallAndSkuIds(int enterpriseId, int stallId, List<Integer> skuIds) {
return orderServiceRpcBlockingStub.querySkuSellQuantitiesByStallAndSkuIds(QuerySkuSellQuantitiesByStallAndSkuIdsRpcRequest.newBuilder()
.setEnterpriseId(enterpriseId)
.setStallId(stallId)
.addAllSkuIds(skuIds)
.build()).getResponsesList();
}
public boolean batchSaveSkuSellQuantities(int enterpriseId, int stallId, List<SkuSellQuantityBO> skuSellQuantityBOs) {
return orderServiceRpcBlockingStub.batchSaveSkuSellQuantities(BatchSaveSkuSellQuantitiesRpcRequest.newBuilder()
.setEnterpriseId(enterpriseId)
.setUpdatedBy(stallId)
.addAllSkuSellQuantityModifications(skuSellQuantityBOs.stream().map(e -> SkuSellQuantityModification.newBuilder()
.setId(e.getId() == null ? 0 : e.getId())
.setStallId(stallId)
.setSkuId(e.getSkuId())
.setMaxSellQuantity(e.getMaxSellQuantity())
.build()).collect(Collectors.toList()))
.build()).getIsSaved();
}
public boolean addSkusSellQuantities(int enterpriseId, int stallId, List<AddSkusSellQuantityBO> skuSellQuantityBOs) {
return orderServiceRpcBlockingStub.addSkusSellQuantities(AddSkusSellQuantitiesRpcRequest.newBuilder()
.setEnterpriseId(enterpriseId)
.setStallId(stallId)
.addAllSkuSellQuantities(skuSellQuantityBOs.stream().map(e -> SkuSellQuantity.newBuilder()
.setSkuId(e.getSkuId())
.setQuantity(e.getQuantity())
.build()).collect(Collectors.toList()))
.build()).getIsAdded();
}
}
......
......@@ -8,8 +8,11 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.infoloop.tianting.clientcustomerorderservice.ClientCustomerOrderModification;
import com.infoloop.tianting.clientcustomerorderservice.OrderStatusEnum;
import com.infoloop.tianting.clientcustomerorderservice.PayStatusEnum;
import com.infoloop.tianting.config.BusinessConfig;
import com.infoloop.tianting.exception.ClientEndExceptions;
import com.infoloop.tianting.exception.ErrorCodeEnum;
import com.infoloop.tianting.model.dto.PayDTO.PayInformRequestDto;
import com.infoloop.tianting.model.dto.PayDTO.PayResponseDto;
import com.infoloop.tianting.model.dto.PayDTO.ThirdPartyPayInformRequestDto;
......@@ -49,6 +52,11 @@ public class PayServiceClient {
private String clientId;
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 = businessConfig.getPayUrl();
String requestDate = DateUtil.formatDate(LocalDateTime.now(), DateUtil.YMDHMS);
ThirdPartyPayInformRequestDto jsonData = buildRequestData(payRequestDto, requestDate);
......
......@@ -2,6 +2,7 @@ package com.infoloop.tianting.service.client;
import com.infoloop.tianting.GeDishSkuByIdsRpcResponse;
import com.infoloop.tianting.GetSkusByIdsRpcRequest;
import com.infoloop.tianting.SingleSkuResponse;
import com.infoloop.tianting.SkuServiceProtoRpcGrpc;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -21,4 +22,12 @@ public class SkuServiceRpcClient {
.build();
return skuServiceProtoRpcBlockingStub.getDishSkusByIds(request);
}
public List<SingleSkuResponse> getSkusByIds(List<Integer> ids) {
final var request = GetSkusByIdsRpcRequest.newBuilder()
.addAllIds(ids)
.setIncludeDeleted(false)
.build();
return skuServiceProtoRpcBlockingStub.getSkusByIds(request).getResponseList();
}
}
......
package com.infoloop.tianting.service.impl;
import com.infoloop.tianting.context.LoginContextHolder;
import com.infoloop.tianting.menuservice.SingleMenuDetailRpcResponse;
import com.infoloop.tianting.menuservice.SingleMenuRpcResponse;
import com.infoloop.tianting.model.dto.MenuDbDTO.BatchCreateMenuRefsDto;
import com.infoloop.tianting.model.dto.MenuDbDTO.BatchCreateMenuRefsResponseDto;
import com.infoloop.tianting.model.dto.MenuDbDTO.DishRuleJson;
......@@ -197,4 +200,10 @@ public class MenuServiceImpl implements MenuService {
.build();
}
@Override
public List<Integer> queryMenuSkuIdsByStallId(int enterpriseId, int stallId) {
final var menuIds = menuServiceRpcClient.queryPublishedMenusByStallId(LoginContextHolder.getEnterpriseId(), stallId).getResponsesList().stream().map(SingleMenuRpcResponse::getId).collect(Collectors.toList());
return menuServiceRpcClient.queryMenuDetailsByMenuIds(LoginContextHolder.getEnterpriseId(), menuIds).getResponsesList().stream().map(SingleMenuDetailRpcResponse::getSkuId).distinct().collect(Collectors.toList());
}
}
......
......@@ -118,10 +118,7 @@ public class OrderServiceImpl implements OrderService {
createOrderDto.setCreationSource(OrderSourceEnum.STALL.getNumber());
createOrderDto.setEnterpriseId(operatorLoginInfo.getEnterpriseId());
// createOrderDto.setStallId();
var onlinePay = false;
if (menu.getOrderRuleJson().getModeOfPayment() == ModeOfPaymentEnum.ONLINE) {
onlinePay = true;
}
var onlinePay = menu.getOrderRuleJson().getModeOfPayment() == ModeOfPaymentEnum.ONLINE;
createOrderDto.setOnlinePay(onlinePay);
OrderTypeEnum orderType;
if (menu.getOrderRuleJson().getCloseTimeType() == CloseTimeTypeEnum.RESERVATION) {
......
package com.infoloop.tianting.service.impl;
import com.infoloop.tianting.SingleSkuResponse;
import com.infoloop.tianting.clientcustomerorderservice.SingleSkuSellQuantityRpcResponse;
import com.infoloop.tianting.context.LoginContextHolder;
import com.infoloop.tianting.enums.SkuSellQuantityStatus;
import com.infoloop.tianting.model.bo.SkuSellQuantityBO;
import com.infoloop.tianting.model.common.PageResult;
import com.infoloop.tianting.model.dto.SkuDbDTO.SkuDetailSingleResponseDto;
import com.infoloop.tianting.model.dto.SkuDbDTO.SkuDto;
import com.infoloop.tianting.model.dto.SkuDbDTO.SkuSpecialDetailSingleResponseDto;
import com.infoloop.tianting.model.dto.SkuSellQuantityDTO;
import com.infoloop.tianting.model.vo.SkuSellQuantityStatisticsVO;
import com.infoloop.tianting.model.vo.SkuSellQuantityVO;
import com.infoloop.tianting.service.MenuService;
import com.infoloop.tianting.service.SkuService;
import com.infoloop.tianting.service.client.OrderServiceRpcClient;
import com.infoloop.tianting.service.client.SkuServiceRpcClient;
import com.infoloop.tianting.utils.DateUtil;
import com.infoloop.tianting.utils.PageUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Comparator;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
@Slf4j
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class SkuServiceImpl implements SkuService {
private final MenuService menuService;
private final SkuServiceRpcClient skuServiceRpcClient;
private final OrderServiceRpcClient orderServiceRpcClient;
@Override
public List<SkuDto> getSkusByIds(List<Integer> ids) {
final var response = skuServiceRpcClient.getDishSkusByIds(ids);
......@@ -56,4 +75,133 @@ public class SkuServiceImpl implements SkuService {
.build()
).collect(Collectors.toList());
}
@Override
public SkuSellQuantityStatisticsVO querySkuSellQuantityStatistics(int stallId) {
final var skuIds = menuService.queryMenuSkuIdsByStallId(LoginContextHolder.getEnterpriseId(), stallId);
final var responses = orderServiceRpcClient.querySkuSellQuantitiesByStall(LoginContextHolder.getEnterpriseId(), stallId);
final var skuSellQuantitiesMap = responses.stream().collect(Collectors.toMap(SingleSkuSellQuantityRpcResponse::getSkuId, Function.identity()));
final var soldOut = skuIds.stream()
.filter(e -> skuSellQuantitiesMap.get(e) == null || skuSellQuantitiesMap.get(e).getMaxSellQuantity() == skuSellQuantitiesMap.get(e).getTodaySellQuantity())
.count();
final int total = skuIds.size();
return SkuSellQuantityStatisticsVO.builder()
.total(total)
.soldOut(soldOut)
.onSale(total - soldOut)
.build();
}
@Override
public PageResult<SkuSellQuantityVO> querySkuSellQuantity(SkuSellQuantityDTO.QuerySkuSellQuantityDTO querySkuSellQuantityDTO) {
final var stallId = querySkuSellQuantityDTO.getStallId();
final var enterpriseId = LoginContextHolder.getEnterpriseId();
final var skuIds = menuService.queryMenuSkuIdsByStallId(enterpriseId, stallId);
var responses = orderServiceRpcClient.querySkuSellQuantitiesByStall(enterpriseId, stallId);
final var skuSellQuantityMap = responses.stream().collect(Collectors.toMap(SingleSkuSellQuantityRpcResponse::getSkuId, Function.identity()));
responses = skuIds.stream()
.map(skuId -> {
var response = skuSellQuantityMap.get(skuId);
if (response == null) {
response = SingleSkuSellQuantityRpcResponse.newBuilder()
.setSkuId(skuId)
.setMaxSellQuantity(0)
.setTodaySellQuantity(0)
.build();
}
return response;
})
.collect(Collectors.toList());
if (querySkuSellQuantityDTO.getStatus() != SkuSellQuantityStatus.ALL) {
responses = responses.stream()
.filter(e -> {
switch (querySkuSellQuantityDTO.getStatus()) {
case SOLD_OUT:
return e.getMaxSellQuantity() == e.getTodaySellQuantity();
case ON_SALE:
return e.getMaxSellQuantity() != e.getTodaySellQuantity();
default:
return true;
}
})
.collect(Collectors.toList());
}
final var skuList = skuServiceRpcClient.getSkusByIds(responses.stream().map(SingleSkuSellQuantityRpcResponse::getSkuId).collect(Collectors.toList()));
final var skuMap = skuList.stream().collect(Collectors.toMap(SingleSkuResponse::getId, Function.identity()));
final var keyword = querySkuSellQuantityDTO.getKeyword();
if (keyword != null && !keyword.isEmpty()) {
responses = responses.stream()
.filter(e -> {
var sku = skuMap.get(e.getSkuId());
return sku != null && (sku.getCode().contains(keyword) || sku.getName().contains(keyword));
})
.collect(Collectors.toList());
}
final var skuSellQuantityVOS = responses.stream()
.map(e -> {
var sku = skuMap.get(e.getSkuId());
return SkuSellQuantityVO.builder()
.skuId(e.getSkuId())
.skuName(sku != null ? sku.getName() : "")
.skuCode(sku != null ? sku.getCode() : "")
.maxSellQuantity(e.getMaxSellQuantity())
.todaySellQuantity(e.getTodaySellQuantity())
.soldOut(e.getMaxSellQuantity() == e.getTodaySellQuantity())
.build();
})
.sorted(Comparator.comparing(SkuSellQuantityVO::getSkuCode))
.collect(Collectors.toList());
return PageUtil.subListPage(skuSellQuantityVOS, querySkuSellQuantityDTO.getPageNo(), querySkuSellQuantityDTO.getPageSize());
}
@Override
public boolean batchSetSkuSellQuantity(int stallId, SkuSellQuantityDTO.BatchSetSkuSellQuantityDTO batchSetSkuSellQuantityDTO) {
final var responses = orderServiceRpcClient.querySkuSellQuantitiesByStallAndSkuIds(LoginContextHolder.getEnterpriseId(), stallId, batchSetSkuSellQuantityDTO.getSkuIds());
final var skuMap = responses.stream().collect(Collectors.toMap(SingleSkuSellQuantityRpcResponse::getSkuId, Function.identity()));
final var skuSellQuantityBOs = batchSetSkuSellQuantityDTO.getSkuIds().stream().map(skuId -> SkuSellQuantityBO.builder()
.id(skuMap.get(skuId) == null ? null : skuMap.get(skuId).getId())
.skuId(skuId)
.maxSellQuantity(batchSetSkuSellQuantityDTO.getMaxSellQuantity())
.build()
).collect(Collectors.toList());
return orderServiceRpcClient.batchSaveSkuSellQuantities(LoginContextHolder.getEnterpriseId(), stallId, skuSellQuantityBOs);
}
@Override
public List<SkuSellQuantityVO> querySkuSellQuantityBySkuIds(SkuSellQuantityDTO.QuerySkuSellQuantityBySkuIdsDTO querySkuSellQuantityBySkuIdsDTO) {
final var stallId = querySkuSellQuantityBySkuIdsDTO.getStallId();
final var enterpriseId = LoginContextHolder.getEnterpriseId();
final var skuIds = menuService.queryMenuSkuIdsByStallId(enterpriseId, stallId);
var responses = orderServiceRpcClient.querySkuSellQuantitiesByStall(enterpriseId, stallId);
final var skuSellQuantityMap = responses.stream().collect(Collectors.toMap(SingleSkuSellQuantityRpcResponse::getSkuId, Function.identity()));
responses = skuIds.stream()
.map(skuId -> {
var response = skuSellQuantityMap.get(skuId);
if (response == null) {
response = SingleSkuSellQuantityRpcResponse.newBuilder()
.setSkuId(skuId)
.setMaxSellQuantity(0)
.setTodaySellQuantity(0)
.build();
}
return response;
})
.collect(Collectors.toList());
final var skuList = skuServiceRpcClient.getSkusByIds(responses.stream().map(SingleSkuSellQuantityRpcResponse::getSkuId).collect(Collectors.toList()));
final var skuMap = skuList.stream().collect(Collectors.toMap(SingleSkuResponse::getId, Function.identity()));
return responses.stream()
.map(e -> {
var sku = skuMap.get(e.getSkuId());
return SkuSellQuantityVO.builder()
.skuId(e.getSkuId())
.skuName(sku != null ? sku.getName() : "")
.skuCode(sku != null ? sku.getCode() : "")
.maxSellQuantity(e.getMaxSellQuantity())
.todaySellQuantity(e.getTodaySellQuantity())
.soldOut(e.getMaxSellQuantity() == e.getTodaySellQuantity())
.build();
})
.sorted(Comparator.comparing(SkuSellQuantityVO::getSkuCode))
.collect(Collectors.toList());
}
}
......
......@@ -33,6 +33,14 @@ service ClientCustomerOrderServiceRpc {
// 操作记录
rpc GetOrderOperationRecordsByOrderId (GetOrderOperationRecordsByOrderIdRequest) returns (GetOrderOperationRecordsByOrderIdResponse) {}
rpc BatchCreateOrderOperationRecords (BatchCreateOrderOperationRecordsRequest) returns (BatchCreateOrderOperationRecordsResponse) {}
// sku菜品库存
rpc QuerySkuSellQuantitiesByStall(QuerySkuSellQuantitiesByStallRpcRequest) returns (QuerySkuSellQuantitiesByStallRpcResponse) {}
rpc QuerySkuSellQuantitiesByStallAndSkuIds(QuerySkuSellQuantitiesByStallAndSkuIdsRpcRequest) returns (QuerySkuSellQuantitiesByStallAndSkuIdsRpcResponse) {}
rpc BatchSaveSkuSellQuantities(BatchSaveSkuSellQuantitiesRpcRequest) returns (BatchSaveSkuSellQuantitiesRpcResponse) {}
rpc AddSkusSellQuantities(AddSkusSellQuantitiesRpcRequest) returns (AddSkusSellQuantitiesRpcResponse) {}
}
enum OrderStatusEnum {
......@@ -608,3 +616,71 @@ message BatchCreateOrderOperationRecordsResponse {
bool isCreated = 1;
repeated int32 ids = 2;
}
message SingleSkuSellQuantityRpcResponse {
int32 id = 1;
int32 enterpriseId = 2;
int32 stallId = 3;
int32 skuId = 4;
int32 maxSellQuantity = 5;
int32 todaySellQuantity = 6;
int32 createdBy = 7;
int64 createdAt = 8;
int32 creationSource = 9;
int32 updatedBy = 10;
int64 updatedAt = 11;
int32 updateSource = 12;
bool isDeleted = 13;
}
message QuerySkuSellQuantitiesByStallRpcRequest {
int32 enterpriseId = 1;
int32 stallId = 2;
}
message QuerySkuSellQuantitiesByStallRpcResponse {
repeated SingleSkuSellQuantityRpcResponse responses = 1;
}
message QuerySkuSellQuantitiesByStallAndSkuIdsRpcRequest {
int32 enterpriseId = 1;
int32 stallId = 2;
repeated int32 skuIds = 3;
}
message QuerySkuSellQuantitiesByStallAndSkuIdsRpcResponse {
repeated SingleSkuSellQuantityRpcResponse responses = 1;
}
message BatchSaveSkuSellQuantitiesRpcRequest {
repeated SkuSellQuantityModification skuSellQuantityModifications = 1;
int32 enterpriseId = 2;
int32 updatedBy = 3;
int32 updateSource = 4;
}
message SkuSellQuantityModification {
int32 id = 1;
int32 stallId = 2;
int32 skuId = 3;
int32 maxSellQuantity = 4;
}
message BatchSaveSkuSellQuantitiesRpcResponse {
bool isSaved = 1;
}
message AddSkusSellQuantitiesRpcRequest {
int32 enterpriseId = 1;
int32 stallId = 2;
repeated SkuSellQuantity skuSellQuantities = 3;
}
message SkuSellQuantity {
int32 skuId = 1;
int32 quantity = 2;
}
message AddSkusSellQuantitiesRpcResponse {
bool isAdded = 1;
}
......