Skip to content
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

fix: split_invoices_based_on_payment_terms #37859

Merged
merged 6 commits into from
Nov 10, 2023

Conversation

marination
Copy link
Collaborator

@marination marination commented Nov 2, 2023

Issues:

  • Invoices were in the wrong order due to the logic. The invoices with payment terms were added first and the rest after.
  • Overly long function with unnecessary loops (reduced to one main loop) and complexity

Before:

  • "ACC-SINV-2023-00038" is allocated first inspite having the longest due date, as it is an invoice with payment terms which was processed first
  • The order makes a difference when one of the invoices is partially allocated. The expectation would be the oldest invoices get fully allocated first. Which does not happen in this case
  • Invoice "ACC-SINV-2023-00037" is partially allocated when we wanted "ACC-SINV-2023-00038" to be partially allocated as it is the newest invoice with a longer due date
    2023-11-02 11 31 22

After:

  • "ACC-SINV-2023-00038" is partially allocated
  • The order of instalments among split rows of the invoice is also maintained
    2023-11-02 11 35 56

Misc:

  • Extracted major parts of split_invoices_based_on_payment_terms into get_currency_data and get_split_invoice_rows
  • Use one single loop to process invoices. In the loop if the invoice can be broken down by payment terms then do that, else add the invoice row as is. In this way the order of invoices is maintained.
  • Instead of creating a default dict for payment terms against invoices, fetch the details in the loop dynamically

Note: Encountered this issue while trying to reuse this API for the new Bank Reco tool. Even there, the order of invoices passed to this API highly matters as the invoices are ordered by rank and the allocation must happen exactly like that.

- Invoices were in the wrong order due to the logic. The invoices with payment terms were added first and the rest after.
- Overly long function with unnecessary loops (reduced to one main loop) and complexity
- The split row as per payment terms was not ordered. So the second installment was allocated first
@marination marination self-assigned this Nov 2, 2023
@github-actions github-actions bot added the needs-tests This PR needs automated unit-tests. label Nov 2, 2023
@marination marination assigned ruthra-kumar and unassigned marination Nov 2, 2023
Copy link

codecov bot commented Nov 2, 2023

Codecov Report

Merging #37859 (4b4b176) into develop (6e3e094) will decrease coverage by 0.01%.
Report is 36 commits behind head on develop.
The diff coverage is 68.64%.

❗ Current head 4b4b176 differs from pull request most recent head 1fc5844. Consider uploading reports for the commit 1fc5844 to get more accurate results

@@             Coverage Diff             @@
##           develop   #37859      +/-   ##
===========================================
- Coverage    67.40%   67.39%   -0.01%     
===========================================
  Files          757      757              
  Lines        60337    60375      +38     
===========================================
+ Hits         40668    40688      +20     
- Misses       19669    19687      +18     
Files Coverage Δ
..._receivable_summary/accounts_receivable_summary.py 92.15% <100.00%> (+0.07%) ⬆️
...tax_withholding_details/tax_withholding_details.py 79.87% <ø> (ø)
erpnext/accounts/utils.py 73.22% <100.00%> (+0.06%) ⬆️
erpnext/stock/doctype/stock_entry/stock_entry.py 82.41% <ø> (ø)
erpnext/stock/get_item_details.py 83.03% <ø> (ø)
.../report/accounts_receivable/accounts_receivable.py 90.09% <96.15%> (+0.13%) ⬆️
erpnext/accounts/report/financial_statements.py 80.42% <0.00%> (ø)
...t/accounts/report/general_ledger/general_ledger.py 70.45% <0.00%> (ø)
...ext/accounts/report/trial_balance/trial_balance.py 75.14% <0.00%> (ø)
...eport/fixed_asset_register/fixed_asset_register.py 0.00% <0.00%> (ø)
... and 6 more

@bosue
Copy link
Contributor

bosue commented Nov 3, 2023

Sorry for bothering you again.

