order.service.ts 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. import { GenericCrudService } from '@/server/utils/generic-crud.service';
  2. import { DataSource, Repository } from 'typeorm';
  3. import { Order } from './order.entity';
  4. import { OrderGoods } from './order-goods.entity';
  5. import { Goods } from '@/server/modules/goods/goods.entity';
  6. import { DeliveryAddress } from '@/server/modules/delivery-address/delivery-address.entity';
  7. import type { CreateOrderRequest } from './dto/create-order-request.dto';
  8. export class OrderService extends GenericCrudService<Order> {
  9. private orderGoodsRepository: Repository<OrderGoods>;
  10. private goodsRepository: Repository<Goods>;
  11. private deliveryAddressRepository: Repository<DeliveryAddress>;
  12. constructor(dataSource: DataSource) {
  13. super(dataSource, Order);
  14. this.orderGoodsRepository = dataSource.getRepository(OrderGoods);
  15. this.goodsRepository = dataSource.getRepository(Goods);
  16. this.deliveryAddressRepository = dataSource.getRepository(DeliveryAddress);
  17. }
  18. /**
  19. * 创建订单
  20. * @param data 创建订单请求数据
  21. * @param userId 用户ID
  22. * @returns 创建的订单信息
  23. */
  24. async createOrder(data: CreateOrderRequest, userId: number): Promise<{
  25. orderId: number;
  26. orderNo: string;
  27. amount: number;
  28. payAmount: number;
  29. }> {
  30. const queryRunner = this.dataSource.createQueryRunner();
  31. await queryRunner.connect();
  32. await queryRunner.startTransaction();
  33. try {
  34. const { addressId, productOwn, consumeFrom, products } = data;
  35. // 验证商品信息并计算总价
  36. let totalAmount = 0;
  37. let totalCostAmount = 0;
  38. const goodsInfo = [];
  39. for (const item of products) {
  40. const goods = await this.goodsRepository.findOne({
  41. where: { id: item.id }
  42. });
  43. if (!goods) {
  44. throw new Error(`商品ID ${item.id} 不存在`);
  45. }
  46. if (goods.stock < item.num) {
  47. throw new Error(`商品 ${goods.name} 库存不足`);
  48. }
  49. const itemAmount = goods.price * item.num;
  50. const itemCostAmount = goods.costPrice * item.num;
  51. totalAmount += itemAmount;
  52. totalCostAmount += itemCostAmount;
  53. goodsInfo.push({
  54. goods,
  55. quantity: item.num,
  56. amount: itemAmount,
  57. costAmount: itemCostAmount
  58. });
  59. }
  60. // 获取收货地址信息
  61. let deliveryAddress = null;
  62. if (addressId) {
  63. deliveryAddress = await this.deliveryAddressRepository.findOne({
  64. where: { id: addressId, userId }
  65. });
  66. if (!deliveryAddress) {
  67. throw new Error('收货地址不存在');
  68. }
  69. }
  70. // 生成订单号
  71. const orderNo = this.generateOrderNo();
  72. // 创建订单
  73. const order = this.repository.create({
  74. orderNo,
  75. userId,
  76. amount: totalAmount,
  77. costAmount: totalCostAmount,
  78. payAmount: totalAmount, // 这里可以根据优惠规则计算实际支付金额
  79. orderType: 1, // 实物订单
  80. payType: consumeFrom === '积分兑换' ? 1 : 2, // 根据消费来源设置支付类型
  81. payState: 0, // 未支付
  82. state: 0, // 未发货
  83. addressId: addressId || 0,
  84. merchantId: goodsInfo[0]?.goods.merchantId || 0,
  85. supplierId: goodsInfo[0]?.goods.supplierId || 0,
  86. createdBy: userId,
  87. updatedBy: userId,
  88. // 设置收货地址信息(如果提供)
  89. ...(deliveryAddress && {
  90. receiverMobile: deliveryAddress.phone,
  91. recevierName: deliveryAddress.name,
  92. recevierProvince: deliveryAddress.provinceId,
  93. recevierCity: deliveryAddress.cityId,
  94. recevierDistrict: deliveryAddress.districtId,
  95. recevierTown: deliveryAddress.townId,
  96. address: deliveryAddress.address
  97. })
  98. });
  99. const savedOrder = await queryRunner.manager.save(order);
  100. // 创建订单商品明细
  101. const orderGoodsList = goodsInfo.map(info => ({
  102. orderId: savedOrder.id,
  103. orderNo,
  104. goodsId: info.goods.id,
  105. goodsName: info.goods.name,
  106. goodsImage: info.goods.image,
  107. goodsType: info.goods.goodsType,
  108. supplierId: info.goods.supplierId,
  109. costPrice: info.goods.costPrice,
  110. price: info.goods.price,
  111. num: info.quantity,
  112. freightAmount: 0,
  113. state: 0,
  114. createdBy: userId,
  115. updatedBy: userId
  116. }));
  117. await queryRunner.manager.save(OrderGoods, orderGoodsList);
  118. // 更新商品库存
  119. for (const item of goodsInfo) {
  120. await queryRunner.manager.update(Goods, item.goods.id, {
  121. stock: () => `stock - ${item.quantity}`,
  122. sales: () => `sales + ${item.quantity}`
  123. });
  124. }
  125. await queryRunner.commitTransaction();
  126. return {
  127. orderId: savedOrder.id,
  128. orderNo: savedOrder.orderNo,
  129. amount: savedOrder.amount,
  130. payAmount: savedOrder.payAmount
  131. };
  132. } catch (error) {
  133. await queryRunner.rollbackTransaction();
  134. throw error;
  135. } finally {
  136. await queryRunner.release();
  137. }
  138. }
  139. /**
  140. * 生成订单号
  141. * 格式:年月日时分秒 + 6位随机数
  142. */
  143. private generateOrderNo(): string {
  144. const now = new Date();
  145. const year = now.getFullYear();
  146. const month = String(now.getMonth() + 1).padStart(2, '0');
  147. const day = String(now.getDate()).padStart(2, '0');
  148. const hour = String(now.getHours()).padStart(2, '0');
  149. const minute = String(now.getMinutes()).padStart(2, '0');
  150. const second = String(now.getSeconds()).padStart(2, '0');
  151. const random = String(Math.floor(Math.random() * 1000000)).padStart(6, '0');
  152. return `ORD${year}${month}${day}${hour}${minute}${second}${random}`;
  153. }
  154. }