Skip to content

Commit

Permalink
feat: split checks by address
Browse files Browse the repository at this point in the history
  • Loading branch information
HKuz authored and agritheory committed Feb 15, 2023
1 parent 78b3e25 commit b32f0c9
Show file tree
Hide file tree
Showing 3 changed files with 172 additions and 20 deletions.
36 changes: 27 additions & 9 deletions check_run/check_run/doctype/check_run/check_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@
from frappe.permissions import has_permission
from frappe.utils.file_manager import save_file, remove_all, download_file
from frappe.utils.password import get_decrypted_password
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

class CheckRun(Document):
Expand All @@ -41,8 +41,8 @@ def validate(self):
self.beg_balance = get_balance_on(gl_account, self.posting_date)
if self.flags.in_insert:
if self.initial_check_number is None:
self.get_last_check_number()
self.get_default_payable_account()
self.set_last_check_number()
self.set_default_payable_account()
self.set_default_dates()
else:
self.validate_transactions()
Expand Down Expand Up @@ -75,13 +75,13 @@ def set_status(self, status=None):
elif self.docstatus == 1:
self.status = 'Submitted'

def get_last_check_number(self):
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")
self.initial_check_number = int(check_number or 0) + 1

def get_default_payable_account(self):
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")

Expand Down Expand Up @@ -144,7 +144,6 @@ def build_nacha_file(self, settings=None):
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())
print(ach_file)
ach_file.seek(0)
return ach_file

Expand Down Expand Up @@ -172,7 +171,14 @@ def create_payment_entries(self, transactions):
check_count = 0
_transactions = []
gl_account = frappe.get_value('Bank Account', self.bank_account, 'account')
for party, _group in groupby(transactions, key=lambda x: x.party):
key_lookup = lambda x: x.party
if settings and settings.split_by_address:
key_lookup = lambda x: (x.get('party'), x.get('address'))
for transaction in transactions:
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))
Expand Down Expand Up @@ -558,7 +564,7 @@ def build_nacha_file_from_payment_entries(doc, payment_entries, settings):
)
nacha_file = NACHAFile(
priority_code=1,
immediate_destination=company_bank_aba_number,
immediate_destination=company_bank_aba_number if not settings.omit_destination else "",
immediate_origin=company_bank_aba_number,
file_creation_date=getdate(),
file_creation_time=get_datetime(),
Expand All @@ -577,4 +583,16 @@ def build_nacha_file_from_payment_entries(doc, payment_entries, settings):
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})
return frappe.get_doc('Check Run Settings', {'bank_account': doc.bank_account, 'pay_to_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')
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,14 @@
"cascade_cancellation",
"column_break_9",
"number_of_invoices_per_voucher",
"split_by_address",
"ach_settings_section",
"ach_file_extension",
"ach_service_class_code",
"ach_standard_class_code",
"ach_description"
"ach_description",
"column_break_21",
"omit_destination"
],
"fields": [
{
Expand Down Expand Up @@ -132,10 +136,31 @@
"fieldtype": "Link",
"label": "Print Format",
"options": "Print Format"
}
},
{
"default": "0",
"fieldname": "split_by_address",
"fieldtype": "Check",
"label": "Split Invoices by Address"
},
{
"fieldname": "ach_settings_section",
"fieldtype": "Section Break",
"label": "ACH Settings"
},
{
"default": "0",
"fieldname": "omit_destination",
"fieldtype": "Check",
"label": "Omit Destination"
},
{
"fieldname": "column_break_21",
"fieldtype": "Column Break"
}
],
"links": [],
"modified": "2022-08-26 16:54:08.327344",
"modified": "2022-02-13 15:33:15.269467",
"modified_by": "Administrator",
"module": "Check Run",
"name": "Check Run Settings",
Expand Down
125 changes: 117 additions & 8 deletions check_run/test_setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,65 @@ def before_test():
create_test_data()