The order makes a difference when one of the invoices is partially allocated. The expectation would be the oldest invoices get fully allocated first. Which does not happen in this case

In general, this is indeed the expectation, so this PR definitely improves things. I would actually consider it a bugfix, name it accordingly, and make sure it’s backported, although refactoring may be part of the solution.

However, there are quite many situation where the allocation order needs to be different:

  • There may be an explicit or more often: implicit instruction by the customer which invoices the payment should be applied to. (§ 366 BGB in Germany)
  • Costs, then interests, then principle rules (§ 367 BGB in Germany)
  • In rental contracts etc., the current invoice ( < 3 weeks or the current month) needs to be allocated first as only then it is considered a “cash-like transaction”, at least according to the German insolvency clawback law.
  • etc.

While your PR does implement a sensible default, in followups we should iterate over this to simplify switching the allocation order or even to implement allocation rules.

@marination
Copy link
Collaborator Author

@bosue Sounds good. Unfortunately I don't have the bandwidth to take this up, but I'd suggest moving your suggestion to a separate issue where it can be tracked and worked on. Thanks for taking the effort :)

@bosue
Copy link
Contributor

bosue commented Nov 3, 2023

A pleasure. Think we need a basic test to fail ahead of the bugfix while passing with it, and then this should be merged and backported. Probably even as “fix!” as it may break previous expectations.

@bosue

This comment was marked as resolved.

@marination marination changed the title refactor: split_invoices_based_on_payment_terms fix: split_invoices_based_on_payment_terms Nov 7, 2023
@marination marination removed the needs-tests This PR needs automated unit-tests. label Nov 7, 2023
@ruthra-kumar
Copy link
Member

ruthra-kumar commented Nov 9, 2023

"ACC-SINV-2023-00038" is partially allocated

@marination This(allocating the oldest first) doesn't happen.

SINV-23-20599 is the oldest with term based allocation in below scenario.

term_based_allocation.mp4

@bosue
Copy link
Contributor

bosue commented Nov 9, 2023

@ruthra-kumar:

I can reproduce though:
IMG_2070

With adapted columns (added Due Date) it’s easier to spot.

@marination
Copy link
Collaborator Author

marination commented Nov 9, 2023

@ruthra-kumar I worded this wrongly. My apologies

  • So the issue was that the invoices passed to split_invoices_based_on_payment_terms would lose their order.
  • Due to how this function processed payment terms first and then added invoices without terms later, we would always have invoices with payment terms added first to the references table (irrespective of due date), which is fixed now by the refactor.
  • In ERPNEXT split_invoices_based_on_payment_terms gets invoices from get_outstanding_invoices, which orders the invoices by due_date.
  • The Payment terms themselves were also fetched haphazardly earlier (the last term was allocated first). I've added an order_by to the Payment Schedule query to fix the order.

What @bosue has shown in his last comment is the issue. The invoices are fetched as per due date but split_invoices_based_on_payment_terms messes up the order.

…effective test

- Make invoice due dates are different so that the invoice with the earliest due date is allocated first in the test
- Translate voucher type, simplify alert message. The invoice could be "split" into 1 row, no. of rows in the message seems unnecessary.
@marination
Copy link
Collaborator Author

Also I think we should have the Due Date in the Payment References child table. If space is a problem, maybe even instead of the Grand Total. Outstanding and Allocated amounts should be sufficient.

@bosue I'm personally not sure/very opinionated on what columns users would deem important although I agree with your suggestion. Let this be tackled in a separate PR/issue

@ruthra-kumar
Copy link
Member

@ruthra-kumar ruthra-kumar merged commit 6ca3b26 into frappe:develop Nov 10, 2023
11 of 12 checks passed
@marination marination added the backport version-14-hotfix backport to version 14 label Nov 13, 2023
deepeshgarg007 added a commit that referenced this pull request Nov 26, 2023
…-37859

