order.entity.ts 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. import { Column, Entity, JoinTable, ManyToMany, ManyToOne, OneToMany } from 'typeorm';
  2. import { Adjustment, AdjustmentType, CurrencyCode, OrderAddress } from '../../../../shared/generated-types';
  3. import { DeepPartial, ID } from '../../../../shared/shared-types';
  4. import { Calculated } from '../../common/calculated-decorator';
  5. import { idType } from '../../config/config-helpers';
  6. import { OrderState } from '../../service/helpers/order-state-machine/order-state';
  7. import { VendureEntity } from '../base/base.entity';
  8. import { Customer } from '../customer/customer.entity';
  9. import { OrderItem } from '../order-item/order-item.entity';
  10. import { OrderLine } from '../order-line/order-line.entity';
  11. import { Payment } from '../payment/payment.entity';
  12. import { ShippingMethod } from '../shipping-method/shipping-method.entity';
  13. /**
  14. * @description
  15. * An Order is created whenever a {@link Customer} adds an item to the cart. It contains all the
  16. * information required to fulfill an order: which {@link ProductVariant}s in what quantities;
  17. * the shipping address and price; any applicable promotions; payments etc.
  18. *
  19. * An Order exists in a well-defined state according to the {@link OrderState} type. A state machine
  20. * is used to govern the transition from one state to another.
  21. *
  22. * @docsCategory entities
  23. */
  24. @Entity()
  25. export class Order extends VendureEntity {
  26. constructor(input?: DeepPartial<Order>) {
  27. super(input);
  28. }
  29. @Column() code: string;
  30. @Column('varchar') state: OrderState;
  31. @Column({ default: true })
  32. active: boolean;
  33. @Column({ nullable: true })
  34. orderPlacedAt?: Date;
  35. @ManyToOne(type => Customer)
  36. customer?: Customer;
  37. @OneToMany(type => OrderLine, line => line.order)
  38. lines: OrderLine[];
  39. @Column('simple-json') pendingAdjustments: Adjustment[];
  40. @Column('simple-json') shippingAddress: OrderAddress;
  41. @Column('simple-json') billingAddress: OrderAddress;
  42. @OneToMany(type => Payment, payment => payment.order)
  43. payments: Payment[];
  44. @Column('varchar')
  45. currencyCode: CurrencyCode;
  46. @Column() subTotalBeforeTax: number;
  47. @Column() subTotal: number;
  48. @Column({ type: idType(), nullable: true })
  49. shippingMethodId: ID | null;
  50. @ManyToOne(type => ShippingMethod)
  51. shippingMethod: ShippingMethod | null;
  52. @Column({ default: 0 })
  53. shipping: number;
  54. @Calculated()
  55. get totalBeforeTax(): number {
  56. return this.subTotalBeforeTax + this.promotionAdjustmentsTotal + (this.shipping || 0);
  57. }
  58. @Calculated()
  59. get total(): number {
  60. return this.subTotal + this.promotionAdjustmentsTotal + (this.shipping || 0);
  61. }
  62. @Calculated()
  63. get adjustments(): Adjustment[] {
  64. return this.pendingAdjustments;
  65. }
  66. get promotionAdjustmentsTotal(): number {
  67. return this.adjustments
  68. .filter(a => a.type === AdjustmentType.PROMOTION)
  69. .reduce((total, a) => total + a.amount, 0);
  70. }
  71. /**
  72. * Clears Adjustments from all OrderItems of the given type. If no type
  73. * is specified, then all adjustments are removed.
  74. */
  75. clearAdjustments(type?: AdjustmentType) {
  76. if (!type) {
  77. this.pendingAdjustments = [];
  78. } else {
  79. this.pendingAdjustments = this.pendingAdjustments.filter(a => a.type !== type);
  80. }
  81. this.lines.forEach(line => line.clearAdjustments(type));
  82. }
  83. getOrderItems(): OrderItem[] {
  84. return this.lines.reduce(
  85. (items, line) => {
  86. return [...items, ...line.items];
  87. },
  88. [] as OrderItem[],
  89. );
  90. }
  91. }