Define the logic that sets (or not) contribution receive_date in relation to payments
We discovered that Payment.create that completed a contribution was having a side-effect of updating the contribution's
receive_date to today's date.
The PR at https://github.com/civicrm/civicrm-core/pull/17688 corrected that by ensuring the payment's date is properly passed through into the underlying BAO code that does the updates and now tests that the
receive_date is set to the
trxn_date of the new payment.
However it raised questions: why should a payment update the contribution's
Rather than hold up a PR which was around fixing a definitely-not-what-we-want behaviour, we started this issue to have the discussion. It is referenced in the docblock of the new test in tests/phpunit/api/v3/PaymentTest.php called
Before we jump in about one field, let's consider the whole picture (which I may or may not describe properly here)
A contribution is created in Pending state, which generates:
- a contribution record, which has a
receive_date, but also
revenue_recognition_date(and less importantly: cancel, receipt and thankyou dates)
- a "financial item" for each line item. This has a
transaction_datefield, as well as a
- depending on config (and possible bugs), a financial transaction record transferring the total amount from the line items' financial types' configured income accounts to Accounts Receivable account, and this table (
civicrm_financial_trxn) has a
- a contribution record, which has a
A contribution may receive various "payments" (in API speak, but it's really about financial transactions). Typically this represents the full payment for the whole contribution, and in which case it "completes" the contribution. But it also seems to cover various changes, cancellations, refunds, partial payments... For the 90% case where it completes the contribution, this generate:
civicrm_financial_trxnrow which has a
trxn_date, and transferrs the funds into (Dr) the payment instrument's configured account from (Cr) the Accounts Receivable account.
- Currently, it will update the
receive_datefor the contribution, too.
So, dates-wise we have:
|Reference||date||observed current behaviour|
||Shown in lists. Create date, then updated.|
||NULL - don't know when/if this gets set|
|➌||financial item 1's
||Date contribution was created|
|➍||financial item 1's
||Date completing (or latest?) payment made|
|➎||financial trxn 1's
||Could not observe; is not created (think this is a bug see link above)|
|➏||financial trxn 2's
||Date of the completing payment|
I can see that there are situations where it makes sense to update the receive date: for most payments that are made in a single lump, it's probably the most important date: when did we get the money (not just the promise/hope/intent of money)? But as soon as you get into partial payments, refunds etc. then that's only going to be an approximation.
CiviContribute sets up pending contributions willy-nilly which can also represent abandoned baskets, but there's the case when this is set up before midnight and the payment comes a minute later but after midnight. Direct Debit processors may set them up for future payments, or initial payments, but the receive dates may differ due to local banking rules (e.g. bank/public holidays, lack of funds...).
So, what should we do? Leave
receive_date alone instead of updating it to the completion date? Do the other dates have enough exposure to do this (ie. is it clear to users what the dates mean)? Set it as the date the first funds were received? The latest funds (completing or not) received? Do we update it for cancelled/refunded/partially refunded?