fix: `split_invoices_based_on_payment_terms` (#37859)
deepeshgarg007 pushed a commit that referenced this pull request Dec 6, 2023
* refactor: `split_invoices_based_on_payment_terms`

- Invoices were in the wrong order due to the logic. The invoices with payment terms were added first and the rest after.
- Overly long function with unnecessary loops (reduced to one main loop) and complexity
- The split row as per payment terms was not ordered. So the second installment was allocated first

(cherry picked from commit 6bd56d2)

* test: `get_outstanding_reference_documents` (triggered via UI)

(cherry picked from commit 162c049)

# Conflicts:
#	erpnext/accounts/doctype/payment_entry/test_payment_entry.py

* fix: Alert message and make sure invoice due dates are different for effective test

- Make invoice due dates are different so that the invoice with the earliest due date is allocated first in the test
- Translate voucher type, simplify alert message. The invoice could be "split" into 1 row, no. of rows in the message seems unnecessary.

(cherry picked from commit 56ac342)

* style: Remove spaces introduced via merge conflict

(cherry picked from commit 4b4b176)

# Conflicts:
#	erpnext/accounts/doctype/payment_entry/test_payment_entry.py

* fix: Re-add no.of rows split in alert message

(cherry picked from commit 1fc5844)

* fix: Merge conflicts in tests

---------

Co-authored-by: marination <maricadsouza221197@gmail.com>
frappe-pr-bot pushed a commit that referenced this pull request Dec 12, 2023
# [15.6.0](v15.5.0...v15.6.0) (2023-12-12)

### Bug Fixes

* `split_invoices_based_on_payment_terms` (backport [#37859](#37859)) ([#38488](#38488)) ([4b76cc4](4b76cc4))
* 1st row depr. sch. value of asset put to less than 180 days acc. to I.T. S. 32 (backport [#38696](#38696)) ([#38703](#38703)) ([2bd9671](2bd9671))
* auto delete draft serial and batch bundle (backport [#38637](#38637)) ([#38654](#38654)) ([b0675f6](b0675f6))
* close PO on SCO close (backport [#38667](#38667)) ([#38681](#38681)) ([4055543](4055543))
* format only if searched text contain link value text ([d79e6e3](d79e6e3))
* get customers for leaderboard ([9d5c79d](9d5c79d))
* get items for leaderboard ([7cb38a8](7cb38a8))
* get sales partner for leaderboard ([3845d42](3845d42))
* get sales person for leaderboard ([2fcfebe](2fcfebe))
* get suppliers for leaderboard ([e205772](e205772))
* ignore non-existing regional customizations (backport [#38621](#38621)) ([#38624](#38624)) ([c70e6f2](c70e6f2))
* limit end date to current date ([dbdb971](dbdb971))
* negative batch issue (backport [#38688](#38688)) ([#38694](#38694)) ([a75081b](a75081b))
* not able to make serial and batch using csv import (backport [#38659](#38659)) ([#38662](#38662)) ([dd07eca](dd07eca))
* only highest eligible coupon applied ([#38416](#38416)) ([aa66ee6](aa66ee6))
* serial and batch bundle permission (backport [#38618](#38618)) ([#38619](#38619)) ([ce2bd15](ce2bd15))
* serial no filter in the Serial No Ledger report (backport [#38669](#38669)) ([#38682](#38682)) ([d188c8e](d188c8e))
* Shipping Address Link Showing in Buying (backport [#38634](#38634)) ([#38646](#38646)) ([4150ed9](4150ed9))
* show stock qty in popup (backport [#38698](#38698)) ([#38699](#38699)) ([6e2cde4](6e2cde4))
* typeerror on new sites ([#38692](#38692)) ([9239e73](9239e73))
* typo in unittest ([#38673](#38673)) ([14ee13c](14ee13c))
* **ux:** don't update qty blindly (backport [#38608](#38608)) ([#38639](#38639)) ([0b2e2a2](0b2e2a2))

### Features

* add employee number to client user bootinfo (backport [#38477](#38477)) ([#38603](#38603)) ([c7dbcbc](c7dbcbc))
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jan 1, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants