11import {
2+ AccountHolderDTO ,
23 BigNumberInput ,
34 CaptureDTO ,
45 Context ,
6+ CreateAccountHolderDTO ,
7+ CreateAccountHolderOutput ,
58 CreateCaptureDTO ,
69 CreatePaymentCollectionDTO ,
710 CreatePaymentMethodDTO ,
811 CreatePaymentSessionDTO ,
912 CreateRefundDTO ,
10- AccountHolderDTO ,
1113 DAL ,
1214 FilterablePaymentCollectionProps ,
1315 FilterablePaymentMethodProps ,
1416 FilterablePaymentProviderProps ,
1517 FindConfig ,
1618 InferEntityType ,
19+ InitiatePaymentOutput ,
1720 InternalModuleDeclaration ,
1821 IPaymentModuleService ,
1922 Logger ,
@@ -28,16 +31,13 @@ import {
2831 ProviderWebhookPayload ,
2932 RefundDTO ,
3033 RefundReasonDTO ,
34+ UpdateAccountHolderDTO ,
35+ UpdateAccountHolderOutput ,
3136 UpdatePaymentCollectionDTO ,
3237 UpdatePaymentDTO ,
3338 UpdatePaymentSessionDTO ,
34- CreateAccountHolderDTO ,
3539 UpsertPaymentCollectionDTO ,
3640 WebhookActionResult ,
37- CreateAccountHolderOutput ,
38- InitiatePaymentOutput ,
39- UpdateAccountHolderDTO ,
40- UpdateAccountHolderOutput ,
4141} from "@medusajs/framework/types"
4242import {
4343 BigNumber ,
@@ -152,6 +152,25 @@ export default class PaymentModuleService
152152 return joinerConfig
153153 }
154154
155+ protected roundToCurrencyPrecision (
156+ amount : BigNumberInput ,
157+ currencyCode : string
158+ ) : BigNumberInput {
159+ let precision : number | undefined = undefined
160+ try {
161+ const formatted = Intl . NumberFormat ( undefined , {
162+ style : "currency" ,
163+ currency : currencyCode ,
164+ } ) . format ( 0.1111111 )
165+
166+ precision = formatted . split ( "." ) [ 1 ] . length
167+ } catch {
168+ // Unknown currency, keep the full precision
169+ }
170+
171+ return MathBN . convert ( amount , precision )
172+ }
173+
155174 // @ts -expect-error
156175 createPaymentCollections (
157176 data : CreatePaymentCollectionDTO ,
@@ -627,6 +646,7 @@ export default class PaymentModuleService
627646 "payment_collection_id" ,
628647 "amount" ,
629648 "raw_amount" ,
649+ "currency_code" ,
630650 "captured_at" ,
631651 "canceled_at" ,
632652 ] ,
@@ -698,7 +718,12 @@ export default class PaymentModuleService
698718 const newCaptureAmount = new BigNumber ( data . amount )
699719 const remainingToCapture = MathBN . sub ( authorizedAmount , capturedAmount )
700720
701- if ( MathBN . gt ( newCaptureAmount , remainingToCapture ) ) {
721+ if (
722+ MathBN . gt (
723+ this . roundToCurrencyPrecision ( newCaptureAmount , payment . currency_code ) ,
724+ this . roundToCurrencyPrecision ( remainingToCapture , payment . currency_code )
725+ )
726+ ) {
702727 throw new MedusaError (
703728 MedusaError . Types . INVALID_DATA ,
704729 `You cannot capture more than the authorized amount substracted by what is already captured.`
@@ -709,7 +734,10 @@ export default class PaymentModuleService
709734 const totalCaptured = MathBN . convert (
710735 MathBN . add ( capturedAmount , newCaptureAmount )
711736 )
712- const isFullyCaptured = MathBN . gte ( totalCaptured , authorizedAmount )
737+ const isFullyCaptured = MathBN . gte (
738+ this . roundToCurrencyPrecision ( totalCaptured , payment . currency_code ) ,
739+ this . roundToCurrencyPrecision ( authorizedAmount , payment . currency_code )
740+ )
713741
714742 const capture = await this . captureService_ . create (
715743 {
@@ -892,7 +920,7 @@ export default class PaymentModuleService
892920 const paymentCollection = await this . paymentCollectionService_ . retrieve (
893921 paymentCollectionId ,
894922 {
895- select : [ "amount" , "raw_amount" , "status" ] ,
923+ select : [ "amount" , "raw_amount" , "status" , "currency_code" ] ,
896924 relations : [
897925 "payment_sessions.amount" ,
898926 "payment_sessions.raw_amount" ,
@@ -938,12 +966,32 @@ export default class PaymentModuleService
938966 : PaymentCollectionStatus . AWAITING
939967
940968 if ( MathBN . gt ( authorizedAmount , 0 ) ) {
941- status = MathBN . gte ( authorizedAmount , paymentCollection . amount )
969+ status = MathBN . gte (
970+ this . roundToCurrencyPrecision (
971+ authorizedAmount ,
972+ paymentCollection . currency_code
973+ ) ,
974+ this . roundToCurrencyPrecision (
975+ paymentCollection . amount ,
976+ paymentCollection . currency_code
977+ )
978+ )
942979 ? PaymentCollectionStatus . AUTHORIZED
943980 : PaymentCollectionStatus . PARTIALLY_AUTHORIZED
944981 }
945982
946- if ( MathBN . eq ( paymentCollection . amount , capturedAmount ) ) {
983+ if (
984+ MathBN . gte (
985+ this . roundToCurrencyPrecision (
986+ capturedAmount ,
987+ paymentCollection . currency_code
988+ ) ,
989+ this . roundToCurrencyPrecision (
990+ paymentCollection . amount ,
991+ paymentCollection . currency_code
992+ )
993+ )
994+ ) {
947995 status = PaymentCollectionStatus . COMPLETED
948996 completedAt = new Date ( )
949997 }
0 commit comments