diff --git a/CHANGELOG.md b/CHANGELOG.md index 913b0a4..b57ac7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ Check our main [developer changelog](https://developer.paddle.com/?utm_source=dx - Added support for `checkouts` report type. See [related changelog](https://developer.paddle.com/changelog/2026/checkouts-report?utm_source=dx&utm_medium=paddle-python-sdk) - Added `CLP` and `PEN` currency code support. See [related changelog](https://developer.paddle.com/changelog/2026/clp-pen-currencies?utm_source=dx&utm_medium=paddle-python-sdk) - Added `rotatable` to api_key events. See [related changelog](https://developer.paddle.com/changelog/2026/aws-secrets-manager-rotation?utm_source=dx&utm_medium=paddle-python-sdk) +- Added `balance_movement_date` and `balance_movement_type` filters for payout reconciliation reports. See [related changelog](https://developer.paddle.com/changelog/2026/payout-reconciliation-report-filters?utm_source=dx&utm_medium=paddle-python-sdk) ## 1.14.1 - 2026-04-21 diff --git a/paddle_billing/Entities/Reports/BalanceMovementType.py b/paddle_billing/Entities/Reports/BalanceMovementType.py new file mode 100644 index 0000000..8e3f0d2 --- /dev/null +++ b/paddle_billing/Entities/Reports/BalanceMovementType.py @@ -0,0 +1,13 @@ +from paddle_billing.PaddleStrEnum import PaddleStrEnum, PaddleStrEnumMeta + + +class BalanceMovementType(PaddleStrEnum, metaclass=PaddleStrEnumMeta): + Rebate: "BalanceMovementType" = "rebate" + SwiftFee: "BalanceMovementType" = "swift_fee" + Sale: "BalanceMovementType" = "sale" + Refund: "BalanceMovementType" = "refund" + ChargebackWarning: "BalanceMovementType" = "chargeback_warning" + ChargebackWarningReverse: "BalanceMovementType" = "chargeback_warning_reverse" + Chargeback: "BalanceMovementType" = "chargeback" + ChargebackReverse: "BalanceMovementType" = "chargeback_reverse" + Credit: "BalanceMovementType" = "credit" diff --git a/paddle_billing/Entities/Reports/ReportFilterName.py b/paddle_billing/Entities/Reports/ReportFilterName.py index 2c2828d..f8383ce 100644 --- a/paddle_billing/Entities/Reports/ReportFilterName.py +++ b/paddle_billing/Entities/Reports/ReportFilterName.py @@ -3,6 +3,8 @@ class ReportFilterName(PaddleStrEnum, metaclass=PaddleStrEnumMeta): Action: "ReportFilterName" = "action" + BalanceMovementDate: "ReportFilterName" = "balance_movement_date" + BalanceMovementType: "ReportFilterName" = "balance_movement_type" CheckoutCreatedAt: "ReportFilterName" = "checkout_created_at" CollectionMode: "ReportFilterName" = "collection_mode" CurrencyCode: "ReportFilterName" = "currency_code" diff --git a/paddle_billing/Entities/Reports/__init__.py b/paddle_billing/Entities/Reports/__init__.py index fefd9dd..3f46884 100644 --- a/paddle_billing/Entities/Reports/__init__.py +++ b/paddle_billing/Entities/Reports/__init__.py @@ -1,4 +1,5 @@ from paddle_billing.Entities.Reports.AdjustmentsReportType import AdjustmentsReportType +from paddle_billing.Entities.Reports.BalanceMovementType import BalanceMovementType from paddle_billing.Entities.Reports.BalanceReportType import BalanceReportType from paddle_billing.Entities.Reports.CheckoutsReportType import CheckoutsReportType from paddle_billing.Entities.Reports.DiscountsReportType import DiscountsReportType diff --git a/paddle_billing/Notifications/Entities/Reports/ReportFilterName.py b/paddle_billing/Notifications/Entities/Reports/ReportFilterName.py index 2c2828d..f8383ce 100644 --- a/paddle_billing/Notifications/Entities/Reports/ReportFilterName.py +++ b/paddle_billing/Notifications/Entities/Reports/ReportFilterName.py @@ -3,6 +3,8 @@ class ReportFilterName(PaddleStrEnum, metaclass=PaddleStrEnumMeta): Action: "ReportFilterName" = "action" + BalanceMovementDate: "ReportFilterName" = "balance_movement_date" + BalanceMovementType: "ReportFilterName" = "balance_movement_type" CheckoutCreatedAt: "ReportFilterName" = "checkout_created_at" CollectionMode: "ReportFilterName" = "collection_mode" CurrencyCode: "ReportFilterName" = "currency_code" diff --git a/paddle_billing/Resources/Reports/Operations/CreatePayoutReconciliationReport.py b/paddle_billing/Resources/Reports/Operations/CreatePayoutReconciliationReport.py index 07d8e8e..4635283 100644 --- a/paddle_billing/Resources/Reports/Operations/CreatePayoutReconciliationReport.py +++ b/paddle_billing/Resources/Reports/Operations/CreatePayoutReconciliationReport.py @@ -3,6 +3,8 @@ from paddle_billing.Entities.Reports import PayoutReconciliationReportType from paddle_billing.Resources.Reports.Operations.Filters import ( + BalanceMovementDateFilter, + BalanceMovementTypeFilter, RemittanceReferenceFilter, TransactionUpdatedAtFilter, ) @@ -15,11 +17,22 @@ @dataclass class CreatePayoutReconciliationReport(CreateReport): type: PayoutReconciliationReportType - filters: list[RemittanceReferenceFilter | TransactionUpdatedAtFilter] = field(default_factory=list) + filters: list[ + BalanceMovementDateFilter | BalanceMovementTypeFilter | RemittanceReferenceFilter | TransactionUpdatedAtFilter + ] = field(default_factory=list) @staticmethod - def get_allowed_filters() -> tuple[RemittanceReferenceFilter | TransactionUpdatedAtFilter]: + def get_allowed_filters() -> ( + tuple[ + BalanceMovementDateFilter + | BalanceMovementTypeFilter + | RemittanceReferenceFilter + | TransactionUpdatedAtFilter + ] + ): return ( + BalanceMovementDateFilter, + BalanceMovementTypeFilter, RemittanceReferenceFilter, TransactionUpdatedAtFilter, ) diff --git a/paddle_billing/Resources/Reports/Operations/Filters/BalanceMovementDateFilter.py b/paddle_billing/Resources/Reports/Operations/Filters/BalanceMovementDateFilter.py new file mode 100644 index 0000000..80d2d9e --- /dev/null +++ b/paddle_billing/Resources/Reports/Operations/Filters/BalanceMovementDateFilter.py @@ -0,0 +1,34 @@ +from __future__ import annotations +from dataclasses import dataclass + +from paddle_billing.Entities.DateTime import DateTime + +from paddle_billing.Entities.Reports import ReportFilterOperator + +from paddle_billing.Resources.Reports.Operations.Filters.Filter import Filter + +from paddle_billing.Entities.Reports import ReportFilterName + + +@dataclass +class BalanceMovementDateFilter(Filter): + operator: ReportFilterOperator + value: DateTime + + @staticmethod + def get_name() -> ReportFilterName: + return ReportFilterName.BalanceMovementDate + + def get_operator(self) -> ReportFilterOperator | None: + return self.operator + + def get_value(self) -> str: + return self.value.format() + + @staticmethod + def gte(value: DateTime) -> BalanceMovementDateFilter: + return BalanceMovementDateFilter(value=value, operator=ReportFilterOperator.Gte) + + @staticmethod + def lt(value: DateTime) -> BalanceMovementDateFilter: + return BalanceMovementDateFilter(value=value, operator=ReportFilterOperator.Lt) diff --git a/paddle_billing/Resources/Reports/Operations/Filters/BalanceMovementTypeFilter.py b/paddle_billing/Resources/Reports/Operations/Filters/BalanceMovementTypeFilter.py new file mode 100644 index 0000000..df80c02 --- /dev/null +++ b/paddle_billing/Resources/Reports/Operations/Filters/BalanceMovementTypeFilter.py @@ -0,0 +1,22 @@ +from __future__ import annotations +from dataclasses import dataclass + +from paddle_billing.EnumStringify import enum_stringify + +from paddle_billing.Resources.Reports.Operations.Filters.Filter import Filter + +from paddle_billing.Entities.Reports import BalanceMovementType + +from paddle_billing.Entities.Reports import ReportFilterName + + +@dataclass +class BalanceMovementTypeFilter(Filter): + types: list[BalanceMovementType] + + @staticmethod + def get_name() -> ReportFilterName: + return ReportFilterName.BalanceMovementType + + def get_value(self) -> list[str]: + return list(map(enum_stringify, self.types)) diff --git a/paddle_billing/Resources/Reports/Operations/Filters/__init__.py b/paddle_billing/Resources/Reports/Operations/Filters/__init__.py index 6acb8a2..534e332 100644 --- a/paddle_billing/Resources/Reports/Operations/Filters/__init__.py +++ b/paddle_billing/Resources/Reports/Operations/Filters/__init__.py @@ -1,5 +1,7 @@ from paddle_billing.Resources.Reports.Operations.Filters.AdjustmentActionFilter import AdjustmentActionFilter from paddle_billing.Resources.Reports.Operations.Filters.AdjustmentStatusFilter import AdjustmentStatusFilter +from paddle_billing.Resources.Reports.Operations.Filters.BalanceMovementDateFilter import BalanceMovementDateFilter +from paddle_billing.Resources.Reports.Operations.Filters.BalanceMovementTypeFilter import BalanceMovementTypeFilter from paddle_billing.Resources.Reports.Operations.Filters.CheckoutCreatedAtFilter import CheckoutCreatedAtFilter from paddle_billing.Resources.Reports.Operations.Filters.CollectionModeFilter import CollectionModeFilter from paddle_billing.Resources.Reports.Operations.Filters.CurrencyCodeFilter import CurrencyCodeFilter diff --git a/tests/Functional/Resources/Reports/_fixtures/request/create_payout_reconciliation_balance_movement.json b/tests/Functional/Resources/Reports/_fixtures/request/create_payout_reconciliation_balance_movement.json new file mode 100644 index 0000000..fc12f60 --- /dev/null +++ b/tests/Functional/Resources/Reports/_fixtures/request/create_payout_reconciliation_balance_movement.json @@ -0,0 +1,24 @@ +{ + "type": "payout_reconciliation", + "filters": [ + { + "name": "balance_movement_type", + "operator": null, + "value": [ + "sale", + "chargeback", + "credit" + ] + }, + { + "name": "balance_movement_date", + "operator": "gte", + "value": "2023-12-30T00:00:00.000000Z" + }, + { + "name": "balance_movement_date", + "operator": "lt", + "value": "2024-12-30T12:30:01.123456Z" + } + ] +} diff --git a/tests/Functional/Resources/Reports/test_ReportsClient.py b/tests/Functional/Resources/Reports/test_ReportsClient.py index a73806d..1ff1c78 100644 --- a/tests/Functional/Resources/Reports/test_ReportsClient.py +++ b/tests/Functional/Resources/Reports/test_ReportsClient.py @@ -7,6 +7,7 @@ from paddle_billing.Entities.ReportCSV import ReportCSV from paddle_billing.Entities.Reports import ( AdjustmentsReportType, + BalanceMovementType, BalanceReportType, CheckoutsReportType, DiscountsReportType, @@ -24,6 +25,8 @@ from paddle_billing.Resources.Reports.Operations.Filters import ( AdjustmentActionFilter, AdjustmentStatusFilter, + BalanceMovementDateFilter, + BalanceMovementTypeFilter, CheckoutCreatedAtFilter, CollectionModeFilter, CurrencyCodeFilter, @@ -196,6 +199,24 @@ class TestReportsClient: ReadsFixtures.read_raw_json_fixture("request/create_checkouts_full"), CheckoutsReportType, ), + ( + CreatePayoutReconciliationReport( + type=PayoutReconciliationReportType.PayoutReconciliation, + filters=[ + BalanceMovementTypeFilter( + [ + BalanceMovementType.Sale, + BalanceMovementType.Chargeback, + BalanceMovementType.Credit, + ] + ), + BalanceMovementDateFilter.gte(DateTime("2023-12-30")), + BalanceMovementDateFilter.lt(DateTime("2024-12-30T12:30:01.123456Z")), + ], + ), + ReadsFixtures.read_raw_json_fixture("request/create_payout_reconciliation_balance_movement"), + PayoutReconciliationReportType, + ), ], ids=[ "Create transaction report with basic data", @@ -209,6 +230,7 @@ class TestReportsClient: "Create payout reconciliation report with filters", "Create checkouts report with basic data", "Create checkouts report with filters", + "Create payout reconciliation report with balance movement filters", ], ) def test_create_report_uses_expected_payload(