suppliers = [
("Exceptional Grid", "Electricity", "ACH/EFT", 150.00),
("Liu & Loewen Accountants LLP", "Accounting Services", "ACH/EFT", 500.00),
("Mare Digitalis", "Cloud Services", "Credit Card", 200.00),
("AgriTheory", "ERPNext Consulting", "Check", 1000.00),
("HIJ Telecom, Inc", "Internet Services", "Check", 150.00),
("Sphere Cellular", "Phone Services", "ACH/EFT", 250.00),
("Cooperative Ag Finance", "Financial Services", "Bank Draft", 5000.00),
("Exceptional Grid", "Electricity", "ACH/EFT", 150.00, {
'address_line1': '2 Cosmo Point',
'city': 'Summerville',
'state': 'MA',
'country': 'United States',
'pincode': '34791'
}),
("Liu & Loewen Accountants LLP", "Accounting Services", "ACH/EFT", 500.00, {
'address_line1': '138 Wanda Square',
'city': 'Chino',
'state': 'ME',
'country': 'United States',
'pincode': '90953'
}),
("Mare Digitalis", "Cloud Services", "Credit Card", 200.00, {
'address_line1': '1000 Toll Plaza Tunnel Alley',
'city': 'Joplin',
'state': 'CT',
'country': 'United States',
'pincode': '51485'
}),
("AgriTheory", "ERPNext Consulting", "Check", 1000.00, {
'address_line1': '1293 Bannan Road',
'city': 'New Brighton',
'state': 'NH',
'country': 'United States',
'pincode': '55932'
}),
("HIJ Telecom, Inc", "Internet Services", "Check", 150.00, {
'address_line1': '955 Winding Highway',
'city': 'Glassboro',
'state': 'NY',
'country': 'United States',
'pincode': '28026'
}),
("Sphere Cellular", "Phone Services", "ACH/EFT", 250.00, {
'address_line1': '1198 Carpenter Road',
'city': 'Rolla',
'state': 'VT',
'country': 'United States',
'pincode': '94286'
}),
("Cooperative Ag Finance", "Financial Services", "Bank Draft", 5000.00, {
'address_line1': '629 Loyola Landing',
'city': 'Warner Robins',
'state': 'CT',
'country': 'United States',
'pincode': '28989'
}),
]

tax_authority = [
("Local Tax Authority", "Payroll Taxes", "Check", 0.00),
("Local Tax Authority", "Payroll Taxes", "Check", 0.00, {
'address_line1': '18 Spooner Stravenue',
'city': 'Danbury',
'state': 'RI',
'country': 'United States',
'pincode': '07165'
}),
]

def create_test_data():
Expand Down Expand Up @@ -106,6 +154,7 @@ def create_bank_and_bank_account(settings):
doc.submit()

def create_suppliers(settings):
addresses = frappe._dict({})
for supplier in suppliers + tax_authority:
biz = frappe.new_doc("Supplier")
biz.supplier_name = supplier[0]
Expand All @@ -119,6 +168,35 @@ def create_suppliers(settings):
biz.default_price_list = "Standard Buying"
biz.save()

addr = frappe.new_doc('Address')
addr.address_title = f"{supplier[0]} - {supplier[4]['city']}"
addr.address_type = 'Billing'
addr.address_line1 = supplier[4]['address_line1']
addr.city = supplier[4]['city']
addr.state = supplier[4]['state']
addr.country = supplier[4]['country']
addr.pincode = supplier[4]['pincode']
addr.append('links', {
'link_doctype': 'Supplier',
'link_name': supplier[0]
})
addr.save()

addr = frappe.new_doc('Address')
addr.address_type = 'Billing'
addr.address_title = "HIJ Telecom - Burlingame"
addr.address_line1 = '167 Auto Terrace'
addr.city = 'Burlingame'
addr.state = "ME"
addr.country = "United States"
addr.pincode = '79749'
addr.append('links', {
'link_doctype': 'Supplier',
'link_name': 'HIJ Telecom, Inc'
})
addr.save()


def create_items(settings):
for supplier in suppliers + tax_authority:
item = frappe.new_doc("Item")
Expand Down Expand Up @@ -161,6 +239,22 @@ def create_invoices(settings):
})
pi.save()
pi.submit()

# two phone bills / test address splitting
pi = frappe.new_doc('Purchase Invoice')
pi.company = settings.company
pi.set_posting_time = 1
pi.posting_date = settings.day
pi.supplier = suppliers[4][0]
pi.append('items', {
'item_code': suppliers[4][1],
'rate': 122.50,
'qty': 1,
})
pi.supplier_address = "HIJ Telecom - Burlingame-Billing"
pi.save()
pi.submit()

# second month - unpaid
next_day = settings.day + datetime.timedelta(days=31)

Expand Down Expand Up @@ -191,6 +285,21 @@ def create_invoices(settings):
pi.save()
pi.submit()

# two phone bills / test address splitting
pi = frappe.new_doc('Purchase Invoice')
pi.company = settings.company
pi.set_posting_time = 1
pi.posting_date = settings.day
pi.supplier = suppliers[4][0]
pi.append('items', {
'item_code': suppliers[4][1],
'rate': 122.50,
'qty': 1,
})
pi.supplier_address = "HIJ Telecom - Burlingame-Billing"
pi.save()
pi.submit()


def config_expense_claim(settings):
try:
Expand Down

0 comments on commit b32f0c9

Please sign in to comment.