feat(payment): update payment collection status (#7335)
This commit is contained in:
@@ -1910,6 +1910,7 @@ medusaIntegrationTestRunner({
|
|||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
currency_code: "usd",
|
currency_code: "usd",
|
||||||
amount: 106,
|
amount: 106,
|
||||||
|
status: "authorized",
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -110,6 +110,11 @@ export interface FindConfig<Entity> {
|
|||||||
* Enable ORM specific defined filters
|
* Enable ORM specific defined filters
|
||||||
*/
|
*/
|
||||||
filters?: Record<string, any>
|
filters?: Record<string, any>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable ORM specific defined options
|
||||||
|
*/
|
||||||
|
options?: Record<string, any>
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -66,6 +66,10 @@ export function buildQuery<T = any, TDto = any>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (config.options) {
|
||||||
|
Object.assign(findOptions, config.options)
|
||||||
|
}
|
||||||
|
|
||||||
return { where, options: findOptions }
|
return { where, options: findOptions }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+206
-6
@@ -1,6 +1,6 @@
|
|||||||
import { Modules } from "@medusajs/modules-sdk"
|
import { Modules } from "@medusajs/modules-sdk"
|
||||||
import { IPaymentModuleService } from "@medusajs/types"
|
import { IPaymentModuleService } from "@medusajs/types"
|
||||||
|
import { promiseAll } from "@medusajs/utils"
|
||||||
import {
|
import {
|
||||||
moduleIntegrationTestRunner,
|
moduleIntegrationTestRunner,
|
||||||
SuiteOptions,
|
SuiteOptions,
|
||||||
@@ -66,9 +66,9 @@ moduleIntegrationTestRunner({
|
|||||||
id: expect.any(String),
|
id: expect.any(String),
|
||||||
currency_code: "usd",
|
currency_code: "usd",
|
||||||
amount: 200,
|
amount: 200,
|
||||||
// TODO
|
authorized_amount: 200,
|
||||||
// authorized_amount: 200,
|
captured_amount: 200,
|
||||||
// status: "authorized",
|
status: "authorized",
|
||||||
region_id: "reg_123",
|
region_id: "reg_123",
|
||||||
deleted_at: null,
|
deleted_at: null,
|
||||||
completed_at: expect.any(Date),
|
completed_at: expect.any(Date),
|
||||||
@@ -635,8 +635,6 @@ moduleIntegrationTestRunner({
|
|||||||
amount: 100,
|
amount: 100,
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
// captured_amount: 100,
|
|
||||||
// refunded_amount: 100,
|
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@@ -685,6 +683,208 @@ moduleIntegrationTestRunner({
|
|||||||
// )
|
// )
|
||||||
// })
|
// })
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe("concurrency", () => {
|
||||||
|
it("should authorize, capture and refund multiple payment sessions", async () => {
|
||||||
|
const collection = await service.createPaymentCollections({
|
||||||
|
amount: 500,
|
||||||
|
region_id: "test-region",
|
||||||
|
currency_code: "usd",
|
||||||
|
})
|
||||||
|
|
||||||
|
const session1 = await service.createPaymentSession(collection.id, {
|
||||||
|
provider_id: "pp_system_default",
|
||||||
|
amount: 120,
|
||||||
|
currency_code: "usd",
|
||||||
|
data: {},
|
||||||
|
})
|
||||||
|
|
||||||
|
const session2 = await service.createPaymentSession(collection.id, {
|
||||||
|
provider_id: "pp_system_default",
|
||||||
|
amount: 180,
|
||||||
|
currency_code: "usd",
|
||||||
|
data: {},
|
||||||
|
})
|
||||||
|
|
||||||
|
const session3 = await service.createPaymentSession(collection.id, {
|
||||||
|
provider_id: "pp_system_default",
|
||||||
|
amount: 200,
|
||||||
|
currency_code: "usd",
|
||||||
|
data: {},
|
||||||
|
})
|
||||||
|
|
||||||
|
const session4 = await service.createPaymentSession(collection.id, {
|
||||||
|
provider_id: "pp_system_default",
|
||||||
|
amount: 500,
|
||||||
|
currency_code: "eur",
|
||||||
|
data: {},
|
||||||
|
})
|
||||||
|
|
||||||
|
// authorize
|
||||||
|
const [payment1, payment2, payment3, payment4] = await promiseAll([
|
||||||
|
service.authorizePaymentSession(session1.id, {}),
|
||||||
|
service.authorizePaymentSession(session2.id, {}),
|
||||||
|
service.authorizePaymentSession(session3.id, {}),
|
||||||
|
service.authorizePaymentSession(session4.id, {}),
|
||||||
|
])
|
||||||
|
|
||||||
|
// capture
|
||||||
|
await promiseAll([
|
||||||
|
service.capturePayment({
|
||||||
|
amount: 60,
|
||||||
|
payment_id: payment1.id,
|
||||||
|
}),
|
||||||
|
service.capturePayment({
|
||||||
|
amount: 60,
|
||||||
|
payment_id: payment1.id,
|
||||||
|
}),
|
||||||
|
service.capturePayment({
|
||||||
|
amount: 180,
|
||||||
|
payment_id: payment2.id,
|
||||||
|
}),
|
||||||
|
service.capturePayment({
|
||||||
|
amount: 100,
|
||||||
|
payment_id: payment3.id,
|
||||||
|
}),
|
||||||
|
service.capturePayment({
|
||||||
|
amount: 40,
|
||||||
|
payment_id: payment3.id,
|
||||||
|
}),
|
||||||
|
service.capturePayment({
|
||||||
|
amount: 60,
|
||||||
|
payment_id: payment3.id,
|
||||||
|
}),
|
||||||
|
service.capturePayment({
|
||||||
|
amount: 200,
|
||||||
|
payment_id: payment4.id,
|
||||||
|
}),
|
||||||
|
service.capturePayment({
|
||||||
|
amount: 200,
|
||||||
|
payment_id: payment4.id,
|
||||||
|
}),
|
||||||
|
service.capturePayment({
|
||||||
|
amount: 100,
|
||||||
|
payment_id: payment4.id,
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
|
||||||
|
// refund
|
||||||
|
await promiseAll([
|
||||||
|
service.refundPayment({
|
||||||
|
amount: 70,
|
||||||
|
payment_id: payment1.id,
|
||||||
|
}),
|
||||||
|
service.refundPayment({
|
||||||
|
amount: 50,
|
||||||
|
payment_id: payment1.id,
|
||||||
|
}),
|
||||||
|
service.refundPayment({
|
||||||
|
amount: 180,
|
||||||
|
payment_id: payment2.id,
|
||||||
|
}),
|
||||||
|
service.refundPayment({
|
||||||
|
amount: 100,
|
||||||
|
payment_id: payment3.id,
|
||||||
|
}),
|
||||||
|
service.refundPayment({
|
||||||
|
amount: 40,
|
||||||
|
payment_id: payment3.id,
|
||||||
|
}),
|
||||||
|
service.refundPayment({
|
||||||
|
amount: 60,
|
||||||
|
payment_id: payment3.id,
|
||||||
|
}),
|
||||||
|
service.refundPayment({
|
||||||
|
amount: 400,
|
||||||
|
payment_id: payment4.id,
|
||||||
|
}),
|
||||||
|
service.refundPayment({
|
||||||
|
amount: 99,
|
||||||
|
payment_id: payment4.id,
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
|
||||||
|
expect(payment1).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
amount: 120,
|
||||||
|
currency_code: "usd",
|
||||||
|
provider_id: "pp_system_default",
|
||||||
|
payment_session: expect.objectContaining({
|
||||||
|
currency_code: "usd",
|
||||||
|
amount: 120,
|
||||||
|
raw_amount: { value: "120", precision: 20 },
|
||||||
|
provider_id: "pp_system_default",
|
||||||
|
status: "authorized",
|
||||||
|
authorized_at: expect.any(Date),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(payment2).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
amount: 180,
|
||||||
|
currency_code: "usd",
|
||||||
|
provider_id: "pp_system_default",
|
||||||
|
payment_session: expect.objectContaining({
|
||||||
|
currency_code: "usd",
|
||||||
|
amount: 180,
|
||||||
|
raw_amount: { value: "180", precision: 20 },
|
||||||
|
provider_id: "pp_system_default",
|
||||||
|
status: "authorized",
|
||||||
|
authorized_at: expect.any(Date),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(payment3).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
amount: 200,
|
||||||
|
currency_code: "usd",
|
||||||
|
provider_id: "pp_system_default",
|
||||||
|
payment_session: expect.objectContaining({
|
||||||
|
currency_code: "usd",
|
||||||
|
amount: 200,
|
||||||
|
raw_amount: { value: "200", precision: 20 },
|
||||||
|
provider_id: "pp_system_default",
|
||||||
|
status: "authorized",
|
||||||
|
authorized_at: expect.any(Date),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(payment4).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
amount: 500,
|
||||||
|
currency_code: "eur",
|
||||||
|
provider_id: "pp_system_default",
|
||||||
|
payment_session: expect.objectContaining({
|
||||||
|
currency_code: "eur",
|
||||||
|
amount: 500,
|
||||||
|
raw_amount: { value: "500", precision: 20 },
|
||||||
|
provider_id: "pp_system_default",
|
||||||
|
status: "authorized",
|
||||||
|
authorized_at: expect.any(Date),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
const finalCollection = (
|
||||||
|
await service.listPaymentCollections({
|
||||||
|
id: collection.id,
|
||||||
|
})
|
||||||
|
)[0]
|
||||||
|
|
||||||
|
expect(finalCollection).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
status: "authorized",
|
||||||
|
amount: 500,
|
||||||
|
authorized_amount: 1000,
|
||||||
|
captured_amount: 1000,
|
||||||
|
refunded_amount: 999,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -18,6 +18,16 @@ export class Migration20240225134525 extends Migration {
|
|||||||
ALTER TABLE IF EXISTS "payment_collection" ADD COLUMN IF NOT EXISTS "completed_at" TIMESTAMPTZ NULL;
|
ALTER TABLE IF EXISTS "payment_collection" ADD COLUMN IF NOT EXISTS "completed_at" TIMESTAMPTZ NULL;
|
||||||
ALTER TABLE IF EXISTS "payment_collection" ADD COLUMN IF NOT EXISTS "raw_amount" JSONB NOT NULL;
|
ALTER TABLE IF EXISTS "payment_collection" ADD COLUMN IF NOT EXISTS "raw_amount" JSONB NOT NULL;
|
||||||
ALTER TABLE IF EXISTS "payment_collection" ADD COLUMN IF NOT EXISTS "deleted_at" TIMESTAMPTZ NULL;
|
ALTER TABLE IF EXISTS "payment_collection" ADD COLUMN IF NOT EXISTS "deleted_at" TIMESTAMPTZ NULL;
|
||||||
|
|
||||||
|
ALTER TABLE IF EXISTS "payment_collection" ADD COLUMN IF NOT EXISTS "authorized_amount" NUMERIC NULL;
|
||||||
|
ALTER TABLE IF EXISTS "payment_collection" ADD COLUMN IF NOT EXISTS "raw_authorized_amount" JSONB NULL;
|
||||||
|
|
||||||
|
ALTER TABLE IF EXISTS "payment_collection" ADD COLUMN IF NOT EXISTS "captured_amount" NUMERIC NULL;
|
||||||
|
ALTER TABLE IF EXISTS "payment_collection" ADD COLUMN IF NOT EXISTS "raw_captured_amount" JSONB NULL;
|
||||||
|
|
||||||
|
ALTER TABLE IF EXISTS "payment_collection" ADD COLUMN IF NOT EXISTS "refunded_amount" NUMERIC NULL;
|
||||||
|
ALTER TABLE IF EXISTS "payment_collection" ADD COLUMN IF NOT EXISTS "raw_refunded_amount" JSONB NULL;
|
||||||
|
|
||||||
ALTER TABLE "payment_collection" DROP CONSTRAINT "FK_payment_collection_region_id";
|
ALTER TABLE "payment_collection" DROP CONSTRAINT "FK_payment_collection_region_id";
|
||||||
|
|
||||||
ALTER TABLE IF EXISTS "payment_provider" ADD COLUMN IF NOT EXISTS "is_enabled" BOOLEAN NOT NULL DEFAULT TRUE;
|
ALTER TABLE IF EXISTS "payment_provider" ADD COLUMN IF NOT EXISTS "is_enabled" BOOLEAN NOT NULL DEFAULT TRUE;
|
||||||
@@ -119,6 +129,12 @@ export class Migration20240225134525 extends Migration {
|
|||||||
"currency_code" TEXT NOT NULL,
|
"currency_code" TEXT NOT NULL,
|
||||||
"amount" NUMERIC NOT NULL,
|
"amount" NUMERIC NOT NULL,
|
||||||
"raw_amount" JSONB NOT NULL,
|
"raw_amount" JSONB NOT NULL,
|
||||||
|
"authorized_amount" NUMERIC NULL,
|
||||||
|
"raw_authorized_amount" JSONB NULL,
|
||||||
|
"captured_amount" NUMERIC NULL,
|
||||||
|
"raw_captured_amount" JSONB NULL,
|
||||||
|
"refunded_amount" NUMERIC NULL,
|
||||||
|
"raw_refunded_amount" JSONB NULL,
|
||||||
"region_id" TEXT NOT NULL,
|
"region_id" TEXT NOT NULL,
|
||||||
"created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
"created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
|
|||||||
@@ -43,6 +43,24 @@ export default class PaymentCollection {
|
|||||||
@Property({ columnType: "jsonb" })
|
@Property({ columnType: "jsonb" })
|
||||||
raw_amount: BigNumberRawValue
|
raw_amount: BigNumberRawValue
|
||||||
|
|
||||||
|
@MikroOrmBigNumberProperty({ nullable: true })
|
||||||
|
authorized_amount: BigNumber | number | null = null
|
||||||
|
|
||||||
|
@Property({ columnType: "jsonb", nullable: true })
|
||||||
|
raw_authorized_amount: BigNumberRawValue | null = null
|
||||||
|
|
||||||
|
@MikroOrmBigNumberProperty({ nullable: true })
|
||||||
|
captured_amount: BigNumber | number | null = null
|
||||||
|
|
||||||
|
@Property({ columnType: "jsonb", nullable: true })
|
||||||
|
raw_captured_amount: BigNumberRawValue | null = null
|
||||||
|
|
||||||
|
@MikroOrmBigNumberProperty({ nullable: true })
|
||||||
|
refunded_amount: BigNumber | number | null = null
|
||||||
|
|
||||||
|
@Property({ columnType: "jsonb", nullable: true })
|
||||||
|
raw_refunded_amount: BigNumberRawValue | null = null
|
||||||
|
|
||||||
@Property({ columnType: "text", index: "IDX_payment_collection_region_id" })
|
@Property({ columnType: "text", index: "IDX_payment_collection_region_id" })
|
||||||
region_id: string
|
region_id: string
|
||||||
|
|
||||||
|
|||||||
@@ -131,13 +131,6 @@ export default class Payment {
|
|||||||
})
|
})
|
||||||
payment_session: PaymentSession
|
payment_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()
|
@BeforeCreate()
|
||||||
onCreate() {
|
onCreate() {
|
||||||
this.id = generateEntityId(this.id, "pay")
|
this.id = generateEntityId(this.id, "pay")
|
||||||
|
|||||||
@@ -36,8 +36,10 @@ import {
|
|||||||
MedusaError,
|
MedusaError,
|
||||||
ModulesSdkUtils,
|
ModulesSdkUtils,
|
||||||
PaymentActions,
|
PaymentActions,
|
||||||
|
PaymentCollectionStatus,
|
||||||
promiseAll,
|
promiseAll,
|
||||||
} from "@medusajs/utils"
|
} from "@medusajs/utils"
|
||||||
|
import { IsolationLevel } from "@mikro-orm/core"
|
||||||
import {
|
import {
|
||||||
Capture,
|
Capture,
|
||||||
Payment,
|
Payment,
|
||||||
@@ -404,6 +406,9 @@ export default class PaymentModuleService<
|
|||||||
context: Record<string, unknown>,
|
context: Record<string, unknown>,
|
||||||
@MedusaContext() sharedContext?: Context
|
@MedusaContext() sharedContext?: Context
|
||||||
): Promise<PaymentDTO> {
|
): Promise<PaymentDTO> {
|
||||||
|
sharedContext ??= {}
|
||||||
|
sharedContext.isolationLevel = IsolationLevel.SERIALIZABLE
|
||||||
|
|
||||||
const session = await this.paymentSessionService_.retrieve(
|
const session = await this.paymentSessionService_.retrieve(
|
||||||
id,
|
id,
|
||||||
{
|
{
|
||||||
@@ -456,7 +461,10 @@ export default class PaymentModuleService<
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: update status on payment collection if authorized_amount === amount - depends on the BigNumber PR
|
await this.maybeUpdatePaymentCollection_(
|
||||||
|
session.payment_collection_id,
|
||||||
|
sharedContext
|
||||||
|
)
|
||||||
|
|
||||||
const payment = await this.paymentService_.create(
|
const payment = await this.paymentService_.create(
|
||||||
{
|
{
|
||||||
@@ -491,11 +499,30 @@ export default class PaymentModuleService<
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager("baseRepository_")
|
@InjectManager("baseRepository_")
|
||||||
async capturePayment(
|
async capturePayment(
|
||||||
data: CreateCaptureDTO,
|
data: CreateCaptureDTO,
|
||||||
@MedusaContext() sharedContext: Context = {}
|
@MedusaContext() sharedContext: Context = {}
|
||||||
): Promise<PaymentDTO> {
|
): Promise<PaymentDTO> {
|
||||||
|
const payment = (await this.capturePayment_(data, sharedContext)) as Payment
|
||||||
|
|
||||||
|
await this.maybeUpdatePaymentCollection_(
|
||||||
|
payment.payment_collection_id,
|
||||||
|
sharedContext
|
||||||
|
)
|
||||||
|
|
||||||
|
return await this.retrievePayment(
|
||||||
|
payment.id,
|
||||||
|
{ relations: ["captures"] },
|
||||||
|
sharedContext
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager("baseRepository_")
|
||||||
|
private async capturePayment_(
|
||||||
|
data: CreateCaptureDTO,
|
||||||
|
@MedusaContext() sharedContext: Context = {}
|
||||||
|
) {
|
||||||
const payment = await this.paymentService_.retrieve(
|
const payment = await this.paymentService_.retrieve(
|
||||||
data.payment_id,
|
data.payment_id,
|
||||||
{
|
{
|
||||||
@@ -503,6 +530,7 @@ export default class PaymentModuleService<
|
|||||||
"id",
|
"id",
|
||||||
"data",
|
"data",
|
||||||
"provider_id",
|
"provider_id",
|
||||||
|
"payment_collection_id",
|
||||||
"amount",
|
"amount",
|
||||||
"raw_amount",
|
"raw_amount",
|
||||||
"canceled_at",
|
"canceled_at",
|
||||||
@@ -561,38 +589,58 @@ export default class PaymentModuleService<
|
|||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
await this.paymentService_.update(
|
|
||||||
{ id: payment.id, data: paymentData },
|
|
||||||
sharedContext
|
|
||||||
)
|
|
||||||
|
|
||||||
// When the entire authorized amount has been captured, we mark it fully capture by setting the captured_at field
|
// When the entire authorized amount has been captured, we mark it fully capture by setting the captured_at field
|
||||||
|
let capturedAt: Date | null = null
|
||||||
const totalCaptured = MathBN.convert(
|
const totalCaptured = MathBN.convert(
|
||||||
MathBN.add(capturedAmount, newCaptureAmount)
|
MathBN.add(capturedAmount, newCaptureAmount)
|
||||||
)
|
)
|
||||||
if (MathBN.gte(totalCaptured, authorizedAmount)) {
|
if (MathBN.gte(totalCaptured, authorizedAmount)) {
|
||||||
await this.paymentService_.update(
|
capturedAt = new Date()
|
||||||
{ id: payment.id, captured_at: new Date() },
|
|
||||||
sharedContext
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await this.paymentService_.update(
|
||||||
|
{ id: payment.id, data: paymentData, captured_at: capturedAt },
|
||||||
|
sharedContext
|
||||||
|
)
|
||||||
|
|
||||||
|
return payment
|
||||||
|
}
|
||||||
|
|
||||||
|
@InjectManager("baseRepository_")
|
||||||
|
async refundPayment(
|
||||||
|
data: CreateRefundDTO,
|
||||||
|
@MedusaContext() sharedContext?: Context
|
||||||
|
): Promise<PaymentDTO> {
|
||||||
|
const payment = await this.refundPayment_(data, sharedContext)
|
||||||
|
|
||||||
|
await this.maybeUpdatePaymentCollection_(
|
||||||
|
payment.payment_collection_id,
|
||||||
|
sharedContext
|
||||||
|
)
|
||||||
|
|
||||||
return await this.retrievePayment(
|
return await this.retrievePayment(
|
||||||
payment.id,
|
payment.id,
|
||||||
{ relations: ["captures"] },
|
{ relations: ["refunds"] },
|
||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager("baseRepository_")
|
@InjectTransactionManager("baseRepository_")
|
||||||
async refundPayment(
|
private async refundPayment_(
|
||||||
data: CreateRefundDTO,
|
data: CreateRefundDTO,
|
||||||
@MedusaContext() sharedContext?: Context
|
@MedusaContext() sharedContext?: Context
|
||||||
): Promise<PaymentDTO> {
|
) {
|
||||||
const payment = await this.paymentService_.retrieve(
|
const payment = await this.paymentService_.retrieve(
|
||||||
data.payment_id,
|
data.payment_id,
|
||||||
{
|
{
|
||||||
select: ["id", "data", "provider_id", "amount", "raw_amount"],
|
select: [
|
||||||
|
"id",
|
||||||
|
"data",
|
||||||
|
"provider_id",
|
||||||
|
"payment_collection_id",
|
||||||
|
"amount",
|
||||||
|
"raw_amount",
|
||||||
|
],
|
||||||
relations: ["captures.raw_amount"],
|
relations: ["captures.raw_amount"],
|
||||||
},
|
},
|
||||||
sharedContext
|
sharedContext
|
||||||
@@ -637,11 +685,7 @@ export default class PaymentModuleService<
|
|||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
return await this.retrievePayment(
|
return payment
|
||||||
payment.id,
|
|
||||||
{ relations: ["refunds"] },
|
|
||||||
sharedContext
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager("baseRepository_")
|
@InjectTransactionManager("baseRepository_")
|
||||||
@@ -756,4 +800,74 @@ export default class PaymentModuleService<
|
|||||||
count,
|
count,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager("baseRepository_")
|
||||||
|
private async maybeUpdatePaymentCollection_(
|
||||||
|
paymentCollectionId: string,
|
||||||
|
sharedContext?: Context
|
||||||
|
) {
|
||||||
|
const paymentCollection = await this.paymentCollectionService_.retrieve(
|
||||||
|
paymentCollectionId,
|
||||||
|
{
|
||||||
|
select: ["amount", "raw_amount", "status"],
|
||||||
|
relations: [
|
||||||
|
"payment_sessions.amount",
|
||||||
|
"payment_sessions.raw_amount",
|
||||||
|
"payments.captures.amount",
|
||||||
|
"payments.captures.raw_amount",
|
||||||
|
"payments.refunds.amount",
|
||||||
|
"payments.refunds.raw_amount",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
sharedContext
|
||||||
|
)
|
||||||
|
|
||||||
|
const paymentSessions = paymentCollection.payment_sessions
|
||||||
|
const captures = paymentCollection.payments
|
||||||
|
.map((pay) => [...pay.captures])
|
||||||
|
.flat()
|
||||||
|
const refunds = paymentCollection.payments
|
||||||
|
.map((pay) => [...pay.refunds])
|
||||||
|
.flat()
|
||||||
|
|
||||||
|
let authorizedAmount = MathBN.convert(0)
|
||||||
|
let capturedAmount = MathBN.convert(0)
|
||||||
|
let refundedAmount = MathBN.convert(0)
|
||||||
|
|
||||||
|
for (const ps of paymentSessions) {
|
||||||
|
if (ps.status === PaymentSessionStatus.AUTHORIZED) {
|
||||||
|
authorizedAmount = MathBN.add(authorizedAmount, ps.amount)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const capture of captures) {
|
||||||
|
capturedAmount = MathBN.add(capturedAmount, capture.amount)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const refund of refunds) {
|
||||||
|
refundedAmount = MathBN.add(refundedAmount, refund.amount)
|
||||||
|
}
|
||||||
|
|
||||||
|
let status =
|
||||||
|
paymentSessions.length === 0
|
||||||
|
? PaymentCollectionStatus.NOT_PAID
|
||||||
|
: PaymentCollectionStatus.AWAITING
|
||||||
|
|
||||||
|
if (MathBN.gt(authorizedAmount, 0)) {
|
||||||
|
status = MathBN.gte(authorizedAmount, paymentCollection.amount)
|
||||||
|
? PaymentCollectionStatus.AUTHORIZED
|
||||||
|
: PaymentCollectionStatus.PARTIALLY_AUTHORIZED
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.paymentCollectionService_.update(
|
||||||
|
{
|
||||||
|
id: paymentCollectionId,
|
||||||
|
status,
|
||||||
|
authorized_amount: authorizedAmount,
|
||||||
|
captured_amount: capturedAmount,
|
||||||
|
refunded_amount: refundedAmount,
|
||||||
|
},
|
||||||
|
sharedContext
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user