All files / marketing-platform/domain/entities PromotionOrder.ts

100% Statements 24/24
100% Branches 5/5
100% Functions 17/17
100% Lines 24/24

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132                                                165x   165x 165x 165x 165x 165x             165x 1x               2x             3x                   2x             2x             2x             2x             3x 3x             3x         1x       1x       1x       2x       1x       1x       1x      
import {
  OrderStatusType,
  PaymentType,
  PaymentInfo,
} from '../types';
 
/**
 * PromotionOrder entity
 * Represents the order and payment information for a promotion application
 */
export class PromotionOrder {
  private readonly orderStatus: OrderStatusType;
  private readonly paymentType: PaymentType;
  private readonly paymentDate: Date;
  private readonly finalPaymentPrice: number;
  private readonly paymentInfo: PaymentInfo;
 
  constructor(params: {
    orderStatus: OrderStatusType;
    paymentType: PaymentType;
    paymentDate: Date;
    finalPaymentPrice: number;
    paymentInfo: PaymentInfo;
  }) {
    this.validatePaymentPrice(params.finalPaymentPrice);
 
    this.orderStatus = params.orderStatus;
    this.paymentType = params.paymentType;
    this.paymentDate = params.paymentDate;
    this.finalPaymentPrice = params.finalPaymentPrice;
    this.paymentInfo = params.paymentInfo;
  }
 
  /**
   * Validates that payment price is non-negative
   */
  private validatePaymentPrice(price: number): void {
    if (price < 0) {
      throw new Error('Payment price cannot be negative');
    }
  }
 
  /**
   * Checks if the order payment is completed
   */
  public isPaymentCompleted(): boolean {
    return this.orderStatus === 'PAYMENT_COMPLETED';
  }
 
  /**
   * Checks if the order has been refunded (fully or partially)
   */
  public isRefunded(): boolean {
    return (
      this.orderStatus === 'REFUND_COMPLETED' ||
      this.orderStatus === 'PARTIAL_REFUND_COMPLETED'
    );
  }
 
  /**
   * Checks if the order has been partially refunded
   */
  public isPartiallyRefunded(): boolean {
    return this.orderStatus === 'PARTIAL_REFUND_COMPLETED';
  }
 
  /**
   * Checks if the order has been fully refunded
   */
  public isFullyRefunded(): boolean {
    return this.orderStatus === 'REFUND_COMPLETED';
  }
 
  /**
   * Checks if payment was made via LINE Pay
   */
  public isLinePay(): boolean {
    return this.paymentType === 'LINE_PAY';
  }
 
  /**
   * Checks if payment was made via Credit Card
   */
  public isCreditCard(): boolean {
    return this.paymentType === 'CREDIT_CARD';
  }
 
  /**
   * Gets the number of days since payment
   */
  public getDaysSincePayment(currentDate: Date = new Date()): number {
    const diffTime = currentDate.getTime() - this.paymentDate.getTime();
    return Math.floor(diffTime / (1000 * 60 * 60 * 24));
  }
 
  /**
   * Validates that the payment amount matches the order amount
   */
  public validatePaymentAmount(expectedAmount: number): boolean {
    return Math.abs(this.finalPaymentPrice - expectedAmount) < 0.01; // Allow for floating point precision
  }
 
  // Getters
  public getOrderStatus(): OrderStatusType {
    return this.orderStatus;
  }
 
  public getPaymentType(): PaymentType {
    return this.paymentType;
  }
 
  public getPaymentDate(): Date {
    return new Date(this.paymentDate);
  }
 
  public getFinalPaymentPrice(): number {
    return this.finalPaymentPrice;
  }
 
  public getPaymentInfo(): PaymentInfo {
    return { ...this.paymentInfo };
  }
 
  public getOrderId(): string {
    return this.paymentInfo.orderId;
  }
 
  public getTotalOrderAmount(): number {
    return this.paymentInfo.totalOrderAmount;
  }
}