Initial commit: backend code

This commit is contained in:
Agent
2026-03-20 04:59:00 +00:00
commit e7c7f3b174
42 changed files with 2855 additions and 0 deletions

View File

@@ -0,0 +1,349 @@
package com.example.building.service.impl;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.building.dto.CreateOrderRequest;
import com.example.building.entity.*;
import com.example.building.mapper.*;
import com.example.building.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
/**
* 订单服务实现类
* 核心业务逻辑:
* 1. 订单原价(total_amount) = Σ(item.price × item.quantity)
* 2. 优惠金额(discount_amount) = total_amount × (100 - discount_rate) / 100
* 3. 实付金额(actual_amount) = total_amount - discount_amount
*/
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private OrderItemMapper orderItemMapper;
@Autowired
private ProductMapper productMapper;
@Autowired
private StockMapper stockMapper;
@Autowired
private StockFlowMapper stockFlowMapper;
@Autowired
private CustomerMapper customerMapper;
/**
* 创建订单
* 核心:价格计算、库存扣减、客户累计消费更新
*/
@Override
@Transactional
public Order createOrder(CreateOrderRequest request, String operatorId, String operatorName) {
// 1. 准备订单数据
Order order = new Order();
order.setOrderId(UUID.randomUUID().toString());
order.setOrderNo(generateOrderNo());
order.setOperatorId(operatorId);
order.setOperatorName(operatorName);
order.setDiscountRate(request.getDiscountRate() != null ? request.getDiscountRate() : new BigDecimal("100"));
order.setRemark(request.getRemark());
order.setPaymentMethod(request.getPaymentMethod());
order.setStatus(1); // 已完成
// 2. 查询客户信息(如果指定了客户)
if (request.getCustomerId() != null) {
Customer customer = customerMapper.selectById(request.getCustomerId());
if (customer != null) {
order.setCustomerId(customer.getCustomerId());
order.setCustomerName(customer.getName());
order.setCustomerPhone(customer.getPhone());
order.setCustomerWechat(customer.getWechatOpenid());
}
}
// 3. 计算订单金额
BigDecimal totalAmount = BigDecimal.ZERO; // 原价
List<OrderItem> orderItems = new ArrayList<>();
for (CreateOrderRequest.OrderItemDTO itemDTO : request.getItems()) {
// 查询商品信息
Product product = productMapper.selectById(itemDTO.getProductId());
if (product == null) {
throw new RuntimeException("商品不存在: " + itemDTO.getProductId());
}
// 使用用户指定价格或商品标价
BigDecimal price = itemDTO.getPrice() != null ? itemDTO.getPrice() : product.getPrice();
// 计算小计
BigDecimal subtotal = price.multiply(new BigDecimal(itemDTO.getQuantity()))
.setScale(2, RoundingMode.HALF_UP);
// 累加原价
totalAmount = totalAmount.add(subtotal);
// 构建订单明细
OrderItem item = new OrderItem();
item.setItemId(UUID.randomUUID().toString());
item.setOrderId(order.getOrderId());
item.setProductId(product.getProductId());
item.setProductName(product.getName());
item.setProductSpec(product.getSpec());
item.setUnit(product.getUnit());
item.setPrice(price);
item.setQuantity(itemDTO.getQuantity());
item.setSubtotal(subtotal);
orderItems.add(item);
// 4. 扣减库存
decreaseStock(product.getProductId(), itemDTO.getQuantity(), order.getOrderId(), operatorId);
}
// 设置订单原价
order.setTotalAmount(totalAmount);
// 5. 计算优惠金额和实付金额
BigDecimal discountRate = order.getDiscountRate();
BigDecimal discountAmount = totalAmount.multiply(new BigDecimal("100").subtract(discountRate))
.divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
BigDecimal actualAmount = totalAmount.subtract(discountAmount);
order.setDiscountAmount(discountAmount);
order.setActualAmount(actualAmount);
// 6. 保存订单
orderMapper.insert(order);
// 7. 保存订单明细
for (OrderItem item : orderItems) {
orderItemMapper.insert(item);
}
// 8. 更新客户累计消费金额
if (request.getCustomerId() != null) {
Customer customer = customerMapper.selectById(request.getCustomerId());
if (customer != null) {
BigDecimal newTotal = customer.getTotalAmount().add(actualAmount);
customer.setTotalAmount(newTotal);
customerMapper.updateById(customer);
}
}
return order;
}
/**
* 获取订单列表
*/
@Override
public Page<Order> getOrders(String customerId, Integer status, String startDate, String endDate, Integer page, Integer pageSize) {
Page<Order> pageParam = new Page<>(page, pageSize);
LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();
if (customerId != null) {
wrapper.eq(Order::getCustomerId, customerId);
}
if (status != null) {
wrapper.eq(Order::getStatus, status);
}
if (startDate != null) {
wrapper.ge(Order::getCreatedAt, startDate);
}
if (endDate != null) {
wrapper.le(Order::getCreatedAt, endDate);
}
wrapper.orderByDesc(Order::getCreatedAt);
return orderMapper.selectPage(pageParam, wrapper);
}
/**
* 获取订单详情(含明细)
*/
@Override
public Map<String, Object> getOrderDetail(String orderId) {
Order order = orderMapper.selectById(orderId);
if (order == null) {
throw new RuntimeException("订单不存在");
}
List<OrderItem> items = orderItemMapper.selectList(new LambdaQueryWrapper<OrderItem>()
.eq(OrderItem::getOrderId, orderId));
Map<String, Object> result = new HashMap<>();
result.put("order", order);
result.put("items", items);
return result;
}
/**
* 取消订单
*/
@Override
@Transactional
public void cancelOrder(String orderId, String operatorId) {
Order order = orderMapper.selectById(orderId);
if (order == null) {
throw new RuntimeException("订单不存在");
}
if (order.getStatus() != 1) {
throw new RuntimeException("订单状态不允许取消");
}
// 恢复库存
List<OrderItem> items = orderItemMapper.selectList(new LambdaQueryWrapper<OrderItem>()
.eq(OrderItem::getOrderId, orderId));
for (OrderItem item : items) {
increaseStock(item.getProductId(), item.getQuantity(), orderId, operatorId);
}
// 更新订单状态
order.setStatus(2); // 已取消
orderMapper.updateById(order);
}
/**
* 退款
*/
@Override
@Transactional
public void refundOrder(String orderId, String operatorId) {
Order order = orderMapper.selectById(orderId);
if (order == null) {
throw new RuntimeException("订单不存在");
}
if (order.getStatus() != 1) {
throw new RuntimeException("订单状态不允许退款");
}
// 恢复库存
List<OrderItem> items = orderItemMapper.selectList(new LambdaQueryWrapper<OrderItem>()
.eq(OrderItem::getOrderId, orderId));
for (OrderItem item : items) {
increaseStock(item.getProductId(), item.getQuantity(), orderId, operatorId);
}
// 更新订单状态
order.setStatus(4); // 已退款
orderMapper.updateById(order);
}
/**
* 订单统计
*/
@Override
public Map<String, Object> getStatistics(String startDate, String endDate) {
LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(Order::getStatus, 1);
if (startDate != null) {
wrapper.ge(Order::getCreatedAt, startDate);
}
if (endDate != null) {
wrapper.le(Order::getCreatedAt, endDate);
}
List<Order> orders = orderMapper.selectList(wrapper);
BigDecimal totalAmount = BigDecimal.ZERO; // 原价合计
BigDecimal actualAmount = BigDecimal.ZERO; // 实付合计
for (Order order : orders) {
totalAmount = totalAmount.add(order.getTotalAmount());
actualAmount = actualAmount.add(order.getActualAmount());
}
Map<String, Object> result = new HashMap<>();
result.put("orderCount", orders.size());
result.put("totalAmount", totalAmount);
result.put("actualAmount", actualAmount);
result.put("discountAmount", totalAmount.subtract(actualAmount));
return result;
}
/**
* 生成订单编号
* 规则: ORD + 年月日 + 6位序号
*/
private String generateOrderNo() {
String date = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
String key = "order:no:" + date;
// 这里简化处理实际应使用Redis自增
int seq = (int) (Math.random() * 1000000);
return "ORD" + date + String.format("%06d", seq);
}
/**
* 扣减库存
*/
private void decreaseStock(String productId, Integer quantity, String relatedId, String operatorId) {
Stock stock = stockMapper.selectOne(new LambdaQueryWrapper<Stock>()
.eq(Stock::getProductId, productId));
if (stock == null) {
throw new RuntimeException("库存记录不存在");
}
if (stock.getQuantity() < quantity) {
throw new RuntimeException("库存不足");
}
int beforeQty = stock.getQuantity();
stock.setQuantity(beforeQty - quantity);
stockMapper.updateById(stock);
// 记录库存流水
saveStockFlow(productId, 2, -quantity, beforeQty, beforeQty - quantity, relatedId, "sale", operatorId);
}
/**
* 增加库存
*/
private void increaseStock(String productId, Integer quantity, String relatedId, String operatorId) {
Stock stock = stockMapper.selectOne(new LambdaQueryWrapper<Stock>()
.eq(Stock::getProductId, productId));
if (stock == null) {
stock = new Stock();
stock.setStockId(UUID.randomUUID().toString());
stock.setProductId(productId);
stock.setQuantity(0);
stock.setLockedQuantity(0);
stockMapper.insert(stock);
}
int beforeQty = stock.getQuantity();
stock.setQuantity(beforeQty + quantity);
stockMapper.updateById(stock);
// 记录库存流水
saveStockFlow(productId, 1, quantity, beforeQty, beforeQty + quantity, relatedId, "cancel", operatorId);
}
/**
* 保存库存流水
*/
private void saveStockFlow(String productId, Integer type, Integer quantity,
Integer beforeQty, Integer afterQty, String relatedId,
String relatedType, String operatorId) {
StockFlow flow = new StockFlow();
flow.setFlowId(UUID.randomUUID().toString());
flow.setProductId(productId);
flow.setType(type);
flow.setQuantity(quantity);
flow.setBeforeQuantity(beforeQty);
flow.setAfterQuantity(afterQty);
flow.setRelatedId(relatedId);
flow.setRelatedType(relatedType);
flow.setOperatorId(operatorId);
stockFlowMapper.insert(flow);
}
}