Skip to content

Commit 554b755

Browse files
fix: ensure that on-hold invoices are not preselected for payment (#358) (#360)
(cherry picked from commit 0e8c4f7) Co-authored-by: Tyler Matteson <support@agritheory.dev>
1 parent aa064fc commit 554b755

File tree

3 files changed

+61
-58
lines changed

3 files changed

+61
-58
lines changed

check_run/check_run/doctype/check_run/check_run.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,6 @@ def _process_check_run(self, save: bool = False) -> None:
233233
self.submit()
234234
self.create_and_attach_positive_pay()
235235
frappe.db.sql("RELEASE SAVEPOINT process_check_run")
236-
frappe.publish_realtime("reload", "{}", doctype=self.doctype, docname=self.name)
237236

238237
def build_nacha_file(self, settings: CheckRunSettings) -> str:
239238
electronic_mop = frappe.get_all(
@@ -779,7 +778,7 @@ def get_entries(doc: CheckRun | str) -> dict:
779778
]
780779

781780
if settings and settings.pre_check_overdue_items:
782-
if transaction.due_date < doc.posting_date: # type: ignore
781+
if transaction.due_date < doc.posting_date and transaction["on_hold"] == 0: # type: ignore
783782
transaction.pay = 1
784783
if transaction.doctype == "Journal Entry":
785784
if transaction.party_type == "Supplier":

check_run/public/js/check_run/CheckRun.vue

Lines changed: 40 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,15 @@
66
<tr>
77
<th style="text-align: left" class="col col-sm-2" id="check-run-party-filter">
88
<div class="d-flex align-items-center justify-between gap-2">
9-
<span class="party-onclick party-display">
10-
Party
11-
</span>
12-
<span class="filter-icon" style="cursor: pointer;" @click="show_party_filter = !show_party_filter">
9+
<span class="party-onclick party-display"> Party </span>
10+
<span class="filter-icon" style="cursor: pointer" @click="show_party_filter = !show_party_filter">
1311
<svg class="icon icon-sm">
1412
<use class="" href="#icon-filter"></use>
1513
</svg>
1614
</span>
1715
</div>
1816
<div class="mt-2">
19-
<input
20-
v-if="show_party_filter"
21-
type="text"
22-
class="form-control"
23-
v-model="filters.party"
24-
/>
17+
<input v-if="show_party_filter" type="text" class="form-control" v-model="filters.party" />
2518
</div>
2619
</th>
2720
<th class="col col-sm-2">Document</th>
@@ -32,21 +25,21 @@
3225
</th>
3326
<th class="col col-sm-2" style="white-space: nowrap; width: 12.49%">
3427
<div class="d-flex align-items-center justify-between gap-2">
35-
<span @click="update_sort('mode_of_payment')" class="flex-grow-1 check-run-sort-indicator" id="check-run-mop-sort">
28+
<span
29+
@click="update_sort('mode_of_payment')"
30+
class="flex-grow-1 check-run-sort-indicator"
31+
id="check-run-mop-sort">
3632
Mode of Payment &#11021;
3733
</span>
38-
<span class="filter-icon" style="cursor: pointer;" @click="show_mop_filter = !show_mop_filter">
34+
<span class="filter-icon" style="cursor: pointer" @click="show_mop_filter = !show_mop_filter">
3935
<svg class="icon icon-sm">
4036
<use href="#icon-filter"></use>
4137
</svg>
4238
</span>
4339
</div>
4440

4541
<div v-if="show_mop_filter" class="mt-2">
46-
<select
47-
class="form-control form-select form-select-sm"
48-
v-model="filters.mode_of_payment_filter"
49-
>
42+
<select class="form-control form-select form-select-sm" v-model="filters.mode_of_payment_filter">
5043
<option value="All">All</option>
5144
<option v-for="mop in modes_of_payment" :key="mop" :value="mop">
5245
{{ mop === '' ? 'Not Set' : mop }}
@@ -70,18 +63,15 @@
7063
style="text-align: left">
7164
<div class="d-flex align-items-center justify-between gap-2">
7265
<span>Pay</span>
73-
<span class="filter-icon" style="cursor: pointer;" @click="show_paid_filter = !show_paid_filter">
66+
<span class="filter-icon" style="cursor: pointer" @click="show_paid_filter = !show_paid_filter">
7467
<svg class="icon icon-sm">
7568
<use href="#icon-filter"></use>
7669
</svg>
7770
</span>
7871
</div>
7972

8073
<div v-if="show_paid_filter" class="mt-2">
81-
<select
82-
class="form-control form-select form-select-sm"
83-
v-model="filters.paid_filter"
84-
>
74+
<select class="form-control form-select form-select-sm" v-model="filters.paid_filter">
8575
<option value="All">All</option>
8676
<option value="Paid">Paid</option>
8777
<option value="Unpaid">Unpaid</option>
@@ -189,35 +179,35 @@ let location = ref(window.location)
189179
let paymentSelects = ref({})
190180
191181
let orderedTransactions = computed(() => {
192-
let arr = Object.values(transactions);
193-
194-
arr = arr.filter(item => {
195-
if (!partyIsInFilter(item.party)) return false;
196-
197-
if (filters.mode_of_payment_filter === '') {
198-
if (item.mode_of_payment) return false;
199-
} else if (
200-
filters.mode_of_payment_filter &&
201-
filters.mode_of_payment_filter !== 'All' &&
202-
item.mode_of_payment !== filters.mode_of_payment_filter
203-
) {
204-
return false;
205-
}
206-
207-
if (filters.paid_filter && filters.paid_filter !== 'All') {
208-
if (filters.paid_filter === 'Paid' && !item.pay) return false;
209-
if (filters.paid_filter === 'Unpaid' && item.pay) return false;
210-
}
211-
212-
return true;
213-
});
214-
215-
return arr.sort((a, b) => {
216-
if (a[filters.key] > b[filters.key]) return filters[filters.key];
217-
if (a[filters.key] < b[filters.key]) return -filters[filters.key];
218-
return 0;
219-
});
220-
});
182+
let arr = Object.values(transactions)
183+
184+
arr = arr.filter(item => {
185+
if (!partyIsInFilter(item.party)) return false
186+
187+
if (filters.mode_of_payment_filter === '') {
188+
if (item.mode_of_payment) return false
189+
} else if (
190+
filters.mode_of_payment_filter &&
191+
filters.mode_of_payment_filter !== 'All' &&
192+
item.mode_of_payment !== filters.mode_of_payment_filter
193+
) {
194+
return false
195+
}
196+
197+
if (filters.paid_filter && filters.paid_filter !== 'All') {
198+
if (filters.paid_filter === 'Paid' && !item.pay) return false
199+
if (filters.paid_filter === 'Unpaid' && item.pay) return false
200+
}
201+
202+
return true
203+
})
204+
205+
return arr.sort((a, b) => {
206+
if (a[filters.key] > b[filters.key]) return filters[filters.key]
207+
if (a[filters.key] < b[filters.key]) return -filters[filters.key]
208+
return 0
209+
})
210+
})
221211
222212
let modes_of_payment = computed(() => {
223213
return unref(window.check_run.modes_of_payment)

check_run/tests/test_check_run.py

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,26 +68,40 @@ def test_process_check_run_on_hold_invoice_error(cr):
6868
with pytest.raises(
6969
frappe.exceptions.ValidationError, match=f"Purchase Invoice ACC-PINV-{year}-00020 is on hold"
7070
):
71-
# cr.flags.in_test = True
7271
cr.process_check_run()
7372

7473

7574
@pytest.mark.order(12)
7675
def test_process_check_run_on_hold_invoice_auto_release(cr):
7776
# Test Settings auto-release of on-hold invoices
78-
cr.transactions = frappe.utils.safe_json_loads(cr.transactions)
77+
crs = get_check_run_settings(cr)
78+
crs.pre_check_overdue_items = True
79+
crs.save()
80+
cr.end_date = datetime.date(year, 12, 30)
81+
cr.transactions = get_entries(cr).get("transactions")
7982
for row in cr.transactions:
80-
if row.get("party") == "Liu & Loewen Accountants LLP":
83+
if row.get("party") == "Liu & Loewen Accountants LLP" and row.get("on_hold") == True:
84+
assert not row.get("pay") # test that on-hold invoices are not selected for payment
8185
row["pay"] = True
8286
row["mode_of_payment"] = "Credit Card"
83-
cr.transactions = frappe.as_json(cr.transactions)
84-
cr.flags.in_test = True
85-
cr.save()
87+
else:
88+
assert row["pay"]
8689

8790
crs = get_check_run_settings(cr)
91+
crs.pre_check_overdue_items = False
8892
crs.automatically_release_on_hold_invoices = True
8993
crs.save()
9094

95+
cr.end_date = datetime.date(year, 12, 31)
96+
cr.transactions = get_entries(cr).get("transactions")
97+
for row in cr.transactions:
98+
if row.get("party") == "Liu & Loewen Accountants LLP" and row.get("on_hold") == True:
99+
row["pay"] = True
100+
row["mode_of_payment"] = "Credit Card"
101+
cr.transactions = frappe.as_json(cr.transactions)
102+
cr.flags.in_test = True
103+
cr.save()
104+
91105
try:
92106
cr.process_check_run()
93107
except frappe.exceptions.ValidationError:

0 commit comments

Comments
 (0)