diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 00000000..b72767b9
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,15 @@
+# Root editor config file
+root = true
+
+# Common settings
+[*]
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+charset = utf-8
+
+# python, js indentation settings
+[{*.py,*.js,*.vue,*.css,*.scss,*.html}]
+indent_style = tab
+indent_size = 2
+max_line_length = 99
diff --git a/.flake8 b/.flake8
new file mode 100644
index 00000000..16f799f3
--- /dev/null
+++ b/.flake8
@@ -0,0 +1,71 @@
+[flake8]
+ignore =
+ B001,
+ B007,
+ B009,
+ B010,
+ B950,
+ E101,
+ E111,
+ E114,
+ E116,
+ E117,
+ E121,
+ E122,
+ E123,
+ E124,
+ E125,
+ E126,
+ E127,
+ E128,
+ E131,
+ E201,
+ E202,
+ E203,
+ E211,
+ E221,
+ E222,
+ E223,
+ E224,
+ E225,
+ E226,
+ E228,
+ E231,
+ E241,
+ E242,
+ E251,
+ E261,
+ E262,
+ E265,
+ E266,
+ E271,
+ E272,
+ E273,
+ E274,
+ E301,
+ E302,
+ E303,
+ E305,
+ E306,
+ E402,
+ E501,
+ E502,
+ E701,
+ E702,
+ E703,
+ E741,
+ W191,
+ W291,
+ W292,
+ W293,
+ W391,
+ W503,
+ W504,
+ E711,
+ E129,
+ F841,
+ E713,
+ E712,
+
+max-line-length = 200
+exclude=,test_*.py
diff --git a/check_run/check_run/doctype/check_run/check_run.js b/check_run/check_run/doctype/check_run/check_run.js
index f37e95c9..ccf06e3d 100644
--- a/check_run/check_run/doctype/check_run/check_run.js
+++ b/check_run/check_run/doctype/check_run/check_run.js
@@ -62,6 +62,20 @@ frappe.ui.form.on('Check Run', {
$(frm.wrapper).on('dirty', () => {
frm.trigger('update_primary_action')
})
+ if (frm.doc.__onload && frm.doc.__onload.check_run_submitting == frm.doc.name) {
+ frm.doc.status = 'Submitting'
+ frm.page.set_indicator(__('Submitting'), 'orange')
+ frm.disable_form()
+ cur_frm.$check_run.$children[0].state.status = 'Submitting'
+ } else if (frm.doc.__onload && frm.doc.__onload.check_run_submitting) {
+ frm.set_intro(
+ __(
+ `Check Run ${frm.doc.__onload.check_run_submitting} is processing. This Check Run cannot be processed until it completes.`
+ ),
+ 'red'
+ )
+ cur_frm.$check_run.$children[0].state.status = 'Submitting'
+ }
},
end_date: frm => {
get_entries(frm)
@@ -97,14 +111,17 @@ frappe.ui.form.on('Check Run', {
frm.doc.status = 'Submitting'
frm.page.set_indicator(__('Submitting'), 'orange')
frm.disable_form()
- $(frm.$check_run).css({ 'pointer-events': 'none' })
frappe.xcall('check_run.check_run.doctype.check_run.check_run.process_check_run', { docname: frm.doc.name })
+ cur_frm.$check_run.$children[0].state.status = frm.doc.status
},
update_primary_action: frm => {
frm.disable_save()
if (frm.is_dirty()) {
frm.enable_save()
- } else if (frm.doc.status === 'Draft') {
+ } else if ((frm.doc.__onload && frm.doc.__onload.check_run_submitting) || frm.doc.status == 'Submitting') {
+ frm.disable_save()
+ frm.disable_form()
+ } else if (frm.doc.status == 'Draft' && !(frm.doc.__onload && frm.doc.__onload.check_run_submitting)) {
frm.page.set_primary_action(__('Process Check Run'), () => frm.trigger('process_check_run'))
}
},
@@ -141,7 +158,7 @@ function get_entries(frm) {
check_run.mount_table(frm)
if (!frappe.user.has_role(['Accounts Manager'])) {
frm.disable_form()
- frm.$check_run.css({ 'pointer-events': 'none' })
+ cur_frm.$check_run.$children[0].state.status = frm.doc.status
}
})
}
diff --git a/check_run/check_run/doctype/check_run/check_run.json b/check_run/check_run/doctype/check_run/check_run.json
index 4cbd6886..3181fabc 100644
--- a/check_run/check_run/doctype/check_run/check_run.json
+++ b/check_run/check_run/doctype/check_run/check_run.json
@@ -11,6 +11,7 @@
"end_date",
"posting_date",
"beg_balance",
+ "company_discretionary_data",
"column_break_3",
"initial_check_number",
"final_check_number",
@@ -19,10 +20,10 @@
"company",
"bank_account",
"pay_to_account",
+ "amended_from",
"section_break_9",
"check_run_table",
"transactions",
- "amended_from",
"print_count",
"status"
],
@@ -95,6 +96,14 @@
"remember_last_selected_value": 1,
"reqd": 1
},
+ {
+ "allow_on_submit": 1,
+ "depends_on": "eval:doc.docstatus==1",
+ "fieldname": "company_discretionary_data",
+ "fieldtype": "Data",
+ "label": "Company Discretionary Data",
+ "length": 20
+ },
{
"fieldname": "section_break_9",
"fieldtype": "Section Break"
@@ -135,7 +144,7 @@
"fieldname": "status",
"fieldtype": "Select",
"hidden": 1,
- "options": "Draft\nSubmitted\nSubmitting\nReady to Print\nConfirm Print\nPrinted"
+ "options": "Draft\nSubmitting\nSubmitted\nReady to Print\nConfirm Print\nPrinted"
},
{
"fieldname": "check_run_table",
@@ -151,11 +160,10 @@
],
"is_submittable": 1,
"links": [],
- "modified": "2023-02-28 16:55:18.369852",
+ "modified": "2023-03-10 12:28:36.910004",
"modified_by": "Administrator",
"module": "Check Run",
"name": "Check Run",
- "naming_rule": "Expression (old style)",
"owner": "Administrator",
"permissions": [
{
@@ -182,7 +190,6 @@
"quick_entry": 1,
"sort_field": "modified",
"sort_order": "DESC",
- "states": [],
"track_changes": 1,
"track_seen": 1,
"track_views": 1
diff --git a/check_run/check_run/doctype/check_run/check_run.py b/check_run/check_run/doctype/check_run/check_run.py
index 90048b71..a41678e0 100644
--- a/check_run/check_run/doctype/check_run/check_run.py
+++ b/check_run/check_run/doctype/check_run/check_run.py
@@ -1,29 +1,26 @@
# Copyright (c) 2022, AgriTheory and contributors
# For license information, please see license.txt
-from __future__ import unicode_literals
import datetime
import json
from itertools import groupby, zip_longest
from io import StringIO
-import types
from PyPDF2 import PdfFileWriter
import frappe
from frappe.model.document import Document
from frappe.utils.data import flt
-from frappe.utils.data import date_diff, add_days, nowdate, getdate, now, get_datetime
+from frappe.utils.data import nowdate, getdate, now, get_datetime
from frappe.utils.print_format import read_multi_pdf
from frappe.permissions import has_permission
-from frappe.utils.file_manager import save_file, remove_all, download_file
+from frappe.utils.file_manager import save_file, remove_all
from frappe.utils.password import get_decrypted_password
-from frappe.contacts.doctype.address.address import get_default_address
+from frappe.contacts.doctype.address.address import get_default_address
from frappe.query_builder.custom import ConstantColumn
from frappe.query_builder.functions import Coalesce
from erpnext.accounts.utils import get_balance_on
-from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_dimensions
from atnacha import ACHEntry, ACHBatch, NACHAFile
from check_run.check_run.doctype.check_run_settings.check_run_settings import create
@@ -35,14 +32,19 @@ def onload(self):
return
settings = get_check_run_settings(self)
if not settings:
- self.set_onload('settings_missing', True)
- errors = frappe.get_all('Error Log', {'method': ['like', f"%{self.name}%"]})
+ self.set_onload("settings_missing", True)
+ errors = frappe.get_all("Error Log", {"method": ["like", f"%{self.name}%"]})
if errors and self.docstatus == 0:
- self.set_onload('errors', True)
+ self.set_onload("errors", True)
+ check_run_submitting = frappe.defaults.get_global_default("check_run_submitting")
+ if check_run_submitting:
+ self.set_onload("check_run_submitting", check_run_submitting)
+ else:
+ self.set_onload("check_run_submitting", False)
def validate(self):
self.set_status()
- gl_account = frappe.get_value('Bank Account', self.bank_account, 'account')
+ gl_account = frappe.get_value("Bank Account", self.bank_account, "account")
if not gl_account:
frappe.throw(frappe._("This Bank Account is not associated with a General Ledger Account."))
self.beg_balance = get_balance_on(gl_account, self.posting_date)
@@ -57,39 +59,39 @@ def validate(self):
def on_cancel(self):
settings = get_check_run_settings(self)
if not settings.allow_cancellation:
- frappe.throw(frappe._('The settings for this Check Run do not allow cancellation'))
+ frappe.throw(frappe._("The settings for this Check Run do not allow cancellation"))
if settings.allow_cancellation and settings.cascade_cancellation:
# cancel all PEs linked to this check run
- pes = frappe.get_all('Payment Entry', {'check_run': self.name, 'docstatus': 1})
+ pes = frappe.get_all("Payment Entry", {"check_run": self.name, "docstatus": 1})
for pe in pes:
- frappe.get_doc('Payment Entry', pe).cancel()
+ frappe.get_doc("Payment Entry", pe).cancel()
if settings.allow_cancellation and not settings.cascade_cancellation:
# unlink all PE's linked to this check run
- pes = frappe.get_all('Payment Entry', {'check_run': self.name, 'docstatus': 1})
+ pes = frappe.get_all("Payment Entry", {"check_run": self.name, "docstatus": 1})
for pe in pes:
- frappe.db.set_value('Payment Entry', pe, 'check_run', '')
+ frappe.db.set_value("Payment Entry", pe, "check_run", "")
def set_status(self, status=None):
if status:
self.status = status
- elif self.status == 'Confirm Print':
+ elif self.status == "Confirm Print":
pass
elif self.docstatus == 0:
- self.status = 'Draft'
+ self.status = "Draft"
elif self.docstatus == 1 and self.print_count > 0:
- self.status = 'Printed'
+ self.status = "Printed"
elif self.docstatus == 1:
- self.status = 'Submitted'
+ self.status = "Submitted"
def set_last_check_number(self):
if self.ach_only().ach_only:
return
- check_number = frappe.get_value('Bank Account', self.bank_account, "check_number")
+ check_number = frappe.get_value("Bank Account", self.bank_account, "check_number")
self.initial_check_number = int(check_number or 0) + 1
def set_default_payable_account(self):
if not self.pay_to_account:
- self.pay_to_account = frappe.get_value('Company', self.company, "default_payable_account")
+ self.pay_to_account = frappe.get_value("Company", self.company, "default_payable_account")
def set_default_dates(self):
if not self.posting_date:
@@ -98,28 +100,40 @@ def set_default_dates(self):
self.end_date = getdate()
def validate_transactions(self):
- if not self.get('transactions'):
+ if not self.get("transactions"):
return
- selected = [txn for txn in json.loads(self.get('transactions')) if txn['pay']]
+ selected = [txn for txn in json.loads(self.get("transactions")) if txn["pay"]]
wrong_status = []
for t in selected:
- if not t['mode_of_payment']:
+ if not t["mode_of_payment"]:
frappe.throw(frappe._(f"Mode of Payment Required: {t['party_name']} {t['ref_number']}"))
- filters = {'name': t['name'] if t['doctype'] != 'Journal Entry' else t['ref_number']}
- if frappe.get_value(t['doctype'], filters, 'docstatus') != 1:
- wrong_status.append({'party_name': t['party_name'], 'ref_number': t['ref_number'] or '', 'name': t['name']})
+ filters = {"name": t["name"] if t["doctype"] != "Journal Entry" else t["ref_number"]}
+ if frappe.get_value(t["doctype"], filters, "docstatus") != 1:
+ wrong_status.append(
+ {"party_name": t["party_name"], "ref_number": t["ref_number"] or "", "name": t["name"]}
+ )
if len(wrong_status) < 1:
return
- invalid_records = ''
+ invalid_records = ""
for invalid_record in wrong_status:
- invalid_records += ' '.join(invalid_record.values()) + '
'
- frappe.throw(frappe._(
- f"The following document(s) have been cancelled, please remove them from Check Run to continue:
{invalid_records}"
- ))
+ invalid_records += " ".join(invalid_record.values()) + "
"
+ frappe.throw(
+ frappe._(
+ f"The following document(s) have been cancelled, please remove them from Check Run to continue:
{invalid_records}"
+ )
+ )
@frappe.whitelist()
def process_check_run(self):
- self.status = 'Submitting'
+ # check_run_submitting = frappe.defaults.get_global_default("check_run_submitting")
+ # if check_run_submitting:
+ # frappe.throw(
+ # frappe._(
+ # f"""Check run {check_run_submitting} is in process. No other check runs can be submitted until it completes. Click here for details."""
+ # )
+ # )
+ # return
+ self.status = "Submitting"
transactions = self.transactions
transactions = json.loads(transactions)
if len(transactions) < 1:
@@ -128,51 +142,65 @@ def process_check_run(self):
if self.ach_only().ach_only:
self.initial_check_number = ""
self.final_check_number = ""
- frappe.enqueue_doc(self.doctype, self.name, "_process_check_run", save=True, queue="short", timeout=3600)
+ frappe.enqueue_doc(
+ self.doctype, self.name, "_process_check_run", save=True, queue="short", timeout=3600, now=True
+ )
def _process_check_run(self, save=False):
- savepoint = "process_check_run"
- frappe.db.savepoint(savepoint)
+ frappe.defaults.set_global_default("check_run_submitting", self.name)
+ frappe.db.sql("SAVEPOINT process_check_run")
try:
transactions = self.transactions
transactions = json.loads(transactions)
- transactions = sorted([frappe._dict(item) for item in transactions if item.get("pay")], key=lambda x: x.party)
+ transactions = sorted(
+ (frappe._dict(item) for item in transactions if item.get("pay")), key=lambda x: x.party
+ )
_transactions = self.create_payment_entries(transactions)
except Exception as e:
- frappe.db.rollback(savepoint="process_check_run")
+ try:
+ frappe.db.rollback(save_point="process_check_run")
+ except Exception as _e:
+ pass
+ frappe.defaults.clear_default("check_run_submitting")
raise e
+ frappe.defaults.clear_default("check_run_submitting")
self.transactions = json.dumps(_transactions)
- self.set_status('Submitted')
+ self.set_status("Submitted")
self.save()
self.submit()
- if self.final_check_number:
- frappe.db.set_value('Bank Account', self.bank_account, 'check_number', self.final_check_number)
- frappe.publish_realtime('reload', '{}', doctype=self.doctype, docname=self.name)
+ frappe.db.sql("RELEASE SAVEPOINT process_check_run")
+ frappe.publish_realtime("reload", "{}", doctype=self.doctype, docname=self.name)
def build_nacha_file(self, settings=None):
- electronic_mop = frappe.get_all('Mode of Payment', {'type': 'Electronic', 'enabled': 1}, 'name', pluck="name")
- ach_payment_entries = list(set(
- [e.get('payment_entry') for e in json.loads(self.transactions) if e.get('mode_of_payment') in electronic_mop]
- ))
- payment_entries = [frappe.get_doc('Payment Entry', pe) for pe in ach_payment_entries]
- nacha_file = build_nacha_file_from_payment_entries(self, payment_entries, settings)
- ach_file = StringIO(nacha_file())
- ach_file.seek(0)
- return ach_file
+ electronic_mop = frappe.get_all(
+ "Mode of Payment", {"type": "Electronic", "enabled": 1}, "name", pluck="name"
+ )
+ ach_payment_entries = list(
+ {
+ e.get("payment_entry")
+ for e in json.loads(self.transactions)
+ if e.get("mode_of_payment") in electronic_mop
+ }
+ )
+ payment_entries = [frappe.get_doc("Payment Entry", pe) for pe in ach_payment_entries]
+ return build_nacha_file_from_payment_entries(self, payment_entries, settings)
@frappe.whitelist()
def ach_only(self):
transactions = json.loads(self.transactions) if self.transactions else []
- ach_only = frappe._dict({'ach_only': True, 'print_checks_only': True})
+ ach_only = frappe._dict({"ach_only": True, "print_checks_only": True})
if not self.transactions:
ach_only.ach_only = False
ach_only.print_checks_only = False
return ach_only
- eft_mapping = {mop.name: mop.type for mop in frappe.get_all("Mode of Payment", {'enabled': True}, ['name', 'type'])}
- if any([eft_mapping.get(t.get('mode_of_payment')) == 'Bank' for t in transactions]):
+ eft_mapping = {
+ mop.name: mop.type
+ for mop in frappe.get_all("Mode of Payment", {"enabled": True}, ["name", "type"])
+ }
+ if any([eft_mapping.get(t.get("mode_of_payment")) == "Bank" for t in transactions]):
ach_only.ach_only = False
- if any([eft_mapping.get(t.get('mode_of_payment')) == 'Electronic' for t in transactions]):
+ if any([eft_mapping.get(t.get("mode_of_payment")) == "Electronic" for t in transactions]):
ach_only.print_checks_only = False
return ach_only
@@ -183,30 +211,33 @@ def create_payment_entries(self, transactions):
split = settings.number_of_invoices_per_voucher
check_count = 0
_transactions = []
- gl_account = frappe.get_value('Bank Account', self.bank_account, 'account')
- key_lookup = lambda x: x.party
+ gl_account = frappe.get_value("Bank Account", self.bank_account, "account")
+ key_lookup = lambda x: x.party # noqa: E731
if settings and settings.split_by_address:
- key_lookup = lambda x: (x.get('party'), x.get('address'))
+ key_lookup = lambda x: (x.get("party"), x.get("address")) # noqa: E731
for transaction in transactions:
- transaction['address'] = get_address(
- transaction.get('party'), transaction.get('party_type'), transaction.get('doctype'), transaction.get('name')
+ transaction["address"] = get_address(
+ transaction.get("party"),
+ transaction.get("party_type"),
+ transaction.get("doctype"),
+ transaction.get("name"),
)
- for party, _group in groupby(transactions, key=key_lookup):
- _group = list(_group)
- if frappe.db.get_value('Mode of Payment', _group[0].mode_of_payment, 'type') == 'Bank':
- groups = list(zip_longest(*[iter(_group)] * split))
+ for party, __group in groupby(transactions, key=key_lookup):
+ _group = list(__group)
+ if frappe.db.get_value("Mode of Payment", _group[0].mode_of_payment, "type") == "Bank":
+ groups = list(zip_longest(*[iter(_group)] * split))
else:
groups = [_group]
if not groups:
continue
for group in groups:
_references = []
- if group[0].doctype == 'Purchase Invoice':
- party = frappe.db.get_value('Purchase Invoice', group[0].name, 'supplier')
- elif group[0].doctype == 'Expense Claim':
- party = frappe.db.get_value('Expense Claim', group[0].name, 'employee')
- elif group[0].doctype == 'Journal Entry':
- party = frappe.db.get_value('Journal Entry Account', group[0].name, 'party')
+ if group[0].doctype == "Purchase Invoice":
+ party = frappe.db.get_value("Purchase Invoice", group[0].name, "supplier")
+ elif group[0].doctype == "Expense Claim":
+ party = frappe.db.get_value("Expense Claim", group[0].name, "employee")
+ elif group[0].doctype == "Journal Entry":
+ party = frappe.db.get_value("Journal Entry Account", group[0].name, "party")
pe = frappe.new_doc("Payment Entry")
pe.payment_type = "Pay"
pe.posting_date = nowdate()
@@ -215,38 +246,47 @@ def create_payment_entries(self, transactions):
pe.bank_account = self.bank_account
pe.paid_from = gl_account
pe.paid_to = self.pay_to_account
- pe.paid_to_account_currency = frappe.db.get_value("Account", self.bank_account, "account_currency")
+ pe.paid_to_account_currency = frappe.db.get_value(
+ "Account", self.bank_account, "account_currency"
+ )
pe.paid_from_account_currency = pe.paid_to_account_currency
pe.reference_date = self.posting_date
pe.party_type = group[0].party_type
- pe.party = group[0].party
+ pe.party = party
pe.check_run = self.name
total_amount = 0
- if frappe.db.get_value('Mode of Payment', _group[0].mode_of_payment, 'type') == 'Bank':
+ if frappe.db.get_value("Mode of Payment", _group[0].mode_of_payment, "type") == "Bank":
pe.reference_no = int(self.initial_check_number) + check_count
check_count += 1
self.final_check_number = pe.reference_no
else:
- pe.reference_no = frappe._(f"via {_group[0].mode_of_payment} {self.get_formatted('posting_date')}")
-
+ pe.reference_no = frappe._(
+ f"via {_group[0].mode_of_payment} {self.get_formatted('posting_date')}"
+ )
+
for reference in group:
if not reference:
continue
- if settings.automatically_release_on_hold_invoices and reference.doctype == 'Purchase Invoice':
- if frappe.get_value(reference.doctype, reference.name, 'on_hold'):
- frappe.db.set_value(reference.doctype, reference.name, 'on_hold', 0)
- if reference.doctype == 'Journal Entry':
+ if (
+ settings.automatically_release_on_hold_invoices and reference.doctype == "Purchase Invoice"
+ ):
+ if frappe.get_value(reference.doctype, reference.name, "on_hold"):
+ frappe.db.set_value(reference.doctype, reference.name, "on_hold", 0)
+ if reference.doctype == "Journal Entry":
reference_name = reference.ref_number
else:
reference_name = reference.name or reference.ref_number
- pe.append('references', {
+ pe.append(
+ "references",
+ {
"reference_doctype": reference.doctype,
"reference_name": reference_name,
"due_date": reference.get("due_date"),
"outstanding_amount": flt(reference.amount),
"allocated_amount": flt(reference.amount),
"total_amount": flt(reference.amount),
- })
+ },
+ )
total_amount += reference.amount
reference.check_number = pe.reference_no
_references.append(reference)
@@ -261,55 +301,63 @@ def create_payment_entries(self, transactions):
except Exception as e:
frappe.db.rollback()
frappe.log_error(title=f"{self.name} Check Run Error", message=e)
- frappe.publish_realtime('reload', '{}', doctype=self.doctype, docname=self.name)
+ frappe.publish_realtime("reload", "{}", doctype=self.doctype, docname=self.name)
raise e
for reference in _references:
reference.payment_entry = pe.name
_transactions.append(reference)
return _transactions
-
@frappe.whitelist()
def increment_print_count(self, reprint_check_number=None):
- print('render checks')
- frappe.enqueue_doc(self.doctype, self.name, 'render_check_pdf', reprint_check_number=reprint_check_number, queue='short', now=True)
-
+ frappe.enqueue_doc(
+ self.doctype,
+ self.name,
+ "render_check_pdf",
+ reprint_check_number=reprint_check_number,
+ queue="short",
+ now=True,
+ )
@frappe.whitelist()
def render_check_pdf(self, reprint_check_number=None):
self.print_count = self.print_count + 1
- self.set_status('Submitted')
- if not frappe.db.exists('File', 'Home/Check Run'):
- try:
+ self.set_status("Submitted")
+ if not frappe.db.exists("File", "Home/Check Run"):
+ try:
cr_folder = frappe.new_doc("File")
- cr_folder.update({"file_name":"Check Run", "is_folder": True, "folder":"Home"})
+ cr_folder.update({"file_name": "Check Run", "is_folder": True, "folder": "Home"})
cr_folder.save()
except Exception as e:
pass
settings = get_check_run_settings(self)
initial_check_number = int(self.initial_check_number)
- if reprint_check_number and reprint_check_number != 'undefined':
+ if reprint_check_number and reprint_check_number != "undefined":
self.initial_check_number = int(reprint_check_number)
output = PdfFileWriter()
transactions = json.loads(self.transactions)
check_increment = 0
_transactions = []
- for pe, group in groupby(transactions, key=lambda x: x.get('payment_entry')):
- group = list(group)
- mode_of_payment, docstatus = frappe.db.get_value('Payment Entry', pe, ['mode_of_payment', 'docstatus']) or (None, None)
- if docstatus == 1 and frappe.db.get_value('Mode of Payment', mode_of_payment, 'type') == 'Bank':
+ for pe, _group in groupby(transactions, key=lambda x: x.get("payment_entry")):
+ group = list(_group)
+ mode_of_payment, docstatus = frappe.db.get_value(
+ "Payment Entry", pe, ["mode_of_payment", "docstatus"]
+ ) or (None, None)
+ if docstatus == 1 and frappe.db.get_value("Mode of Payment", mode_of_payment, "type") == "Bank":
output = frappe.get_print(
- 'Payment Entry',
+ "Payment Entry",
pe,
- settings.print_format or frappe.get_meta('Payment Entry').default_print_format,
+ settings.print_format or frappe.get_meta("Payment Entry").default_print_format,
as_pdf=True,
output=output,
no_letterhead=0,
)
if initial_check_number != reprint_check_number:
- frappe.db.set_value('Payment Entry', pe, 'reference_no', self.initial_check_number + check_increment)
+ frappe.db.set_value(
+ "Payment Entry", pe, "reference_no", self.initial_check_number + check_increment
+ )
for ref in group:
- ref['check_number'] = self.initial_check_number + check_increment
+ ref["check_number"] = self.initial_check_number + check_increment
_transactions.append(ref)
check_increment += 1
elif docstatus == 1:
@@ -317,30 +365,33 @@ def render_check_pdf(self, reprint_check_number=None):
_transactions.append(ref)
if _transactions and reprint_check_number:
- self.db_set('transactions', json.dumps(_transactions))
- self.db_set('final_check_number', self.initial_check_number + (check_increment - 1))
- self.db_set('status', 'Ready to Print')
- self.db_set('print_count', self.print_count)
- frappe.db.set_value('Bank Account', self.bank_account, 'check_number', self.final_check_number)
- save_file(f"{self.name}.pdf", read_multi_pdf(output), 'Check Run', self.name, 'Home/Check Run', False, 0)
+ self.db_set("transactions", json.dumps(_transactions))
+ self.db_set("initial_check_number", self.initial_check_number)
+ self.db_set("final_check_number", self.initial_check_number + (check_increment - 1))
+ self.db_set("status", "Ready to Print")
+ self.db_set("print_count", self.print_count)
+ frappe.db.set_value("Bank Account", self.bank_account, "check_number", self.final_check_number)
+ save_file(
+ f"{self.name}.pdf", read_multi_pdf(output), "Check Run", self.name, "Home/Check Run", False, 0
+ )
frappe.db.commit()
- frappe.publish_realtime('reload', '{}', doctype=self.doctype, docname=self.name)
+ frappe.publish_realtime("reload", "{}", doctype=self.doctype, docname=self.name)
@frappe.whitelist()
def check_for_draft_check_run(company, bank_account, payable_account):
existing = frappe.get_value(
- 'Check Run', {
- 'company': company,
- 'bank_account': bank_account,
- 'pay_to_account': payable_account,
- 'status': ['in', ['Draft', 'Submitted']],
- 'initial_check_number': ['!=', 0]
- }
+ "Check Run",
+ {
+ "company": company,
+ "bank_account": bank_account,
+ "pay_to_account": payable_account,
+ "docstatus": 0,
+ },
)
if existing:
return existing
- cr = frappe.new_doc('Check Run')
+ cr = frappe.new_doc("Check Run")
cr.company = company
cr.bank_account = bank_account
cr.pay_to_account = payable_account
@@ -351,129 +402,141 @@ def check_for_draft_check_run(company, bank_account, payable_account):
@frappe.whitelist()
def confirm_print(docname):
# Remove PDF file(s)
- remove_all('Check Run', docname, from_delete=False, delete_permanently=False)
-
+ remove_all("Check Run", docname, from_delete=False, delete_permanently=False)
+
# Reset status
- return frappe.db.set_value('Check Run', docname, 'status', 'Printed')
+ return frappe.db.set_value("Check Run", docname, "status", "Printed")
@frappe.whitelist()
def get_entries(doc):
doc = frappe._dict(json.loads(doc)) if isinstance(doc, str) else doc
if isinstance(doc.end_date, str):
- doc.end_date = getdate(doc.end_date)
- doc.posting_date = getdate(doc.posting_date)
- modes_of_payment = frappe.get_all('Mode of Payment', order_by='name')
- if frappe.db.exists('Check Run Settings', {'bank_account': doc.bank_account, 'pay_to_account': doc.pay_to_account}):
- settings = frappe.get_doc('Check Run Settings', {'bank_account': doc.bank_account, 'pay_to_account': doc.pay_to_account})
+ doc.end_date = getdate(doc.end_date)
+ doc.posting_date = getdate(doc.posting_date)
+ modes_of_payment = frappe.get_all("Mode of Payment", order_by="name")
+ if frappe.db.exists(
+ "Check Run Settings", {"bank_account": doc.bank_account, "pay_to_account": doc.pay_to_account}
+ ):
+ settings = frappe.get_doc(
+ "Check Run Settings", {"bank_account": doc.bank_account, "pay_to_account": doc.pay_to_account}
+ )
else:
settings = None
- if frappe.db.exists('Check Run', doc.name):
- db_doc = frappe.get_doc('Check Run', doc.name)
+ if frappe.db.exists("Check Run", doc.name):
+ db_doc = frappe.get_doc("Check Run", doc.name)
if doc.end_date == db_doc.end_date and db_doc.transactions:
- return {'transactions': json.loads(db_doc.transactions), 'modes_of_payment': modes_of_payment}
+ return {"transactions": json.loads(db_doc.transactions), "modes_of_payment": modes_of_payment}
company = doc.company
pay_to_account = doc.pay_to_account
end_date = doc.end_date
# Build purchase invoices query
- purchase_invoices = frappe.qb.DocType('Purchase Invoice')
- suppliers = frappe.qb.DocType('Supplier')
+ purchase_invoices = frappe.qb.DocType("Purchase Invoice")
+ suppliers = frappe.qb.DocType("Supplier")
pi_qb = (
frappe.qb.from_(purchase_invoices)
- .inner_join(suppliers)
- .on(purchase_invoices.supplier == suppliers.name)
- .select(
- ConstantColumn('Purchase Invoice').as_('doctype'),
- ConstantColumn('Supplier').as_('party_type'),
- purchase_invoices.name,
- (purchase_invoices.bill_no).as_('ref_number'),
- (purchase_invoices.supplier_name).as_('party'),
- (suppliers.supplier_name).as_('party_name'),
- (purchase_invoices.outstanding_amount).as_('amount'),
- purchase_invoices.due_date,
- purchase_invoices.posting_date,
- Coalesce(purchase_invoices.supplier_default_mode_of_payment, suppliers.supplier_default_mode_of_payment, '\n').as_('mode_of_payment')
- )
- .where(purchase_invoices.outstanding_amount > 0)
- .where(purchase_invoices.company == company)
- .where(purchase_invoices.docstatus == 1)
- .where(purchase_invoices.credit_to == pay_to_account)
- .where(purchase_invoices.due_date <= end_date)
- .where(Coalesce(purchase_invoices.release_date, datetime.date(1900, 1, 1)) < end_date)
+ .inner_join(suppliers)
+ .on(purchase_invoices.supplier == suppliers.name)
+ .select(
+ ConstantColumn("Purchase Invoice").as_("doctype"),
+ ConstantColumn("Supplier").as_("party_type"),
+ purchase_invoices.name,
+ (purchase_invoices.bill_no).as_("ref_number"),
+ (purchase_invoices.supplier_name).as_("party"),
+ (suppliers.supplier_name).as_("party_name"),
+ (purchase_invoices.outstanding_amount).as_("amount"),
+ purchase_invoices.due_date,
+ purchase_invoices.posting_date,
+ Coalesce(
+ purchase_invoices.supplier_default_mode_of_payment,
+ suppliers.supplier_default_mode_of_payment,
+ "\n",
+ ).as_("mode_of_payment"),
+ )
+ .where(purchase_invoices.outstanding_amount > 0)
+ .where(purchase_invoices.company == company)
+ .where(purchase_invoices.docstatus == 1)
+ .where(purchase_invoices.credit_to == pay_to_account)
+ .where(purchase_invoices.due_date <= end_date)
+ .where(Coalesce(purchase_invoices.release_date, datetime.date(1900, 1, 1)) < end_date)
)
# Build expense claims query
- exp_claims = frappe.qb.DocType('Expense Claim')
- employees = frappe.qb.DocType('Employee')
+ exp_claims = frappe.qb.DocType("Expense Claim")
+ employees = frappe.qb.DocType("Employee")
ec_qb = (
frappe.qb.from_(exp_claims)
- .inner_join(employees)
- .on(exp_claims.employee == employees.name)
- .select(
- ConstantColumn('Expense Claim').as_('doctype'),
- ConstantColumn('Employee').as_('party_type'),
- exp_claims.name,
- (exp_claims.name).as_('ref_number'),
- (exp_claims.employee).as_('party'),
- (employees.employee_name).as_('party_name'),
- (exp_claims.grand_total).as_('amount'),
- (exp_claims.posting_date).as_('due_date'),
- exp_claims.posting_date,
- Coalesce(exp_claims.mode_of_payment, employees.mode_of_payment, '\n').as_('mode_of_payment')
- )
- .where(exp_claims.grand_total > exp_claims.total_amount_reimbursed)
- .where(exp_claims.company == company)
- .where(exp_claims.docstatus == 1)
- .where(exp_claims.payable_account == pay_to_account)
- .where(exp_claims.posting_date <= end_date)
+ .inner_join(employees)
+ .on(exp_claims.employee == employees.name)
+ .select(
+ ConstantColumn("Expense Claim").as_("doctype"),
+ ConstantColumn("Employee").as_("party_type"),
+ exp_claims.name,
+ (exp_claims.name).as_("ref_number"),
+ (exp_claims.employee).as_("party"),
+ (employees.employee_name).as_("party_name"),
+ (exp_claims.grand_total).as_("amount"),
+ (exp_claims.posting_date).as_("due_date"),
+ exp_claims.posting_date,
+ Coalesce(exp_claims.mode_of_payment, employees.mode_of_payment, "\n").as_("mode_of_payment"),
+ )
+ .where(exp_claims.grand_total > exp_claims.total_amount_reimbursed)
+ .where(exp_claims.company == company)
+ .where(exp_claims.docstatus == 1)
+ .where(exp_claims.payable_account == pay_to_account)
+ .where(exp_claims.posting_date <= end_date)
)
# Build journal entries query
- journal_entries = frappe.qb.DocType('Journal Entry')
- je_accounts = frappe.qb.DocType('Journal Entry Account')
- payment_entries = frappe.qb.DocType('Payment Entry')
- pe_ref = frappe.qb.DocType('Payment Entry Reference')
-
+ journal_entries = frappe.qb.DocType("Journal Entry")
+ je_accounts = frappe.qb.DocType("Journal Entry Account")
+ payment_entries = frappe.qb.DocType("Payment Entry")
+ pe_ref = frappe.qb.DocType("Payment Entry Reference")
+
sub_q = (
frappe.qb.from_(payment_entries)
- .inner_join(pe_ref)
- .on(payment_entries.name == pe_ref.parent)
- .select(pe_ref.reference_name)
- .where(pe_ref.reference_doctype == 'Journal Entry')
- .where(payment_entries.party == je_accounts.party)
- .where(payment_entries.docstatus == 1)
+ .inner_join(pe_ref)
+ .on(payment_entries.name == pe_ref.parent)
+ .select(pe_ref.reference_name)
+ .where(pe_ref.reference_doctype == "Journal Entry")
+ .where(payment_entries.party == je_accounts.party)
+ .where(payment_entries.docstatus == 1)
)
je_qb = (
frappe.qb.from_(journal_entries)
- .inner_join(je_accounts)
- .on(journal_entries.name == je_accounts.parent)
- .select(
- ConstantColumn('Journal Entry').as_('doctype'),
- je_accounts.party_type,
- je_accounts.name,
- (journal_entries.name).as_('ref_number'),
- je_accounts.party,
- (je_accounts.party).as_('party_name'),
- (je_accounts.credit_in_account_currency).as_('amount'),
- journal_entries.due_date,
- journal_entries.posting_date,
- Coalesce(journal_entries.mode_of_payment, '\n').as_('mode_of_payment')
- )
- .where(journal_entries.company == company)
- .where(journal_entries.docstatus == 1)
- .where(je_accounts.account == pay_to_account)
- .where(journal_entries.due_date <= end_date)
- .where((journal_entries.name).notin(sub_q))
+ .inner_join(je_accounts)
+ .on(journal_entries.name == je_accounts.parent)
+ .select(
+ ConstantColumn("Journal Entry").as_("doctype"),
+ je_accounts.party_type,
+ je_accounts.name,
+ (journal_entries.name).as_("ref_number"),
+ je_accounts.party,
+ (je_accounts.party).as_("party_name"),
+ (je_accounts.credit_in_account_currency).as_("amount"),
+ journal_entries.due_date,
+ journal_entries.posting_date,
+ Coalesce(journal_entries.mode_of_payment, "\n").as_("mode_of_payment"),
+ )
+ .where(journal_entries.company == company)
+ .where(journal_entries.docstatus == 1)
+ .where(je_accounts.account == pay_to_account)
+ .where(journal_entries.due_date <= end_date)
+ .where((journal_entries.name).notin(sub_q))
)
-
+
if not settings:
query = pi_qb.union(ec_qb).union(je_qb)
else:
query = ""
- flags = (settings.include_purchase_invoices, settings.include_expense_claims, settings.include_journal_entries)
+ flags = (
+ settings.include_purchase_invoices,
+ settings.include_expense_claims,
+ settings.include_journal_entries,
+ )
for flag, qb in zip(flags, (pi_qb, ec_qb, je_qb)):
if not flag:
continue
@@ -482,24 +545,28 @@ def get_entries(doc):
else:
query = query.union(qb)
if query:
- query = query.orderby('due_date', 'name').get_sql()
+ query = query.orderby("due_date", "name").get_sql()
- transactions = frappe.db.sql(query, {
- 'company': company, 'pay_to_account': pay_to_account, 'end_date': end_date
- }, as_dict=True)
+ transactions = frappe.db.sql(
+ query, {"company": company, "pay_to_account": pay_to_account, "end_date": end_date}, as_dict=True
+ )
for transaction in transactions:
if settings and settings.pre_check_overdue_items:
if transaction.due_date < doc.posting_date:
transaction.pay = 1
- if transaction.doctype == 'Journal Entry':
- if transaction.party_type == 'Supplier':
- transaction.party_name = frappe.get_value('Supplier', transaction.party, 'supplier_name')
- transaction.mode_of_payment = frappe.get_value('Supplier', transaction.party, 'supplier_default_mode_of_payment')
- if transaction.party_type == 'Employee':
- transaction.party_name = frappe.get_value('Employee', transaction.party, 'employee_name')
- transaction.mode_of_payment = frappe.get_value('Employee', transaction.party, 'mode_of_payment')
+ if transaction.doctype == "Journal Entry":
+ if transaction.party_type == "Supplier":
+ transaction.party_name = frappe.get_value("Supplier", transaction.party, "supplier_name")
+ transaction.mode_of_payment = frappe.get_value(
+ "Supplier", transaction.party, "supplier_default_mode_of_payment"
+ )
+ if transaction.party_type == "Employee":
+ transaction.party_name = frappe.get_value("Employee", transaction.party, "employee_name")
+ transaction.mode_of_payment = frappe.get_value(
+ "Employee", transaction.party, "mode_of_payment"
+ )
- return {'transactions': transactions, 'modes_of_payment': modes_of_payment}
+ return {"transactions": transactions, "modes_of_payment": modes_of_payment}
@frappe.whitelist()
@@ -507,32 +574,42 @@ def get_balance(doc):
doc = frappe._dict(json.loads(doc)) if isinstance(doc, str) else doc
if not doc.bank_account or not doc.posting_date:
return
- gl_account = frappe.get_value('Bank Account', doc.bank_account, 'account')
+ gl_account = frappe.get_value("Bank Account", doc.bank_account, "account")
return get_balance_on(gl_account, doc.posting_date)
@frappe.whitelist()
def download_checks(docname):
- has_permission('Payment Entry', ptype="print", verbose=False, user=frappe.session.user, raise_exception=True)
- file_name = frappe.get_value('File', {'attached_to_name': docname})
- frappe.db.set_value('Check Run', docname, 'status', "Confirm Print")
- return frappe.get_value('File', file_name, 'file_url')
+ has_permission(
+ "Payment Entry", ptype="print", verbose=False, user=frappe.session.user, raise_exception=True
+ )
+ file_name = frappe.get_value("File", {"attached_to_name": docname})
+ frappe.db.set_value("Check Run", docname, "status", "Confirm Print")
+ return frappe.get_value("File", file_name, "file_url")
@frappe.whitelist()
def download_nacha(docname):
- has_permission('Payment Entry', ptype="print", verbose=False, user=frappe.session.user, raise_exception=True)
- doc = frappe.get_doc('Check Run', docname)
+ has_permission(
+ "Payment Entry", ptype="print", verbose=False, user=frappe.session.user, raise_exception=True
+ )
+ doc = frappe.get_doc("Check Run", docname)
settings = get_check_run_settings(doc)
ach_file = doc.build_nacha_file(settings)
+ if settings.custom_post_processing_hook:
+ ach_file = frappe.call(settings.custom_post_processing_hook, doc, settings, ach_file)
+ else:
+ ach_file = ach_file()
+ ach_file = StringIO(ach_file)
+ ach_file.seek(0)
file_ext = settings.ach_file_extension if settings and settings.ach_file_extension else "ach"
frappe.local.response.filename = f'{docname.replace(" ", "-").replace("/", "-")}.{file_ext}'
frappe.local.response.type = "download"
frappe.local.response.filecontent = ach_file.read()
- comment = frappe.new_doc('Comment')
+ comment = frappe.new_doc("Comment")
comment.owner = "Administrator"
- comment.comment_type = 'Info'
- comment.reference_doctype = 'Check Run'
+ comment.comment_type = "Info"
+ comment.reference_doctype = "Check Run"
comment.reference_name = doc.name
comment.published = 1
comment.content = f"{frappe.session.user} created a NACHA file on {now()}"
@@ -544,58 +621,67 @@ def download_nacha(docname):
def build_nacha_file_from_payment_entries(doc, payment_entries, settings):
ach_entries = []
exceptions = []
- company_bank = frappe.db.get_value('Bank Account', doc.bank_account, 'bank')
+ company_bank = frappe.db.get_value("Bank Account", doc.bank_account, "bank")
if not company_bank:
- exceptions.append(f'Company Bank missing for {doc.company}')
+ exceptions.append(f"Company Bank missing for {doc.company}")
if company_bank:
- company_bank_aba_number = frappe.db.get_value('Bank', company_bank, 'aba_number')
- company_bank_account_no = frappe.db.get_value('Bank Account', doc.bank_account, 'bank_account_no')
- company_ach_id = frappe.db.get_value('Bank Account', doc.bank_account, 'company_ach_id')
+ company_bank_aba_number = frappe.db.get_value("Bank", company_bank, "aba_number")
+ company_bank_account_no = frappe.db.get_value(
+ "Bank Account", doc.bank_account, "bank_account_no"
+ )
+ company_ach_id = frappe.db.get_value("Bank Account", doc.bank_account, "company_ach_id")
if company_bank and not company_bank_aba_number:
- exceptions.append(f'Company Bank ABA Number missing for {doc.bank_account}')
+ exceptions.append(f"Company Bank ABA Number missing for {doc.bank_account}")
if company_bank and not company_bank_account_no:
- exceptions.append(f'Company Bank Account Number missing for {doc.bank_account}')
+ exceptions.append(f"Company Bank Account Number missing for {doc.bank_account}")
if company_bank and not company_ach_id:
- exceptions.append(f'Company Bank ACH ID missing for {doc.bank_account}')
+ exceptions.append(f"Company Bank ACH ID missing for {doc.bank_account}")
for pe in payment_entries:
- party_bank_account = get_decrypted_password(pe.party_type, pe.party, fieldname='bank_account', raise_exception=False)
+ party_bank_account = get_decrypted_password(
+ pe.party_type, pe.party, fieldname="bank_account", raise_exception=False
+ )
if not party_bank_account:
- exceptions.append(f'{pe.party_type} Bank Account missing for {pe.party_name}')
- party_bank = frappe.db.get_value(pe.party_type, pe.party, 'bank')
+ exceptions.append(f"{pe.party_type} Bank Account missing for {pe.party_name}")
+ party_bank = frappe.db.get_value(pe.party_type, pe.party, "bank")
if not party_bank:
- exceptions.append(f'{pe.party_type} Bank missing for {pe.party_name}')
+ exceptions.append(f"{pe.party_type} Bank missing for {pe.party_name}")
if party_bank:
- party_bank_routing_number = frappe.db.get_value('Bank', party_bank, 'aba_number')
+ party_bank_routing_number = frappe.db.get_value("Bank", party_bank, "aba_number")
if not party_bank_routing_number:
- exceptions.append(f'{pe.party_type} Bank Routing Number missing for {pe.party_name}')
+ exceptions.append(f"{pe.party_type} Bank Routing Number missing for {pe.party_name}")
ach_entry = ACHEntry(
- transaction_code=22, # checking account
+ transaction_code=22, # checking account
receiving_dfi_identification=party_bank_routing_number,
dfi_account_number=party_bank_account,
amount=int(pe.paid_amount * 100),
- individual_id_number='',
+ individual_id_number="",
individual_name=pe.party_name,
- discretionary_data='',
+ discretionary_data="",
addenda_record_indicator=0,
)
ach_entries.append(ach_entry)
-
- if exceptions:
- frappe.throw('
'.join(e for e in exceptions))
+ if exceptions:
+ frappe.throw("
".join(e for e in exceptions))
+ company_discretionary_data = (
+ doc.get("company_discretionary_data")
+ if doc.get("company_discretionary_data")
+ else (settings.get("company_discretionary_data") or "")
+ )
+ ach_description = settings.get("ach_description") or ""
batch = ACHBatch(
service_class_code=settings.ach_service_class_code,
- company_name=doc.get('company'),
- company_discretionary_data='',
+ company_name=doc.get("company"),
+ company_discretionary_data=company_discretionary_data[:20],
company_id=company_ach_id,
standard_class_code=settings.ach_standard_class_code,
- company_entry_description=settings.ach_description or "",
+ company_entry_description=ach_description[:10] or "",
company_descriptive_date=None,
- effective_entry_date=getdate(),
+ effective_entry_date=doc.posting_date,
settlement_date=None,
originator_status_code=1,
originating_dfi_id=company_bank_account_no,
- entries=ach_entries
+ entries=ach_entries,
)
nacha_file = NACHAFile(
priority_code=1,
@@ -603,13 +689,13 @@ def build_nacha_file_from_payment_entries(doc, payment_entries, settings):
immediate_origin=settings.immediate_origin or "",
file_creation_date=getdate(),
file_creation_time=get_datetime(),
- file_id_modifier='0',
+ file_id_modifier="0",
blocking_factor=10,
format_code=1,
immediate_destination_name=company_bank,
immediate_origin_name=doc.company,
- reference_code='',
- batches=[batch]
+ reference_code="",
+ batches=[batch],
)
return nacha_file
@@ -617,33 +703,37 @@ def build_nacha_file_from_payment_entries(doc, payment_entries, settings):
@frappe.whitelist()
def get_check_run_settings(doc):
doc = frappe._dict(json.loads(doc)) if isinstance(doc, str) else doc
- if frappe.db.exists('Check Run Settings', {'bank_account': doc.bank_account, 'pay_to_account': doc.pay_to_account}):
- return frappe.get_doc('Check Run Settings', {'bank_account': doc.bank_account, 'pay_to_account': doc.pay_to_account})
+ if frappe.db.exists(
+ "Check Run Settings", {"bank_account": doc.bank_account, "pay_to_account": doc.pay_to_account}
+ ):
+ return frappe.get_doc(
+ "Check Run Settings", {"bank_account": doc.bank_account, "pay_to_account": doc.pay_to_account}
+ )
else:
return create(doc.company, doc.bank_account, doc.pay_to_account)
-
+
def get_address(party, party_type, doctype, name):
- if doctype == 'Purchase Invoice':
- return frappe.get_value('Purchase Invoice', name, 'supplier_address')
- elif doctype == 'Expense Claim':
- return frappe.get_value('Employee', name, 'permanent_address')
- elif doctype == 'Journal Entry':
- if party_type == 'Supplier':
- return get_default_address('Supplier', party)
- elif party_type == 'Employee':
- return frappe.get_value('Employee', name, 'permanent_address')
+ if doctype == "Purchase Invoice":
+ return frappe.get_value("Purchase Invoice", name, "supplier_address")
+ elif doctype == "Expense Claim":
+ return frappe.get_value("Employee", name, "permanent_address")
+ elif doctype == "Journal Entry":
+ if party_type == "Supplier":
+ return get_default_address("Supplier", party)
+ elif party_type == "Employee":
+ return frappe.get_value("Employee", name, "permanent_address")
@frappe.whitelist()
def ach_only(docname):
- if not frappe.db.exists('Check Run', docname):
- return {'ach_only': False, 'checks_only': False}
- cr = frappe.get_doc('Check Run', docname)
+ if not frappe.db.exists("Check Run", docname):
+ return {"ach_only": False, "checks_only": False}
+ cr = frappe.get_doc("Check Run", docname)
return cr.ach_only()
@frappe.whitelist()
def process_check_run(docname):
- doc = frappe.get_doc('Check Run', docname)
+ doc = frappe.get_doc("Check Run", docname)
doc.process_check_run()
diff --git a/check_run/check_run/doctype/check_run_settings/check_run_settings.json b/check_run/check_run/doctype/check_run_settings/check_run_settings.json
index 84910163..1b097f9e 100644
--- a/check_run/check_run/doctype/check_run_settings/check_run_settings.json
+++ b/check_run/check_run/doctype/check_run_settings/check_run_settings.json
@@ -28,7 +28,9 @@
"ach_standard_class_code",
"ach_description",
"column_break_21",
- "immediate_origin"
+ "immediate_origin",
+ "company_discretionary_data",
+ "custom_post_processing_hook"
],
"fields": [
{
@@ -130,7 +132,8 @@
{
"fieldname": "ach_description",
"fieldtype": "Data",
- "label": "ACH Description"
+ "label": "ACH Description",
+ "length": 10
},
{
"fieldname": "print_format",
@@ -163,10 +166,22 @@
"fieldname": "immediate_origin",
"fieldtype": "Data",
"label": "Immediate Origin"
+ },
+ {
+ "fieldname": "company_discretionary_data",
+ "fieldtype": "Data",
+ "label": "Company Discretionary Data",
+ "length": 20
+ },
+ {
+ "fieldname": "custom_post_processing_hook",
+ "fieldtype": "Data",
+ "label": "Custom Post Processing Hook",
+ "read_only": 1
}
],
"links": [],
- "modified": "2023-03-09 07:34:52.062230",
+ "modified": "2023-03-17 13:43:25.837467",
"modified_by": "Administrator",
"module": "Check Run",
"name": "Check Run Settings",
@@ -201,4 +216,4 @@
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
-}
\ No newline at end of file
+}
diff --git a/check_run/hooks.py b/check_run/hooks.py
index 69c28529..a97b2f77 100644
--- a/check_run/hooks.py
+++ b/check_run/hooks.py
@@ -36,6 +36,7 @@
# include js in doctype views
doctype_js = {
'Employee': 'public/js/custom/employee_custom.js',
+ "Payment Entry": 'public/js/custom/payment_entry_custom.js',
"Supplier": 'public/js/custom/supplier_custom.js',
}
# doctype_list_js = {"doctype" : "public/js/doctype_list.js"}
@@ -102,13 +103,11 @@
# ---------------
# Hook on document methods and events
-# doc_events = {
-# "*": {
-# "on_update": "method",
-# "on_cancel": "method",
-# "on_trash": "method"
-# }
-# }
+doc_events = {
+ "Payment Entry": {
+ "on_submit": "check_run.overrides.payment_entry.update_check_number",
+ }
+}
# Scheduled Tasks
# ---------------
diff --git a/check_run/overrides/payment_entry.py b/check_run/overrides/payment_entry.py
new file mode 100644
index 00000000..ff6a4de5
--- /dev/null
+++ b/check_run/overrides/payment_entry.py
@@ -0,0 +1,7 @@
+import frappe
+
+@frappe.whitelist()
+def update_check_number(doc, method=None):
+ mode_of_payment_type = frappe.db.get_value('Mode of Payment', doc.mode_of_payment, 'type')
+ if doc.bank_account and mode_of_payment_type == 'Bank':
+ frappe.db.set_value('Bank Account', doc.bank_account, 'check_number', doc.reference_no)
diff --git a/check_run/public/js/check_run/CheckRun.vue b/check_run/public/js/check_run/CheckRun.vue
index 3777a888..1a5eb56e 100644
--- a/check_run/public/js/check_run/CheckRun.vue
+++ b/check_run/public/js/check_run/CheckRun.vue
@@ -41,7 +41,7 @@
>⬍
-