-
Notifications
You must be signed in to change notification settings - Fork 0
FOSFASPRT-78: Add native overpayment support #260
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
41a95fa to
02266aa
Compare
|
@codex review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codex Review
Here are some automated review suggestions for this pull request.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
02266aa to
05d9420
Compare
Add ability to allocate overpayments from contributions to credit notes. Features: - New CreditNote.allocateOverpayment API action - Company setting for overpayment financial type - Admin setting to enable/disable overpayments feature - "Allocate overpayment" link on overpaid contributions - Creates credit note with overpayment amount as line item - Records negative payment on contribution to balance it Database changes: - Added overpayment_financial_type_id column to Company table - New upgrade_1006.sql migration
05d9420 to
8f5699b
Compare
|
@codex review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codex Review
Here are some automated review suggestions for this pull request.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
tests/phpunit/Civi/Api4/Action/CreditNote/AllocateOverpaymentActionTest.php
Show resolved
Hide resolved
|
@codex review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds native support for handling contribution overpayments by allowing users to allocate overpayments to new credit notes. When a contribution is overpaid (in "Pending refund" status), users can now convert the excess payment into a credit note for future invoice allocation.
Key Changes:
- New "Enable Overpayments" setting in CiviContribute configuration
- New "Overpayment Financial Type" field on Company entity for configuring which financial type to use
- New
CreditNote::allocateOverpayment()API action to convert overpayments to credit notes
Reviewed changes
Copilot reviewed 20 out of 20 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| xml/schema/CRM/Financeextras/Company.xml | Adds overpayment_financial_type_id field to Company schema |
| xml/Menu/financeextras.xml | Registers new overpayment allocation form route |
| tests/phpunit/Civi/Api4/Action/CreditNote/AllocateOverpaymentActionTest.php | Comprehensive test coverage for overpayment allocation |
| templates/CRM/Financeextras/Page/Company.tpl | Adds overpayment financial type column to company listing |
| templates/CRM/Financeextras/OverpaymentFinancialType.hlp | Help text for configuring overpayment financial types |
| templates/CRM/Financeextras/Form/Contribute/OverpaymentAllocate.tpl | Confirmation dialog template for allocating overpayments |
| templates/CRM/Financeextras/Form/Company/Add.tpl | Adds overpayment financial type field to company form |
| sql/upgrade_1006.sql | Migration to add overpayment_financial_type_id column |
| sql/auto_install.sql | Updates auto-install schema with new field and constraint |
| settings/financeextras.setting.php | Defines the enable overpayments setting |
| Civi/Financeextras/Utils/OverpaymentUtils.php | Utility functions for overpayment detection and eligibility |
| Civi/Financeextras/Hook/Links/Contribution/Overpayment.php | Adds overpayment allocation link to contribution actions |
| Civi/Financeextras/Hook/Links/Contribution.php | Integrates overpayment link handler |
| Civi/Api4/CreditNote.php | Registers allocateOverpayment API action |
| Civi/Api4/Action/CreditNote/AllocateOverpaymentAction.php | Core implementation of overpayment allocation logic |
| CRM/Financeextras/Upgrader.php | Adds upgrade_1006 method for database migration |
| CRM/Financeextras/Page/Company.php | Updates company listing query to include overpayment financial type |
| CRM/Financeextras/Form/Contribute/OverpaymentAllocate.php | Form controller for overpayment allocation |
| CRM/Financeextras/Form/Company/Add.php | Adds overpayment financial type field handling |
| CRM/Financeextras/DAO/Company.php | Generated DAO updates for new overpayment_financial_type_id field |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| $getQuery = 'SELECT fc.*, cc.display_name as company_name, mt.msg_title as invoice_template_name, mt2.msg_title as creditnote_template_name, ov.label AS receivable_payment_method, ft.name AS overpayment_financial_type_name FROM financeextras_company fc | ||
| LEFT JOIN civicrm_contact cc on cc.id = fc.contact_id | ||
| LEFT JOIN civicrm_msg_template mt ON mt.id = fc.invoice_template_id | ||
| LEFT JOIN civicrm_msg_template mt2 ON mt2.id = fc.creditnote_template_id | ||
| LEFT JOIN civicrm_option_value ov ON ov.value = fc.receivable_payment_method AND ov.option_group_id = ' . $optionGroupId . ' ORDER BY fc.id DESC | ||
| LEFT JOIN civicrm_option_value ov ON ov.value = fc.receivable_payment_method AND ov.option_group_id = ' . $optionGroupId . ' | ||
| LEFT JOIN civicrm_financial_type ft ON ft.id = fc.overpayment_financial_type_id | ||
| ORDER BY fc.id DESC |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] SQL query is difficult to read and maintain as a single concatenated string. Consider using a multi-line heredoc or nowdoc syntax for better readability and maintainability.
|
Codex Review: Didn't find any major issues. Keep them coming! ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
- Look up tax rate from Sales Tax Account linked to the overpayment financial type instead of hardcoding tax_amount to 0 - Pass tax_rate to CreditNote::save() which calculates tax_amount using the same code path as UI-created credit notes - Add test for tax calculation when financial type has tax configured
- Change payment instrument from 'credit_note' to 'accounts_receivable' since this is an internal allocation, not actual money movement - Set both from/to financial accounts to Accounts Receivable from the contribution's financial type (instead of using bank account)
- Get receivable_payment_method from company instead of using hardcoded accounts_receivable payment instrument - Get AR financial account from company's configured payment method using getInstrumentFinancialAccount() for multi-company support
|
@codex review |
1 similar comment
|
@codex review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codex Review
Here are some automated review suggestions for this pull request.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| 'description' => ts('Overpayment %1', [1 => $todayFormatted]), | ||
| 'financial_type_id' => $financialTypeId, | ||
| 'quantity' => 1, | ||
| 'unit_price' => $amount, | ||
| 'tax_rate' => $taxRate, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid adding tax on top of overpayment amount
When the overpayment financial type has a sales tax account, the credit note line is created with unit_price equal to the full overpayment and a non‑zero tax_rate. Because the overpayment amount is already the gross cash paid (computed as total payments minus the contribution’s tax‑inclusive total), CreditNote::save will add tax on top and produce a credit note larger than the overpayment (e.g. a £50 overpayment with 20% tax becomes a £60 credit), leaving accounting out of balance. Treat the overpayment as tax‑inclusive or derive a net unit price before applying tax so total credit does not exceed the overpayment.
Useful? React with 👍 / 👎.
|
@codex review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codex Review
Here are some automated review suggestions for this pull request.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
The overpayment amount is already gross cash (total_payments minus contribution_total), where contribution_total is tax-inclusive. Adding tax would inflate the credit note beyond the actual overpayment.
0ae62a4 to
d472b55
Compare
Overview
Add native support for handling contribution overpayments. When a contact pays more than the invoice amount, the contribution enters "Pending refund" status. This PR allows users to allocate that overpayment to a new credit note, which can then be applied to future
invoices.
Before
When a contribution is overpaid:
After
Technical Details
New API Action: CreditNote::allocateOverpayment()
CreditNote::allocateOverpayment(FALSE)
->setContributionId($contributionId)
->execute();
Key Implementation Notes:
Database: New column overpayment_financial_type_id added to civicrm_financeextras_company table
Multi-Company Support
The overpayment allocation uses the company's configured Accounts Receivable Payment Method to determine the financial accounts for the transaction. This ensures correct accounting in multi-company setups.
How it works:
Why this matters: