Skip to content

Conversation

@erawat
Copy link
Member

@erawat erawat commented Feb 12, 2026

Overview

Ensures instalment contributions inherit the payment method (e.g., Credit Card, Direct Debit) from their parent recurring contribution when generated by Job 1.

Before

Instalment contributions created by the Generate Instalments job did not have a payment_instrument_id, even when the parent recurring contribution had one set.

After

Instalment contributions now inherit payment_instrument_id from the parent recurring contribution, matching the Recurring-5 specification requirements.

Technical Details

  • Added paymentInstrumentId property to RecurringContributionDTO
  • Updated getDueRecurringContributions() query to select payment_instrument_id
  • Updated createInstalment() to copy payment_instrument_id when present

Core overrides

None.

Comments

This completes the Job 1 (Generate Instalments) implementation per the Recurring-5 spec.

… instalment

Add payment_instrument_id field to RecurringContributionDTO and copy it
when creating instalment contributions. This ensures instalments inherit
the payment method from the parent recurring contribution as specified
in the Recurring-5 requirements.
@gemini-code-assist
Copy link

Summary of Changes

Hello @erawat, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request resolves an issue where instalment contributions generated by Job 1 were not inheriting the payment instrument ID from their parent recurring contributions. The changes ensure that these generated instalments now correctly carry the associated payment method information, thereby aligning with the Recurring-5 specification requirements.

Highlights

  • DTO Enhancement: The RecurringContributionDTO has been updated to include a paymentInstrumentId property, allowing it to carry payment method information.
  • Data Retrieval: The getDueRecurringContributions method now explicitly selects the payment_instrument_id from the database when fetching recurring contributions.
  • Instalment Inheritance: The createInstalment method has been modified to ensure that newly generated instalment contributions inherit the payment_instrument_id from their parent recurring contribution, if available.
Changelog
  • Civi/Paymentprocessingcore/DTO/RecurringContributionDTO.php
    • Added a new private property $paymentInstrumentId to store the payment instrument ID.
    • Updated the class constructor to accept paymentInstrumentId as a parameter.
    • Modified the fromApiResult factory method to parse and set the payment_instrument_id from API results.
    • Introduced a public getter method getPaymentInstrumentId() to access the new property.
  • Civi/Paymentprocessingcore/Service/InstalmentGenerationService.php
    • Modified the getDueRecurringContributions method to include payment_instrument_id in the list of selected fields from the database.
    • Updated the createInstalment method to conditionally add the payment_instrument_id to the new instalment if it is present in the parent recurring contribution DTO.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request correctly adds support for copying the payment_instrument_id from a recurring contribution to its generated instalments. The changes in the RecurringContributionDTO and InstalmentGenerationService are logical and consistent with the existing codebase. However, I've identified a potential issue in the DTO data validation that could be improved for robustness, aligning with best practices for handling critical data. Additionally, as per the repository's style guide, the changes are missing corresponding unit tests to verify the new functionality.

'financial_type_id',
'campaign_id'
'campaign_id',
'payment_instrument_id'

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

While adding payment_instrument_id to the query is correct, this new functionality is not covered by unit tests. The repository style guide requires new features to have corresponding tests.

Please add tests to InstalmentGenerationServiceTest.php to verify that when a recurring contribution has a payment_instrument_id, the generated instalment also has it. Additionally, tests in RecurringContributionDTOTest.php should be added to ensure payment_instrument_id is correctly handled by the DTO.

References
  1. New features and bug fixes include unit tests. (link)

Comment on lines +160 to +162
$paymentInstrumentId = isset($record['payment_instrument_id']) && is_numeric($record['payment_instrument_id'])
? (int) $record['payment_instrument_id']
: NULL;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The use of isset() here could allow a payment_instrument_id of 0 to be considered valid. In CiviCRM, entity IDs are typically positive integers, so 0 is not a valid ID. This could lead to incorrect data being propagated.

To ensure only valid, positive IDs are processed, it would be safer to use !empty() which correctly handles 0, null, and empty strings as invalid values. This aligns with the principle of failing fast if critical data is missing, rather than masking potential issues with invalid default values.

    $paymentInstrumentId = !empty($record['payment_instrument_id']) && is_numeric($record['payment_instrument_id'])
      ? (int) $record['payment_instrument_id']
      : NULL;
References
  1. Avoid overly defensive variable extraction that can mask underlying data issues. It's safer to fail fast if critical data is missing, especially when default values can lead to unexpected behavior (e.g., strtotime('') evaluating to 1970-01-01).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant