diff --git a/packages/payment/src/models/capture.ts b/packages/payment/src/models/capture.ts new file mode 100644 index 0000000000..f1e2e7ba27 --- /dev/null +++ b/packages/payment/src/models/capture.ts @@ -0,0 +1,49 @@ +import { + BeforeCreate, + Entity, + ManyToOne, + OnInit, + PrimaryKey, + Property, +} from "@mikro-orm/core" + +import { generateEntityId } from "@medusajs/utils" +import Payment from "./payment" + +@Entity({ tableName: "capture" }) +export default class Capture { + @PrimaryKey({ columnType: "text" }) + id: string + + @Property({ + columnType: "numeric", + serializer: Number, + }) + amount: number + + @ManyToOne(() => Payment, { + onDelete: "cascade", + fieldName: "payment_id", + }) + payment: Payment + + @Property({ + onCreate: () => new Date(), + columnType: "timestamptz", + defaultRaw: "now()", + }) + created_at: Date + + @Property({ nullable: true }) + created_by: string | null + + @BeforeCreate() + onCreate() { + this.id = generateEntityId(this.id, "capture") + } + + @OnInit() + onInit() { + this.id = generateEntityId(this.id, "capture") + } +} diff --git a/packages/payment/src/models/index.ts b/packages/payment/src/models/index.ts index 6810edbc6f..6588a97b76 100644 --- a/packages/payment/src/models/index.ts +++ b/packages/payment/src/models/index.ts @@ -1 +1,7 @@ +export { default as Capture } from "./capture" export { default as Payment } from "./payment" +export { default as PaymentCollection } from "./payment-collection" +export { default as PaymentMethodToken } from "./payment-method-token" +export { default as PaymentProvider } from "./payment-provider" +export { default as PaymentSession } from "./payment-session" +export { default as Refund } from "./refund" diff --git a/packages/payment/src/models/payment-collection.ts b/packages/payment/src/models/payment-collection.ts new file mode 100644 index 0000000000..eed769a76f --- /dev/null +++ b/packages/payment/src/models/payment-collection.ts @@ -0,0 +1,135 @@ +import { + BeforeCreate, + Collection, + Entity, + Enum, + Filter, + ManyToMany, + OneToMany, + OnInit, + PrimaryKey, + Property, +} from "@mikro-orm/core" + +import { DALUtils, generateEntityId } from "@medusajs/utils" +import PaymentProvider from "./payment-provider" +import PaymentSession from "./payment-session" +import Payment from "./payment" + +/** + * @enum + * + * The payment collection's status. + */ +export enum PaymentCollectionStatus { + /** + * The payment collection isn't paid. + */ + NOT_PAID = "not_paid", + /** + * The payment collection is awaiting payment. + */ + AWAITING = "awaiting", + /** + * The payment collection is authorized. + */ + AUTHORIZED = "authorized", + /** + * Some of the payments in the payment collection are authorized. + */ + PARTIALLY_AUTHORIZED = "partially_authorized", + /** + * The payment collection is canceled. + */ + CANCELED = "canceled", +} + +@Entity({ tableName: "payment-collection" }) +@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions) +export default class PaymentCollection { + @PrimaryKey({ columnType: "text" }) + id: string + + @Property({ columnType: "text", nullable: true }) + currency_code: string | null + + @Property({ + columnType: "numeric", + serializer: Number, + }) + amount: number + + @Property({ + columnType: "numeric", + nullable: true, + serializer: Number, + }) + authorized_amount: number | null + + @Property({ + columnType: "numeric", + nullable: true, + serializer: Number, + }) + refunded_amount: number | null + + @Property({ columnType: "text", nullable: true }) + region_id?: string | null + + @Property({ + onCreate: () => new Date(), + columnType: "timestamptz", + defaultRaw: "now()", + }) + created_at: Date + + @Property({ + onCreate: () => new Date(), + onUpdate: () => new Date(), + columnType: "timestamptz", + defaultRaw: "now()", + }) + updated_at: Date + + @Property({ + columnType: "timestamptz", + nullable: true, + index: "IDX_payment_collection_deleted_at", + }) + deleted_at: Date | null + + @Property({ + columnType: "timestamptz", + nullable: true, + }) + completed_at: Date | null + + @Enum({ + items: () => PaymentCollectionStatus, + default: PaymentCollectionStatus.NOT_PAID, + }) + status: PaymentCollectionStatus = PaymentCollectionStatus.NOT_PAID + + @ManyToMany(() => PaymentProvider) + payment_providers = new Collection(this) + + @OneToMany(() => PaymentSession, (ps) => ps.payment_collection, { + orphanRemoval: true, + }) + payment_sessions = new Collection(this) + + @OneToMany(() => Payment, (payment) => payment.payment_collection, { + orphanRemoval: true, + }) + payments = new Collection(this) + + @BeforeCreate() + onCreate() { + this.id = generateEntityId(this.id, "paycol") + } + + @OnInit() + onInit() { + this.id = generateEntityId(this.id, "paycol") + } +} diff --git a/packages/payment/src/models/payment-method-token.ts b/packages/payment/src/models/payment-method-token.ts new file mode 100644 index 0000000000..1f7a1314a0 --- /dev/null +++ b/packages/payment/src/models/payment-method-token.ts @@ -0,0 +1,43 @@ +import { + BeforeCreate, + Entity, + OnInit, + PrimaryKey, + Property, +} from "@mikro-orm/core" + +import { generateEntityId } from "@medusajs/utils" + +@Entity({ tableName: "payment-method-token" }) +export default class PaymentMethodToken { + @PrimaryKey({ columnType: "text" }) + id: string + + @Property({ columnType: "jsonb", nullable: true }) + data?: Record | null + + @Property() + name: string + + @Property() + type_detail: string + + @Property() + description_detail: string + + @Property({ columnType: "jsonb", nullable: true }) + metadata?: Record | null + + @Property({ columnType: "text" }) + provider_id: string + + @BeforeCreate() + onCreate() { + this.id = generateEntityId(this.id, "pmt") + } + + @OnInit() + onInit() { + this.id = generateEntityId(this.id, "pmt") + } +} diff --git a/packages/payment/src/models/payment-provider.ts b/packages/payment/src/models/payment-provider.ts new file mode 100644 index 0000000000..db5f53ae99 --- /dev/null +++ b/packages/payment/src/models/payment-provider.ts @@ -0,0 +1,12 @@ +import { Entity, PrimaryKey, Property } from "@mikro-orm/core" + +@Entity({ tableName: "payment-provider" }) +export default class PaymentProvider { + @PrimaryKey({ columnType: "text" }) + id: string + + @Property({ + default: true, + }) + is_enabled: boolean = true +} diff --git a/packages/payment/src/models/payment-session.ts b/packages/payment/src/models/payment-session.ts new file mode 100644 index 0000000000..dcfdb317d5 --- /dev/null +++ b/packages/payment/src/models/payment-session.ts @@ -0,0 +1,98 @@ +import { + BeforeCreate, + Entity, + Enum, + ManyToOne, + OneToOne, + OnInit, + PrimaryKey, + Property, +} from "@mikro-orm/core" +import PaymentCollection from "./payment-collection" +import { generateEntityId } from "@medusajs/utils" +import Payment from "./payment" + +/** + * @enum + * + * The status of a payment session. + */ +export enum PaymentSessionStatus { + /** + * The payment is authorized. + */ + AUTHORIZED = "authorized", + /** + * The payment is pending. + */ + PENDING = "pending", + /** + * The payment requires an action. + */ + REQUIRES_MORE = "requires_more", + /** + * An error occurred while processing the payment. + */ + ERROR = "error", + /** + * The payment is canceled. + */ + CANCELED = "canceled", +} + +@Entity({ tableName: "payment-session" }) +export default class PaymentSession { + @PrimaryKey({ columnType: "text" }) + id: string + + @Property({ columnType: "text", nullable: true }) + currency_code: string | null + + @Property({ + columnType: "numeric", + serializer: Number, + }) + amount: number + + @Property({ columnType: "text" }) + provider_id: string + + @Property({ columnType: "jsonb", nullable: true }) + data?: Record | null + + @Enum({ + items: () => PaymentSessionStatus, + }) + status: PaymentSessionStatus + + @Property({ nullable: true }) + is_selected: boolean | null + + @Property({ + columnType: "timestamptz", + nullable: true, + }) + authorised_at: Date | null + + @ManyToOne({ + fieldName: "payment_collection_id", + }) + payment_collection!: PaymentCollection + + @OneToOne({ + entity: () => Payment, + mappedBy: (payment) => payment.session, + cascade: ["soft-remove"] as any, + }) + payment: Payment + + @BeforeCreate() + onCreate() { + this.id = generateEntityId(this.id, "ps") + } + + @OnInit() + onInit() { + this.id = generateEntityId(this.id, "ps") + } +} diff --git a/packages/payment/src/models/payment.ts b/packages/payment/src/models/payment.ts index f4fee2bd64..366a5a542c 100644 --- a/packages/payment/src/models/payment.ts +++ b/packages/payment/src/models/payment.ts @@ -1,18 +1,58 @@ import { BeforeCreate, + Collection, Entity, + Filter, + ManyToOne, + OneToMany, + OneToOne, OnInit, PrimaryKey, Property, } from "@mikro-orm/core" -import { generateEntityId } from "@medusajs/utils" +import { DALUtils, generateEntityId } from "@medusajs/utils" +import Refund from "./refund" +import Capture from "./capture" +import PaymentSession from "./payment-session" +import PaymentCollection from "./payment-collection" @Entity({ tableName: "payment" }) +@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions) export default class Payment { @PrimaryKey({ columnType: "text" }) id: string + @Property({ + columnType: "numeric", + serializer: Number, + }) + amount: number + + @Property({ + columnType: "numeric", + serializer: Number, + }) + authorized_amount: number + + @Property() + provider_id: string + + @Property({ nullable: true }) + currency_code: string | null + + @Property({ nullable: true }) + cart_id: string | null + + @Property({ nullable: true }) + order_id: string | null + + @Property({ nullable: true }) + customer_id: string | null + + @Property({ columnType: "jsonb", nullable: true }) + data?: Record | null + @Property({ onCreate: () => new Date(), columnType: "timestamptz", @@ -28,6 +68,50 @@ export default class Payment { }) updated_at: Date + @Property({ + columnType: "timestamptz", + nullable: true, + index: "IDX_payment_deleted_at", + }) + deleted_at: Date | null + + @Property({ + columnType: "timestamptz", + nullable: true, + }) + captured_at: Date | null + + @Property({ + columnType: "timestamptz", + nullable: true, + }) + canceled_at: Date | null + + @OneToMany(() => Refund, (refund) => refund.payment, { + orphanRemoval: true, + }) + refunds = new Collection(this) + + @OneToMany(() => Capture, (capture) => capture.payment, { + orphanRemoval: true, + }) + captures = new Collection(this) + + @ManyToOne({ + fieldName: "payment_collection_id", + }) + payment_collection!: PaymentCollection + + @OneToOne({ owner: true, fieldName: "session_id" }) + session: PaymentSession + + /** COMPUTED PROPERTIES START **/ + + // captured_amount: number // sum of the associated captures + // refunded_amount: number // sum of the associated refunds + + /** COMPUTED PROPERTIES END **/ + @BeforeCreate() onCreate() { this.id = generateEntityId(this.id, "pay") diff --git a/packages/payment/src/models/refund.ts b/packages/payment/src/models/refund.ts new file mode 100644 index 0000000000..a580f371c9 --- /dev/null +++ b/packages/payment/src/models/refund.ts @@ -0,0 +1,49 @@ +import { + BeforeCreate, + Entity, + ManyToOne, + OnInit, + PrimaryKey, + Property, +} from "@mikro-orm/core" + +import { generateEntityId } from "@medusajs/utils" +import Payment from "./payment" + +@Entity({ tableName: "refund" }) +export default class Refund { + @PrimaryKey({ columnType: "text" }) + id: string + + @Property({ + columnType: "numeric", + serializer: Number, + }) + amount: number + + @ManyToOne(() => Payment, { + onDelete: "cascade", + fieldName: "payment_id", + }) + payment: Payment + + @Property({ + onCreate: () => new Date(), + columnType: "timestamptz", + defaultRaw: "now()", + }) + created_at: Date + + @Property({ nullable: true }) + created_by: string | null + + @BeforeCreate() + onCreate() { + this.id = generateEntityId(this.id, "refund") + } + + @OnInit() + onInit() { + this.id = generateEntityId(this.id, "refund") + } +}