From 1d2a0b691e0f41d57ae35482bce3454afb15ade2 Mon Sep 17 00:00:00 2001 From: viralpatel15 Date: Mon, 1 Apr 2024 07:11:19 +0000 Subject: [PATCH 01/24] condition on button , only visible at docstatus = 1 --- .../check_run/doctype/check_run/check_run.js | 32 ++++ .../doctype/check_run/gen_sepa_xml.py | 161 ++++++++++++++++++ 2 files changed, 193 insertions(+) create mode 100644 check_run/check_run/doctype/check_run/gen_sepa_xml.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 d912994b..f72d917a 100644 --- a/check_run/check_run/doctype/check_run/check_run.js +++ b/check_run/check_run/doctype/check_run/check_run.js @@ -49,6 +49,9 @@ frappe.ui.form.on('Check Run', { permit_first_user(frm) get_defaults(frm) set_queries(frm) + if(frm.doc.docstatus == 1){ + gen_sepa_xml(frm) + } frappe.realtime.off('reload') frappe.realtime.on('reload', message => { frm.reload_doc() @@ -428,3 +431,32 @@ function check_settings(frm) { }) } } + +function gen_sepa_xml(frm){ + frm.add_custom_button("Download SEPA", ()=>{ + frappe.call({ + method:"check_run.check_run.doctype.check_run.gen_sepa_xml.gen_sepa_xml_file", + args:{ + data : frm.doc.transactions, + company : frm.doc.company, + pay_to_account : frm.doc.pay_to_account + }, + callback:function(r){ + downloadXML("payments.xml", r.message); + } + }) + }) +} + +function downloadXML(filename, content) { + var element = document.createElement('a'); + element.setAttribute('href', 'data:application/octet-stream;charset=utf-8,' + encodeURIComponent(content)); + element.setAttribute('download', filename); + + element.style.display = 'none'; + document.body.appendChild(element); + + element.click(); + + document.body.removeChild(element); + } \ No newline at end of file diff --git a/check_run/check_run/doctype/check_run/gen_sepa_xml.py b/check_run/check_run/doctype/check_run/gen_sepa_xml.py new file mode 100644 index 00000000..b18a85dd --- /dev/null +++ b/check_run/check_run/doctype/check_run/gen_sepa_xml.py @@ -0,0 +1,161 @@ +import frappe +import json +from frappe.utils import getdate +from frappe import throw, _ +from collections import defaultdict +import time +import html +from frappe.utils import flt, get_link_to_form, getdate, nowdate + +@frappe.whitelist() +def gen_sepa_xml_file(data, company, pay_to_account): + data = json.loads(data) + posting_date = getdate() + content = genrate_file_for_sepa(data, company, pay_to_account, posting_date) + return content + + +def genrate_file_for_sepa(payments, company, pay_to_account, posting_date): + # remove empty items in case there should be any (bigfix for issue #2) + content = make_line("") + content += make_line("") + content += make_line("") + content += make_line(" ") + content += make_line(" ") + content += make_line(" {0}".format(time.strftime("%Y%m%d%H%M%S"))) + content += make_line(" {0}".format(time.strftime("%Y-%m-%dT%H:%M:%S"))) + transaction_count = 0 + transaction_count_identifier = "" + content += make_line(" {0}".format(transaction_count_identifier)) + control_sum = 0.0 + control_sum_identifier = "" + content += make_line(" {0}".format(control_sum_identifier)) + content += make_line(" ") + content += make_line(" {0}".format(company)) + content += make_line(" ") + content += make_line(" ") + content += make_line(" ") + content += make_line(" 556036867100") + content += make_line(" ") + content += make_line(" BANK") + content += make_line(" ") + content += make_line(" ") + content += make_line(" ") + content += make_line(" ") + content += make_line(" ") + content += make_line(" ") + content += make_line(" ") + content += make_line(" {0}".format(payments[0].get('payment_entry'))) + content += make_line(" TRF") + content += make_line(" false") + content += make_line(" {0}".format(transaction_count_identifier)) + + content += make_line(" {0}".format(control_sum_identifier)) + content += make_line(" ") + content += make_line(" ") + content += make_line(" SEPA") + content += make_line(" ") + content += make_line(" ") + required_execution_date = posting_date + content += make_line(" {0}".format(required_execution_date)) + content += make_line(" ") + content += make_line(" {0}".format(company)) + content += make_line(" ") + content += make_line(" ") + content += make_line(" ") + content += make_line(" 55667755110004") + content += make_line(" ") + content += make_line(" BANK") + content += make_line(" ") + content += make_line(" ") + content += make_line(" ") + content += make_line(" ") + content += make_line(" SE") + content += make_line(" ") + content += make_line(" ") + content += make_line(" ") + iban = get_iban_number(company, pay_to_account) + content += make_line(" {0}".format(iban)) + content += make_line(" ") + content += make_line(" EUR") + content += make_line(" ") + content += make_line(" ") + content += make_line(" ") + content += make_line(" ") + content += make_line(" ") + content += make_line(" NOTPROVIDED") + content += make_line(" ") + content += make_line(" ") + content += make_line(" ") + content += make_line(" SLEV") + for payment in payments: + payment_record = frappe.get_doc('Payment Entry', payment.get('payment_entry')) + content += make_line(" ") + content += make_line(" ") + content += make_line(" {}".format(payment.get('payment_entry'))) + content += make_line(" {}".format(payment.get('payment_entry').replace('-',""))) + content += make_line(" ") + content += make_line(" ") + content += make_line(" {1:.2f}".format( + payment_record.paid_from_account_currency, + payment_record.paid_amount)) + content += make_line(" ") + content += make_line(" ") + content += make_line(" ") + if payment_record.party_type == "Employee": + name = frappe.get_value("Employee", payment_record.party, "employee_name") + if payment_record.party_type == "Supplier": + name = frappe.db.get_value("Supplier",payment_record.party,"supplier_name") + if '&' in name: + new_name = name.replace('& ','') + if new_name == name: + new_name = name.replace('&',' ') + name = new_name + content += make_line(" {0}".format(name)) + content += make_line(" ") + content += make_line(" ") + content += make_line(" ") + iban_code = get_party_iban_code(payment_record.party_type, payment_record.party) + content += make_line(" {0}".format(iban_code.strip() or "")) + content += make_line(" ") + content += make_line(" ") + content += make_line(" ") + sup_invoice_no = frappe.db.get_value("Purchase Invoice" , payment_record.references[0].reference_name , 'bill_no') + content += make_line(" {0}".format(sup_invoice_no if sup_invoice_no else "")) + content += make_line(" ") + content += make_line(" ") + transaction_count += 1 + control_sum += payment_record.paid_amount + content += make_line(" ") + content += make_line(" ") + content += make_line("") + content = content.replace(transaction_count_identifier, "{0}".format(transaction_count)) + content = content.replace(control_sum_identifier, "{:.2f}".format(control_sum)) + return content + +def get_company_name(payment_entry): + return frappe.get_value('Payment Entry', payment_entry, 'company') + +def make_line(line): + return line + "\r\n" + +def get_iban_number(company, pay_to_account): + bank_iban = frappe.db.sql(f""" + Select iban + From `tabBank Account` + Where is_company_account = 1 and account = '{pay_to_account}' and company = '{company}' + """,as_dict = 1) + if bank_iban: + return bank_iban[0].iban + return + +def get_party_iban_code(party_type, party): + party_iban = frappe.db.sql(f""" + Select iban + From `tabBank Account` + Where party_type = '{party_type}' and party = '{party}' + """,as_dict = 1) + + if party_iban: + return party_iban[0].iban + return \ No newline at end of file From 0097b12329df77cf9c8af6437576618017c1970c Mon Sep 17 00:00:00 2001 From: viral Date: Mon, 1 Apr 2024 16:07:30 +0000 Subject: [PATCH 02/24] change the title of payment info tag --- .../check_run/doctype/check_run/check_run.js | 45 +-- .../doctype/check_run/gen_sepa_xml.py | 301 ++++++++++-------- 2 files changed, 186 insertions(+), 160 deletions(-) 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 f72d917a..521365c6 100644 --- a/check_run/check_run/doctype/check_run/check_run.js +++ b/check_run/check_run/doctype/check_run/check_run.js @@ -49,7 +49,7 @@ frappe.ui.form.on('Check Run', { permit_first_user(frm) get_defaults(frm) set_queries(frm) - if(frm.doc.docstatus == 1){ + if (frm.doc.docstatus == 1) { gen_sepa_xml(frm) } frappe.realtime.off('reload') @@ -432,31 +432,32 @@ function check_settings(frm) { } } -function gen_sepa_xml(frm){ - frm.add_custom_button("Download SEPA", ()=>{ +function gen_sepa_xml(frm) { + frm.add_custom_button('Download SEPA', () => { frappe.call({ - method:"check_run.check_run.doctype.check_run.gen_sepa_xml.gen_sepa_xml_file", - args:{ - data : frm.doc.transactions, - company : frm.doc.company, - pay_to_account : frm.doc.pay_to_account + method: 'check_run.check_run.doctype.check_run.gen_sepa_xml.gen_sepa_xml_file', + args: { + data: frm.doc.transactions, + company: frm.doc.company, + pay_to_account: frm.doc.pay_to_account, + check_run: frm.doc.name, + }, + callback: function (r) { + downloadXML('payments.xml', r.message) }, - callback:function(r){ - downloadXML("payments.xml", r.message); - } }) }) } function downloadXML(filename, content) { - var element = document.createElement('a'); - element.setAttribute('href', 'data:application/octet-stream;charset=utf-8,' + encodeURIComponent(content)); - element.setAttribute('download', filename); - - element.style.display = 'none'; - document.body.appendChild(element); - - element.click(); - - document.body.removeChild(element); - } \ No newline at end of file + var element = document.createElement('a') + element.setAttribute('href', 'data:application/octet-stream;charset=utf-8,' + encodeURIComponent(content)) + element.setAttribute('download', filename) + + element.style.display = 'none' + document.body.appendChild(element) + + element.click() + + document.body.removeChild(element) +} diff --git a/check_run/check_run/doctype/check_run/gen_sepa_xml.py b/check_run/check_run/doctype/check_run/gen_sepa_xml.py index b18a85dd..40d0d8de 100644 --- a/check_run/check_run/doctype/check_run/gen_sepa_xml.py +++ b/check_run/check_run/doctype/check_run/gen_sepa_xml.py @@ -1,161 +1,186 @@ import frappe import json from frappe.utils import getdate -from frappe import throw, _ -from collections import defaultdict import time -import html -from frappe.utils import flt, get_link_to_form, getdate, nowdate + @frappe.whitelist() -def gen_sepa_xml_file(data, company, pay_to_account): - data = json.loads(data) - posting_date = getdate() - content = genrate_file_for_sepa(data, company, pay_to_account, posting_date) - return content +def gen_sepa_xml_file(data, company, pay_to_account, check_run): + data = json.loads(data) + posting_date = getdate() + content = genrate_file_for_sepa(data, company, pay_to_account, posting_date, check_run) + return content + + +def genrate_file_for_sepa(payments, company, pay_to_account, posting_date, check_run): + # remove empty items in case there should be any (bigfix for issue #2) + content = make_line("") + content += make_line("") + content += make_line( + "" + ) + content += make_line(" ") + content += make_line(" ") + content += make_line(" {}".format(time.strftime("%Y%m%d%H%M%S"))) + content += make_line(" {}".format(time.strftime("%Y-%m-%dT%H:%M:%S"))) + transaction_count = 0 + transaction_count_identifier = "" + content += make_line(f" {transaction_count_identifier}") + control_sum = 0.0 + control_sum_identifier = "" + content += make_line(f" {control_sum_identifier}") + content += make_line(" ") + content += make_line(f" {company}") + content += make_line(" ") + content += make_line(" ") + content += make_line(" ") + content += make_line(" 556036867100") + content += make_line(" ") + content += make_line(" BANK") + content += make_line(" ") + content += make_line(" ") + content += make_line(" ") + content += make_line(" ") + content += make_line(" ") + content += make_line(" ") + content += make_line(" ") + content += make_line(f" {check_run}") + content += make_line(" TRF") + content += make_line(" false") + content += make_line(f" {transaction_count_identifier}") + content += make_line(f" {control_sum_identifier}") + content += make_line(" ") + content += make_line(" ") + content += make_line(" SEPA") + content += make_line(" ") + content += make_line(" ") + required_execution_date = posting_date + content += make_line(f" {required_execution_date}") + content += make_line(" ") + content += make_line(f" {company}") + content += make_line(" ") + content += make_line(" ") + content += make_line(" ") + content += make_line(" 55667755110004") + content += make_line(" ") + content += make_line(" BANK") + content += make_line(" ") + content += make_line(" ") + content += make_line(" ") + content += make_line(" ") + content += make_line(" SE") + content += make_line(" ") + content += make_line(" ") + content += make_line(" ") + iban = get_iban_number(company, pay_to_account) + content += make_line(f" {iban}") + content += make_line(" ") + content += make_line(" EUR") + content += make_line(" ") + content += make_line(" ") + content += make_line( + " " + ) + content += make_line(" ") + content += make_line(" ") + content += make_line(" NOTPROVIDED") + content += make_line(" ") + content += make_line(" ") + content += make_line(" ") + content += make_line(" SLEV") + for payment in payments: + payment_record = frappe.get_doc("Payment Entry", payment.get("payment_entry")) + content += make_line(" ") + content += make_line(" ") + content += make_line( + " {}".format(payment.get("payment_entry")) + ) + content += make_line( + " {}".format( + payment.get("payment_entry").replace("-", "") + ) + ) + content += make_line(" ") + content += make_line(" ") + content += make_line( + ' {:.2f}'.format( + payment_record.paid_from_account_currency, payment_record.paid_amount + ) + ) + content += make_line(" ") + content += make_line( + " " + ) + content += make_line(" ") + if payment_record.party_type == "Employee": + name = frappe.get_value("Employee", payment_record.party, "employee_name") + if payment_record.party_type == "Supplier": + name = frappe.db.get_value("Supplier", payment_record.party, "supplier_name") + if "&" in name: + new_name = name.replace("& ", "") + if new_name == name: + new_name = name.replace("&", " ") + name = new_name + content += make_line(f" {name}") + content += make_line(" ") + content += make_line(" ") + content += make_line(" ") + iban_code = get_party_iban_code(payment_record.party_type, payment_record.party) + content += make_line(" {}".format(iban_code.strip() or "")) + content += make_line(" ") + content += make_line(" ") + content += make_line(" ") + sup_invoice_no = frappe.db.get_value( + "Purchase Invoice", payment_record.references[0].reference_name, "bill_no" + ) + content += make_line( + " {}".format(sup_invoice_no if sup_invoice_no else "") + ) + content += make_line(" ") + content += make_line(" ") + transaction_count += 1 + control_sum += payment_record.paid_amount + content += make_line(" ") + content += make_line(" ") + content += make_line("") + content = content.replace(transaction_count_identifier, f"{transaction_count}") + content = content.replace(control_sum_identifier, f"{control_sum:.2f}") + return content -def genrate_file_for_sepa(payments, company, pay_to_account, posting_date): - # remove empty items in case there should be any (bigfix for issue #2) - content = make_line("") - content += make_line("") - content += make_line("") - content += make_line(" ") - content += make_line(" ") - content += make_line(" {0}".format(time.strftime("%Y%m%d%H%M%S"))) - content += make_line(" {0}".format(time.strftime("%Y-%m-%dT%H:%M:%S"))) - transaction_count = 0 - transaction_count_identifier = "" - content += make_line(" {0}".format(transaction_count_identifier)) - control_sum = 0.0 - control_sum_identifier = "" - content += make_line(" {0}".format(control_sum_identifier)) - content += make_line(" ") - content += make_line(" {0}".format(company)) - content += make_line(" ") - content += make_line(" ") - content += make_line(" ") - content += make_line(" 556036867100") - content += make_line(" ") - content += make_line(" BANK") - content += make_line(" ") - content += make_line(" ") - content += make_line(" ") - content += make_line(" ") - content += make_line(" ") - content += make_line(" ") - content += make_line(" ") - content += make_line(" {0}".format(payments[0].get('payment_entry'))) - content += make_line(" TRF") - content += make_line(" false") - content += make_line(" {0}".format(transaction_count_identifier)) - - content += make_line(" {0}".format(control_sum_identifier)) - content += make_line(" ") - content += make_line(" ") - content += make_line(" SEPA") - content += make_line(" ") - content += make_line(" ") - required_execution_date = posting_date - content += make_line(" {0}".format(required_execution_date)) - content += make_line(" ") - content += make_line(" {0}".format(company)) - content += make_line(" ") - content += make_line(" ") - content += make_line(" ") - content += make_line(" 55667755110004") - content += make_line(" ") - content += make_line(" BANK") - content += make_line(" ") - content += make_line(" ") - content += make_line(" ") - content += make_line(" ") - content += make_line(" SE") - content += make_line(" ") - content += make_line(" ") - content += make_line(" ") - iban = get_iban_number(company, pay_to_account) - content += make_line(" {0}".format(iban)) - content += make_line(" ") - content += make_line(" EUR") - content += make_line(" ") - content += make_line(" ") - content += make_line(" ") - content += make_line(" ") - content += make_line(" ") - content += make_line(" NOTPROVIDED") - content += make_line(" ") - content += make_line(" ") - content += make_line(" ") - content += make_line(" SLEV") - for payment in payments: - payment_record = frappe.get_doc('Payment Entry', payment.get('payment_entry')) - content += make_line(" ") - content += make_line(" ") - content += make_line(" {}".format(payment.get('payment_entry'))) - content += make_line(" {}".format(payment.get('payment_entry').replace('-',""))) - content += make_line(" ") - content += make_line(" ") - content += make_line(" {1:.2f}".format( - payment_record.paid_from_account_currency, - payment_record.paid_amount)) - content += make_line(" ") - content += make_line(" ") - content += make_line(" ") - if payment_record.party_type == "Employee": - name = frappe.get_value("Employee", payment_record.party, "employee_name") - if payment_record.party_type == "Supplier": - name = frappe.db.get_value("Supplier",payment_record.party,"supplier_name") - if '&' in name: - new_name = name.replace('& ','') - if new_name == name: - new_name = name.replace('&',' ') - name = new_name - content += make_line(" {0}".format(name)) - content += make_line(" ") - content += make_line(" ") - content += make_line(" ") - iban_code = get_party_iban_code(payment_record.party_type, payment_record.party) - content += make_line(" {0}".format(iban_code.strip() or "")) - content += make_line(" ") - content += make_line(" ") - content += make_line(" ") - sup_invoice_no = frappe.db.get_value("Purchase Invoice" , payment_record.references[0].reference_name , 'bill_no') - content += make_line(" {0}".format(sup_invoice_no if sup_invoice_no else "")) - content += make_line(" ") - content += make_line(" ") - transaction_count += 1 - control_sum += payment_record.paid_amount - content += make_line(" ") - content += make_line(" ") - content += make_line("") - content = content.replace(transaction_count_identifier, "{0}".format(transaction_count)) - content = content.replace(control_sum_identifier, "{:.2f}".format(control_sum)) - return content def get_company_name(payment_entry): - return frappe.get_value('Payment Entry', payment_entry, 'company') + return frappe.get_value("Payment Entry", payment_entry, "company") + def make_line(line): - return line + "\r\n" + return line + "\r\n" + def get_iban_number(company, pay_to_account): - bank_iban = frappe.db.sql(f""" + bank_iban = frappe.db.sql( + f""" Select iban From `tabBank Account` Where is_company_account = 1 and account = '{pay_to_account}' and company = '{company}' - """,as_dict = 1) - if bank_iban: - return bank_iban[0].iban - return + """, + as_dict=1, + ) + if bank_iban: + return bank_iban[0].iban + return + def get_party_iban_code(party_type, party): - party_iban = frappe.db.sql(f""" + party_iban = frappe.db.sql( + f""" Select iban From `tabBank Account` Where party_type = '{party_type}' and party = '{party}' - """,as_dict = 1) + """, + as_dict=1, + ) - if party_iban: - return party_iban[0].iban - return \ No newline at end of file + if party_iban: + return party_iban[0].iban + return From 3d9f2124db5fdcc3b825299c8d38089777b6dfe8 Mon Sep 17 00:00:00 2001 From: viral Date: Wed, 10 Apr 2024 12:17:30 +0000 Subject: [PATCH 03/24] changes in sepa xml file --- .../check_run/doctype/check_run/check_run.js | 9 ++--- .../doctype/check_run/gen_sepa_xml.py | 33 ++++++++++++------- 2 files changed, 27 insertions(+), 15 deletions(-) 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 521365c6..ff896e7f 100644 --- a/check_run/check_run/doctype/check_run/check_run.js +++ b/check_run/check_run/doctype/check_run/check_run.js @@ -437,10 +437,11 @@ function gen_sepa_xml(frm) { frappe.call({ method: 'check_run.check_run.doctype.check_run.gen_sepa_xml.gen_sepa_xml_file', args: { - data: frm.doc.transactions, - company: frm.doc.company, - pay_to_account: frm.doc.pay_to_account, - check_run: frm.doc.name, + doc : frm.doc + // data: frm.doc.transactions, + // company: frm.doc.company, + // pay_to_account: frm.doc.pay_to_account, + // check_run: frm.doc.name, }, callback: function (r) { downloadXML('payments.xml', r.message) diff --git a/check_run/check_run/doctype/check_run/gen_sepa_xml.py b/check_run/check_run/doctype/check_run/gen_sepa_xml.py index 40d0d8de..dc6c737c 100644 --- a/check_run/check_run/doctype/check_run/gen_sepa_xml.py +++ b/check_run/check_run/doctype/check_run/gen_sepa_xml.py @@ -5,21 +5,25 @@ @frappe.whitelist() -def gen_sepa_xml_file(data, company, pay_to_account, check_run): - data = json.loads(data) +def gen_sepa_xml_file(doc): + doc = frappe.parse_json(doc) + payments = frappe.parse_json(doc.transactions) posting_date = getdate() - content = genrate_file_for_sepa(data, company, pay_to_account, posting_date, check_run) + content = genrate_file_for_sepa(payments, doc, posting_date) return content -def genrate_file_for_sepa(payments, company, pay_to_account, posting_date, check_run): - # remove empty items in case there should be any (bigfix for issue #2) +def genrate_file_for_sepa(payments, doc, posting_date): + #Message Root content = make_line("") content += make_line("") content += make_line( "" ) content += make_line(" ") + + + # Group Header content += make_line(" ") content += make_line(" {}".format(time.strftime("%Y%m%d%H%M%S"))) content += make_line(" {}".format(time.strftime("%Y-%m-%dT%H:%M:%S"))) @@ -30,7 +34,7 @@ def genrate_file_for_sepa(payments, company, pay_to_account, posting_date, check control_sum_identifier = "" content += make_line(f" {control_sum_identifier}") content += make_line(" ") - content += make_line(f" {company}") + content += make_line(f" {doc.company}") content += make_line(" ") content += make_line(" ") content += make_line(" ") @@ -43,8 +47,11 @@ def genrate_file_for_sepa(payments, company, pay_to_account, posting_date, check content += make_line(" ") content += make_line(" ") content += make_line(" ") + + + #Payment Information Elements content += make_line(" ") - content += make_line(f" {check_run}") + content += make_line(f" {doc.name}") content += make_line(" TRF") content += make_line(" false") content += make_line(f" {transaction_count_identifier}") @@ -58,7 +65,7 @@ def genrate_file_for_sepa(payments, company, pay_to_account, posting_date, check required_execution_date = posting_date content += make_line(f" {required_execution_date}") content += make_line(" ") - content += make_line(f" {company}") + content += make_line(f" {doc.company}") content += make_line(" ") content += make_line(" ") content += make_line(" ") @@ -73,7 +80,7 @@ def genrate_file_for_sepa(payments, company, pay_to_account, posting_date, check content += make_line(" ") content += make_line(" ") content += make_line(" ") - iban = get_iban_number(company, pay_to_account) + iban = get_iban_number(company = doc.company, pay_to_account = doc.pay_to_account) content += make_line(f" {iban}") content += make_line(" ") content += make_line(" EUR") @@ -126,8 +133,10 @@ def genrate_file_for_sepa(payments, company, pay_to_account, posting_date, check content += make_line(" ") content += make_line(" ") content += make_line(" ") + iban_code = get_party_iban_code(payment_record.party_type, payment_record.party) - content += make_line(" {}".format(iban_code.strip() or "")) + + content += make_line(" {}".format(iban_code.strip() if iban_code else "")) content += make_line(" ") content += make_line(" ") content += make_line(" ") @@ -142,6 +151,8 @@ def genrate_file_for_sepa(payments, company, pay_to_account, posting_date, check transaction_count += 1 control_sum += payment_record.paid_amount content += make_line(" ") + + #Finished tags content += make_line(" ") content += make_line("") content = content.replace(transaction_count_identifier, f"{transaction_count}") @@ -159,7 +170,7 @@ def make_line(line): def get_iban_number(company, pay_to_account): bank_iban = frappe.db.sql( - f""" + f""" Select iban From `tabBank Account` Where is_company_account = 1 and account = '{pay_to_account}' and company = '{company}' From 5115955ba239e2edf5c1f0d4c0cf33f5b630677b Mon Sep 17 00:00:00 2001 From: viral Date: Wed, 10 Apr 2024 12:19:46 +0000 Subject: [PATCH 04/24] changes in sepa xml file --- .../check_run/doctype/check_run/check_run.js | 2 +- .../check_run/doctype/check_run/gen_sepa_xml.py | 17 ++++++++--------- 2 files changed, 9 insertions(+), 10 deletions(-) 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 ff896e7f..103443fc 100644 --- a/check_run/check_run/doctype/check_run/check_run.js +++ b/check_run/check_run/doctype/check_run/check_run.js @@ -437,7 +437,7 @@ function gen_sepa_xml(frm) { frappe.call({ method: 'check_run.check_run.doctype.check_run.gen_sepa_xml.gen_sepa_xml_file', args: { - doc : frm.doc + doc: frm.doc, // data: frm.doc.transactions, // company: frm.doc.company, // pay_to_account: frm.doc.pay_to_account, diff --git a/check_run/check_run/doctype/check_run/gen_sepa_xml.py b/check_run/check_run/doctype/check_run/gen_sepa_xml.py index dc6c737c..e35ef122 100644 --- a/check_run/check_run/doctype/check_run/gen_sepa_xml.py +++ b/check_run/check_run/doctype/check_run/gen_sepa_xml.py @@ -1,5 +1,4 @@ import frappe -import json from frappe.utils import getdate import time @@ -14,7 +13,7 @@ def gen_sepa_xml_file(doc): def genrate_file_for_sepa(payments, doc, posting_date): - #Message Root + # Message Root content = make_line("") content += make_line("") content += make_line( @@ -22,7 +21,6 @@ def genrate_file_for_sepa(payments, doc, posting_date): ) content += make_line(" ") - # Group Header content += make_line(" ") content += make_line(" {}".format(time.strftime("%Y%m%d%H%M%S"))) @@ -48,8 +46,7 @@ def genrate_file_for_sepa(payments, doc, posting_date): content += make_line(" ") content += make_line(" ") - - #Payment Information Elements + # Payment Information Elements content += make_line(" ") content += make_line(f" {doc.name}") content += make_line(" TRF") @@ -80,7 +77,7 @@ def genrate_file_for_sepa(payments, doc, posting_date): content += make_line(" ") content += make_line(" ") content += make_line(" ") - iban = get_iban_number(company = doc.company, pay_to_account = doc.pay_to_account) + iban = get_iban_number(company=doc.company, pay_to_account=doc.pay_to_account) content += make_line(f" {iban}") content += make_line(" ") content += make_line(" EUR") @@ -136,7 +133,9 @@ def genrate_file_for_sepa(payments, doc, posting_date): iban_code = get_party_iban_code(payment_record.party_type, payment_record.party) - content += make_line(" {}".format(iban_code.strip() if iban_code else "")) + content += make_line( + " {}".format(iban_code.strip() if iban_code else "") + ) content += make_line(" ") content += make_line(" ") content += make_line(" ") @@ -152,7 +151,7 @@ def genrate_file_for_sepa(payments, doc, posting_date): control_sum += payment_record.paid_amount content += make_line(" ") - #Finished tags + # Finished tags content += make_line(" ") content += make_line("") content = content.replace(transaction_count_identifier, f"{transaction_count}") @@ -170,7 +169,7 @@ def make_line(line): def get_iban_number(company, pay_to_account): bank_iban = frappe.db.sql( - f""" + f""" Select iban From `tabBank Account` Where is_company_account = 1 and account = '{pay_to_account}' and company = '{company}' From cae9be21f45a8a82b50ec006006685aa5b8d193d Mon Sep 17 00:00:00 2001 From: viral Date: Wed, 10 Apr 2024 13:15:41 +0000 Subject: [PATCH 05/24] validation if iban code is not available --- .../doctype/check_run/gen_sepa_xml.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/check_run/check_run/doctype/check_run/gen_sepa_xml.py b/check_run/check_run/doctype/check_run/gen_sepa_xml.py index e35ef122..0eed717f 100644 --- a/check_run/check_run/doctype/check_run/gen_sepa_xml.py +++ b/check_run/check_run/doctype/check_run/gen_sepa_xml.py @@ -1,5 +1,5 @@ import frappe -from frappe.utils import getdate +from frappe.utils import getdate, get_link_to_form import time @@ -139,11 +139,15 @@ def genrate_file_for_sepa(payments, doc, posting_date): content += make_line(" ") content += make_line(" ") content += make_line(" ") - sup_invoice_no = frappe.db.get_value( - "Purchase Invoice", payment_record.references[0].reference_name, "bill_no" - ) + sup_invoice_no = [ + frappe.db.get_value("Purchase Invoice", row.reference_name, "bill_no") + for row in payment_record.references + ] + content += make_line( - " {}".format(sup_invoice_no if sup_invoice_no else "") + " {}".format( + ", ".join(sup_invoice_no) if sup_invoice_no else "" + ) ) content += make_line(" ") content += make_line(" ") @@ -193,4 +197,7 @@ def get_party_iban_code(party_type, party): if party_iban: return party_iban[0].iban - return + else: + frappe.throw( + frappe._(f"Iban Code is not available for {party_type} {get_link_to_form(party_type, party)}") + ) From 779c32e22c368dd36bb9156f1b3af4348b69cac6 Mon Sep 17 00:00:00 2001 From: viral Date: Mon, 15 Apr 2024 11:54:32 +0000 Subject: [PATCH 06/24] Iban No validation and added in xml file --- .../doctype/check_run/gen_sepa_xml.py | 28 +- .../check_run_settings.json | 559 +++++++++--------- 2 files changed, 310 insertions(+), 277 deletions(-) diff --git a/check_run/check_run/doctype/check_run/gen_sepa_xml.py b/check_run/check_run/doctype/check_run/gen_sepa_xml.py index 0eed717f..2a2a202d 100644 --- a/check_run/check_run/doctype/check_run/gen_sepa_xml.py +++ b/check_run/check_run/doctype/check_run/gen_sepa_xml.py @@ -77,7 +77,7 @@ def genrate_file_for_sepa(payments, doc, posting_date): content += make_line(" ") content += make_line(" ") content += make_line(" ") - iban = get_iban_number(company=doc.company, pay_to_account=doc.pay_to_account) + iban = get_iban_number(doc.company, doc.bank_account, doc.pay_to_account) content += make_line(f" {iban}") content += make_line(" ") content += make_line(" EUR") @@ -146,7 +146,7 @@ def genrate_file_for_sepa(payments, doc, posting_date): content += make_line( " {}".format( - ", ".join(sup_invoice_no) if sup_invoice_no else "" + ", ".join(sup_invoice_no) if sup_invoice_no[0] else "" ) ) content += make_line(" ") @@ -171,18 +171,26 @@ def make_line(line): return line + "\r\n" -def get_iban_number(company, pay_to_account): +def get_iban_number(company, bank_account, pay_to_account): bank_iban = frappe.db.sql( - f""" - Select iban - From `tabBank Account` - Where is_company_account = 1 and account = '{pay_to_account}' and company = '{company}' - """, + f""" + Select ba.iban + From `tabCheck Run Settings` as crs + Left Join `tabBank Account` as ba ON ba.name = crs.company_bank_account + where crs.company = '{company}' and crs.bank_account = '{bank_account}' and crs.pay_to_account = '{pay_to_account}' + """, as_dict=1, ) + if bank_iban: - return bank_iban[0].iban - return + if bank_iban[0].iban: + return bank_iban[0].iban + else: + frappe.throw( + frappe._( + f"Iban no is missing in bank account {get_link_to_form('Bank Account', bank_account)}" + ) + ) def get_party_iban_code(party_type, party): 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 d1243c27..0bdeddbc 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 @@ -1,268 +1,293 @@ { - "actions": [], - "autoname": "format:ACC-CRS-{bank_account}-{pay_to_account}", - "creation": "2022-08-22 14:43:43.533105", - "doctype": "DocType", - "editable_grid": 1, - "engine": "InnoDB", - "field_order": [ - "company", - "bank_account", - "column_break_3", - "pay_to_account", - "print_format", - "section_break_4", - "include_purchase_invoices", - "include_journal_entries", - "include_expense_claims", - "pre_check_overdue_items", - "allow_cancellation", - "cascade_cancellation", - "validate_unique_check_number", - "column_break_9", - "number_of_invoices_per_voucher", - "split_by_address", - "automatically_release_on_hold_invoices", - "file_preview_threshold", - "default_modes_of_payment_section_section", - "purchase_invoice", - "journal_entry", - "column_break_21", - "expense_claim", - "ach_settings_section", - "ach_file_extension", - "ach_service_class_code", - "ach_standard_class_code", - "ach_description", - "column_break_27", - "immediate_origin", - "company_discretionary_data", - "custom_post_processing_hook" - ], - "fields": [ - { - "fieldname": "company", - "fieldtype": "Link", - "label": "Company", - "options": "Company" - }, - { - "fieldname": "bank_account", - "fieldtype": "Link", - "label": "Bank Account", - "options": "Bank Account" - }, - { - "fieldname": "section_break_4", - "fieldtype": "Section Break" - }, - { - "default": "1", - "fieldname": "include_purchase_invoices", - "fieldtype": "Check", - "label": "Include Purchase Invoices" - }, - { - "default": "1", - "fieldname": "include_journal_entries", - "fieldtype": "Check", - "label": "Include Journal Entries " - }, - { - "default": "1", - "fieldname": "include_expense_claims", - "fieldtype": "Check", - "label": "Include Expense Claims" - }, - { - "default": "0", - "description": "Payment Entries will be unlinked when Check Run is cancelled", - "fieldname": "allow_cancellation", - "fieldtype": "Check", - "label": "Allow Cancellation" - }, - { - "fieldname": "column_break_9", - "fieldtype": "Column Break" - }, - { - "default": "ach", - "description": "Common file extensions are 'ach', 'txt' and 'dat'. Your bank may require one of these.", - "fieldname": "ach_file_extension", - "fieldtype": "Data", - "label": "ACH File Extension" - }, - { - "default": "0", - "description": "Pre-Check all payables that have a due date greater than the Check Run's posting date", - "fieldname": "pre_check_overdue_items", - "fieldtype": "Check", - "label": "Pre-Check Overdue Items" - }, - { - "default": "0", - "description": "When a Check Run is cancelled, all Payment Entries linked to it will also be cancelled. This is not recommended.", - "fieldname": "cascade_cancellation", - "fieldtype": "Check", - "label": "Cascade Cancellation" - }, - { - "description": "Defaults to 5 if no value is provided", - "fieldname": "number_of_invoices_per_voucher", - "fieldtype": "Int", - "label": "Number of Invoices per Voucher", - "non_negative": 1 - }, - { - "fieldname": "column_break_3", - "fieldtype": "Column Break" - }, - { - "fieldname": "pay_to_account", - "fieldtype": "Link", - "label": "Payable Account", - "options": "Account" - }, - { - "fieldname": "ach_service_class_code", - "fieldtype": "Select", - "label": "ACH Service Class Code", - "options": "200\n220\n225" - }, - { - "description": "PPD is only supported Entry format at this time", - "fieldname": "ach_standard_class_code", - "fieldtype": "Select", - "label": "ACH Standard Class Code", - "options": "PPD" - }, - { - "fieldname": "ach_description", - "fieldtype": "Data", - "label": "ACH Description", - "length": 10 - }, - { - "fieldname": "print_format", - "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" - }, - { - "fieldname": "column_break_21", - "fieldtype": "Column Break" - }, - { - "default": "0", - "fieldname": "automatically_release_on_hold_invoices", - "fieldtype": "Check", - "label": "Automatically Release On Hold Invoices" - }, - { - "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 - }, - { - "fieldname": "default_modes_of_payment_section_section", - "fieldtype": "Section Break", - "label": "Default Modes of Payment Section" - }, - { - "fieldname": "purchase_invoice", - "fieldtype": "Link", - "label": "Purchase Invoice", - "options": "Mode of Payment" - }, - { - "fieldname": "journal_entry", - "fieldtype": "Link", - "label": "Journal Entry", - "options": "Mode of Payment" - }, - { - "fieldname": "expense_claim", - "fieldtype": "Link", - "label": "Expense Claim", - "options": "Mode of Payment" - }, - { - "fieldname": "column_break_27", - "fieldtype": "Column Break" - }, - { - "default": "1000", - "description": "File preview is enabled up to this number of transactions", - "fieldname": "file_preview_threshold", - "fieldtype": "Int", - "label": "File Preview Threshold" - }, - { - "default": "0", - "fieldname": "validate_unique_check_number", - "fieldtype": "Check", - "label": "Validate Unique Check Number" - } - ], - "links": [], - "modified": "2024-01-11 10:49:46.062226", - "modified_by": "Administrator", - "module": "Check Run", - "name": "Check Run Settings", - "naming_rule": "Expression", - "owner": "Administrator", - "permissions": [ - { - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "print": 1, - "read": 1, - "report": 1, - "role": "System Manager", - "share": 1, - "write": 1 - }, - { - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "print": 1, - "read": 1, - "report": 1, - "role": "Accounts Manager", - "share": 1, - "write": 1 - } - ], - "quick_entry": 1, - "sort_field": "modified", - "sort_order": "DESC", - "states": [], - "track_changes": 1 -} + "actions": [], + "autoname": "format:ACC-CRS-{bank_account}-{pay_to_account}", + "creation": "2022-08-22 14:43:43.533105", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "company", + "bank_account", + "column_break_3", + "pay_to_account", + "print_format", + "section_break_4", + "include_purchase_invoices", + "include_journal_entries", + "include_expense_claims", + "pre_check_overdue_items", + "allow_cancellation", + "cascade_cancellation", + "validate_unique_check_number", + "column_break_9", + "number_of_invoices_per_voucher", + "split_by_address", + "automatically_release_on_hold_invoices", + "file_preview_threshold", + "default_modes_of_payment_section_section", + "purchase_invoice", + "journal_entry", + "column_break_21", + "expense_claim", + "ach_settings_section", + "ach_file_extension", + "ach_service_class_code", + "ach_standard_class_code", + "ach_description", + "column_break_27", + "immediate_origin", + "company_discretionary_data", + "custom_post_processing_hook", + "sepa_payment_settings_section", + "company_bank_account", + "initiating_party_org_id", + "debtor_org_id" + ], + "fields": [ + { + "fieldname": "company", + "fieldtype": "Link", + "label": "Company", + "options": "Company" + }, + { + "fieldname": "bank_account", + "fieldtype": "Link", + "label": "Bank Account", + "options": "Bank Account" + }, + { + "fieldname": "section_break_4", + "fieldtype": "Section Break" + }, + { + "default": "1", + "fieldname": "include_purchase_invoices", + "fieldtype": "Check", + "label": "Include Purchase Invoices" + }, + { + "default": "1", + "fieldname": "include_journal_entries", + "fieldtype": "Check", + "label": "Include Journal Entries " + }, + { + "default": "1", + "fieldname": "include_expense_claims", + "fieldtype": "Check", + "label": "Include Expense Claims" + }, + { + "default": "0", + "description": "Payment Entries will be unlinked when Check Run is cancelled", + "fieldname": "allow_cancellation", + "fieldtype": "Check", + "label": "Allow Cancellation" + }, + { + "fieldname": "column_break_9", + "fieldtype": "Column Break" + }, + { + "default": "ach", + "description": "Common file extensions are 'ach', 'txt' and 'dat'. Your bank may require one of these.", + "fieldname": "ach_file_extension", + "fieldtype": "Data", + "label": "ACH File Extension" + }, + { + "default": "0", + "description": "Pre-Check all payables that have a due date greater than the Check Run's posting date", + "fieldname": "pre_check_overdue_items", + "fieldtype": "Check", + "label": "Pre-Check Overdue Items" + }, + { + "default": "0", + "description": "When a Check Run is cancelled, all Payment Entries linked to it will also be cancelled. This is not recommended.", + "fieldname": "cascade_cancellation", + "fieldtype": "Check", + "label": "Cascade Cancellation" + }, + { + "description": "Defaults to 5 if no value is provided", + "fieldname": "number_of_invoices_per_voucher", + "fieldtype": "Int", + "label": "Number of Invoices per Voucher", + "non_negative": 1 + }, + { + "fieldname": "column_break_3", + "fieldtype": "Column Break" + }, + { + "fieldname": "pay_to_account", + "fieldtype": "Link", + "label": "Payable Account", + "options": "Account" + }, + { + "fieldname": "ach_service_class_code", + "fieldtype": "Select", + "label": "ACH Service Class Code", + "options": "200\n220\n225" + }, + { + "description": "PPD is only supported Entry format at this time", + "fieldname": "ach_standard_class_code", + "fieldtype": "Select", + "label": "ACH Standard Class Code", + "options": "PPD" + }, + { + "fieldname": "ach_description", + "fieldtype": "Data", + "label": "ACH Description", + "length": 10 + }, + { + "fieldname": "print_format", + "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" + }, + { + "fieldname": "column_break_21", + "fieldtype": "Column Break" + }, + { + "default": "0", + "fieldname": "automatically_release_on_hold_invoices", + "fieldtype": "Check", + "label": "Automatically Release On Hold Invoices" + }, + { + "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 + }, + { + "fieldname": "default_modes_of_payment_section_section", + "fieldtype": "Section Break", + "label": "Default Modes of Payment Section" + }, + { + "fieldname": "purchase_invoice", + "fieldtype": "Link", + "label": "Purchase Invoice", + "options": "Mode of Payment" + }, + { + "fieldname": "journal_entry", + "fieldtype": "Link", + "label": "Journal Entry", + "options": "Mode of Payment" + }, + { + "fieldname": "expense_claim", + "fieldtype": "Link", + "label": "Expense Claim", + "options": "Mode of Payment" + }, + { + "fieldname": "column_break_27", + "fieldtype": "Column Break" + }, + { + "default": "1000", + "description": "File preview is enabled up to this number of transactions", + "fieldname": "file_preview_threshold", + "fieldtype": "Int", + "label": "File Preview Threshold" + }, + { + "default": "0", + "fieldname": "validate_unique_check_number", + "fieldtype": "Check", + "label": "Validate Unique Check Number" + }, + { + "fieldname": "sepa_payment_settings_section", + "fieldtype": "Section Break", + "label": "SEPA Payment Settings" + }, + { + "fieldname": "company_bank_account", + "fieldtype": "Link", + "label": "Company Bank Account(Currency=EUR)", + "options": "Bank Account" + }, + { + "fieldname": "initiating_party_org_id", + "fieldtype": "Data", + "label": "Initiating Party Org Id" + }, + { + "fieldname": "debtor_org_id", + "fieldtype": "Data", + "label": "Debtor Org Id" + } + ], + "links": [], + "modified": "2024-04-15 07:11:53.018423", + "modified_by": "Administrator", + "module": "Check Run", + "name": "Check Run Settings", + "naming_rule": "Expression", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, + "write": 1 + }, + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Accounts Manager", + "share": 1, + "write": 1 + } + ], + "quick_entry": 1, + "sort_field": "modified", + "sort_order": "DESC", + "states": [], + "track_changes": 1 +} \ No newline at end of file From ab4d224c22c1dead011d050ed67fd1b0afed79dd Mon Sep 17 00:00:00 2001 From: viral Date: Mon, 15 Apr 2024 11:58:59 +0000 Subject: [PATCH 07/24] Iban No validation and added in xml file --- .../doctype/check_run/gen_sepa_xml.py | 25 ++++++------------- .../check_run_settings.json | 9 +------ 2 files changed, 8 insertions(+), 26 deletions(-) diff --git a/check_run/check_run/doctype/check_run/gen_sepa_xml.py b/check_run/check_run/doctype/check_run/gen_sepa_xml.py index 2a2a202d..d59e34a9 100644 --- a/check_run/check_run/doctype/check_run/gen_sepa_xml.py +++ b/check_run/check_run/doctype/check_run/gen_sepa_xml.py @@ -171,26 +171,15 @@ def make_line(line): return line + "\r\n" -def get_iban_number(company, bank_account, pay_to_account): - bank_iban = frappe.db.sql( - f""" - Select ba.iban - From `tabCheck Run Settings` as crs - Left Join `tabBank Account` as ba ON ba.name = crs.company_bank_account - where crs.company = '{company}' and crs.bank_account = '{bank_account}' and crs.pay_to_account = '{pay_to_account}' - """, - as_dict=1, - ) +def get_iban_number(company, bank_account): + bank_iban = frappe.db.get_value("Bank Account", bank_account, "iban") if bank_iban: - if bank_iban[0].iban: - return bank_iban[0].iban - else: - frappe.throw( - frappe._( - f"Iban no is missing in bank account {get_link_to_form('Bank Account', bank_account)}" - ) - ) + return bank_iban + else: + frappe.throw( + frappe._(f"Iban no is missing in bank account {get_link_to_form('Bank Account', bank_account)}") + ) def get_party_iban_code(party_type, party): 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 0bdeddbc..195c1dcd 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 @@ -39,7 +39,6 @@ "company_discretionary_data", "custom_post_processing_hook", "sepa_payment_settings_section", - "company_bank_account", "initiating_party_org_id", "debtor_org_id" ], @@ -235,12 +234,6 @@ "fieldtype": "Section Break", "label": "SEPA Payment Settings" }, - { - "fieldname": "company_bank_account", - "fieldtype": "Link", - "label": "Company Bank Account(Currency=EUR)", - "options": "Bank Account" - }, { "fieldname": "initiating_party_org_id", "fieldtype": "Data", @@ -253,7 +246,7 @@ } ], "links": [], - "modified": "2024-04-15 07:11:53.018423", + "modified": "2024-04-15 07:57:00.135495", "modified_by": "Administrator", "module": "Check Run", "name": "Check Run Settings", From bbe79c09ebbeb5aa28a17b688cf215d21ad3fa60 Mon Sep 17 00:00:00 2001 From: viral Date: Mon, 15 Apr 2024 12:59:41 +0000 Subject: [PATCH 08/24] set the Organisation id check run setting --- .../doctype/check_run/gen_sepa_xml.py | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/check_run/check_run/doctype/check_run/gen_sepa_xml.py b/check_run/check_run/doctype/check_run/gen_sepa_xml.py index d59e34a9..b629d2b4 100644 --- a/check_run/check_run/doctype/check_run/gen_sepa_xml.py +++ b/check_run/check_run/doctype/check_run/gen_sepa_xml.py @@ -34,9 +34,15 @@ def genrate_file_for_sepa(payments, doc, posting_date): content += make_line(" ") content += make_line(f" {doc.company}") content += make_line(" ") + + orgid = get_party_orgid(doc.company, doc.bank_account, doc.pay_to_account) + + initiating_party_org_id = orgid.get("initiating_party_org_id", None) + if not initiating_party_org_id: + frappe.throw(frappe._("Please specify Initiating Party OrgID in check run settings")) content += make_line(" ") content += make_line(" ") - content += make_line(" 556036867100") + content += make_line(f" {initiating_party_org_id}") content += make_line(" ") content += make_line(" BANK") content += make_line(" ") @@ -66,7 +72,10 @@ def genrate_file_for_sepa(payments, doc, posting_date): content += make_line(" ") content += make_line(" ") content += make_line(" ") - content += make_line(" 55667755110004") + debtor_org_id = orgid.get("initiating_party_org_id", None) + if not debtor_org_id: + frappe.throw(frappe._("Please specify Debtor Org Id in check run settings")) + content += make_line(f" {debtor_org_id}") content += make_line(" ") content += make_line(" BANK") content += make_line(" ") @@ -171,7 +180,7 @@ def make_line(line): return line + "\r\n" -def get_iban_number(company, bank_account): +def get_iban_number(company, bank_account, pay_to_account): bank_iban = frappe.db.get_value("Bank Account", bank_account, "iban") if bank_iban: @@ -198,3 +207,15 @@ def get_party_iban_code(party_type, party): frappe.throw( frappe._(f"Iban Code is not available for {party_type} {get_link_to_form(party_type, party)}") ) + + +def get_party_orgid(company, bank_account, pay_to_account): + orgid = frappe.db.sql( + f""" + Select initiating_party_org_id, debtor_org_id + From `tabCheck Run Settings` + Where company = '{company}' and pay_to_account = '{pay_to_account}' and bank_account = '{bank_account}' + """, + as_dict=1, + ) + return orgid[0] From 79978ebff7e4a76e12d9a8a206c9e211cf72a692 Mon Sep 17 00:00:00 2001 From: viral Date: Mon, 22 Apr 2024 04:55:57 +0000 Subject: [PATCH 09/24] org id variable chnages --- .../doctype/check_run/gen_sepa_xml.py | 2 +- .../check_run_settings.json | 24 +++++++++++++++++-- check_run/tests/setup.py | 10 ++++++++ 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/check_run/check_run/doctype/check_run/gen_sepa_xml.py b/check_run/check_run/doctype/check_run/gen_sepa_xml.py index b629d2b4..bdbe07d2 100644 --- a/check_run/check_run/doctype/check_run/gen_sepa_xml.py +++ b/check_run/check_run/doctype/check_run/gen_sepa_xml.py @@ -72,7 +72,7 @@ def genrate_file_for_sepa(payments, doc, posting_date): content += make_line(" ") content += make_line(" ") content += make_line(" ") - debtor_org_id = orgid.get("initiating_party_org_id", None) + debtor_org_id = orgid.get("debtor_org_id", None) if not debtor_org_id: frappe.throw(frappe._("Please specify Debtor Org Id in check run settings")) content += make_line(f" {debtor_org_id}") 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 195c1dcd..2bec78a7 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 @@ -40,7 +40,10 @@ "custom_post_processing_hook", "sepa_payment_settings_section", "initiating_party_org_id", - "debtor_org_id" + "debtor_org_id", + "column_break_lzfmw", + "debtors_address", + "role" ], "fields": [ { @@ -243,10 +246,27 @@ "fieldname": "debtor_org_id", "fieldtype": "Data", "label": "Debtor Org Id" + }, + { + "fieldname": "column_break_lzfmw", + "fieldtype": "Column Break" + }, + { + "fieldname": "debtors_address", + "fieldtype": "Link", + "label": "Debtor's Address", + "options": "Address" + }, + { + "description": "Select a Role which has rights to download XML file multiple time", + "fieldname": "role", + "fieldtype": "Link", + "label": "Role", + "options": "Role" } ], "links": [], - "modified": "2024-04-15 07:57:00.135495", + "modified": "2024-04-19 02:25:15.078347", "modified_by": "Administrator", "module": "Check Run", "name": "Check Run Settings", diff --git a/check_run/tests/setup.py b/check_run/tests/setup.py index 5b4afc7c..7d7dbc36 100644 --- a/check_run/tests/setup.py +++ b/check_run/tests/setup.py @@ -151,6 +151,16 @@ def create_bank_and_bank_account(settings): doc.save() doc.submit() +# def create_eur_bank_and_bank_account(settings): +# if not frappe.db.exists("Mode of Payment", "SEPA"): +# mop.mode_of_payment = "" +# mop.enabled = 1 +# mop.type = "Electronic" +# mop.append( +# "accounts", {"company": settings.company, "default_account": settings.company_account} +# ) +# mop.save() + def setup_accounts(): frappe.rename_doc( From fc6d24409e1a1917a9994e934df39f87b3648a61 Mon Sep 17 00:00:00 2001 From: viral Date: Mon, 22 Apr 2024 04:57:25 +0000 Subject: [PATCH 10/24] org id variable chnages --- check_run/tests/setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/check_run/tests/setup.py b/check_run/tests/setup.py index 7d7dbc36..9c9b07a1 100644 --- a/check_run/tests/setup.py +++ b/check_run/tests/setup.py @@ -151,6 +151,7 @@ def create_bank_and_bank_account(settings): doc.save() doc.submit() + # def create_eur_bank_and_bank_account(settings): # if not frappe.db.exists("Mode of Payment", "SEPA"): # mop.mode_of_payment = "" From 7f6abb7c83e78cb6ddb172a4d494954adaf8ffad Mon Sep 17 00:00:00 2001 From: viral Date: Mon, 22 Apr 2024 05:00:56 +0000 Subject: [PATCH 11/24] added atest cases to create mode of payment sepa --- check_run/tests/setup.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/check_run/tests/setup.py b/check_run/tests/setup.py index 9c9b07a1..455e3a2f 100644 --- a/check_run/tests/setup.py +++ b/check_run/tests/setup.py @@ -152,15 +152,16 @@ def create_bank_and_bank_account(settings): doc.submit() -# def create_eur_bank_and_bank_account(settings): -# if not frappe.db.exists("Mode of Payment", "SEPA"): -# mop.mode_of_payment = "" -# mop.enabled = 1 -# mop.type = "Electronic" -# mop.append( -# "accounts", {"company": settings.company, "default_account": settings.company_account} -# ) -# mop.save() +def create_eur_bank_and_bank_account(settings): + if not frappe.db.exists("Mode of Payment", "SEPA"): + mop = frappe.new_doc("Mode of Payment") + mop.mode_of_payment = "SEPA" + mop.enabled = 1 + mop.type = "Electronic" + mop.append( + "accounts", {"company": settings.company, "default_account": settings.company_account} + ) + mop.save() def setup_accounts(): From a4dbedabda8a95946aff97e5ceb03292a77c14bd Mon Sep 17 00:00:00 2001 From: viral Date: Mon, 22 Apr 2024 06:28:02 +0000 Subject: [PATCH 12/24] Test cases for supplier bank account with iban code --- check_run/tests/fixtures.py | 17 +++++++++++ check_run/tests/setup.py | 57 ++++++++++++++++++++++++++++++++++++- 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/check_run/tests/fixtures.py b/check_run/tests/fixtures.py index 2129869c..de3c47fe 100644 --- a/check_run/tests/fixtures.py +++ b/check_run/tests/fixtures.py @@ -113,6 +113,23 @@ ), ] +sepa_supplier = [ + ( + "NRW Global Business", + "Export Service", + "SEPA", + 20000.00, + "Net 30", + { + "address_line1": "Volklinger Str. 4", + "city": "Dusseldorf", + "state": "Berlin", + "country": "Germany", + "pincode": "40219", + }, + ) +] + tax_authority = [ ( "Local Tax Authority", diff --git a/check_run/tests/setup.py b/check_run/tests/setup.py index 455e3a2f..5eda43d2 100644 --- a/check_run/tests/setup.py +++ b/check_run/tests/setup.py @@ -9,7 +9,7 @@ from erpnext.accounts.doctype.purchase_invoice.purchase_invoice import make_debit_note -from check_run.tests.fixtures import employees, suppliers, tax_authority +from check_run.tests.fixtures import employees, suppliers, tax_authority, sepa_supplier def before_test(): @@ -62,6 +62,7 @@ def create_test_data(): } ) create_bank_and_bank_account(settings) + create_eur_bank_and_bank_account(settings) create_payment_terms_templates(settings) create_suppliers(settings) create_items(settings) @@ -162,6 +163,26 @@ def create_eur_bank_and_bank_account(settings): "accounts", {"company": settings.company, "default_account": settings.company_account} ) mop.save() + if not frappe.db.exists("Bank", "EUR Bank"): + bank = frappe.new_doc("Bank") + bank.bank_name = "EUR Bank" + bank.save() + if not frappe.db.exists("Account", "1202 - Primary EUR Account - CFC"): + acc = frappe.new_doc("Account") + acc.account_currency = "EUR" + acc.account_name = "1202 - Primary EUR Account" + acc.account_type = "Bank" + acc.company = "Chelsea Fruit Co" + acc.parent_account = "1200 - Bank Accounts - CFC" + acc.save() + if not frappe.db.exists("Bank Account", "Primary Checking - EUR Bank"): + ba = frappe.new_doc("Bank Account") + ba.account_name = "Primary Checking" + ba.bank = "EUR Bank" + ba.is_company_account = 1 + ba.branch_code = "CXF6754" + ba.iban_code = "GB82 WEST 1234 5698 7654 32" + ba.save() def setup_accounts(): @@ -302,6 +323,40 @@ def create_suppliers(settings): addr.append("links", {"link_doctype": "Supplier", "link_name": "HIJ Telecom, Inc"}) addr.save() + for supplier in sepa_supplier: + su = frappe.new_doc("Supplier") + su.supplier_name = supplier[0] + su.supplier_group = "Services" + su.country = "Germany" + su.supplier_default_mode_of_payment = supplier[2] + if su.supplier_default_mode_of_payment == "SEPA": + su.bank = "EUR Bank" + su.iban = "DE89370400440532013000" + su.currency = "EUR" + su.default_price_list = "Standard Buying" + su.payment_terms = supplier[4] + su.save() + + ba = frappe.new_doc("Bank Account") + ba.account_name = "NRW Global Business" + ba.bank = "EUR Bank" + ba.party_type = "Supplier" + ba.party = "NRW Global Business" + ba.iban = "DE89370400440532013000" + ba.branch_code = "BGYH7876" + ba.save() + + addr = frappe.new_doc("Address") + addr.address_title = f"{supplier[0]} - {supplier[5]['city']}" + addr.address_type = "Billing" + addr.address_line1 = supplier[5]["address_line1"] + addr.city = supplier[5]["city"] + addr.state = supplier[5]["state"] + addr.country = supplier[5]["country"] + addr.pincode = supplier[5]["pincode"] + addr.append("links", {"link_doctype": "Supplier", "link_name": supplier[0]}) + addr.save() + def create_items(settings): for supplier in suppliers + tax_authority: From 76ef9ffb3f729e872381106580651e0aa7072ad1 Mon Sep 17 00:00:00 2001 From: viral Date: Mon, 22 Apr 2024 07:07:53 +0000 Subject: [PATCH 13/24] branch code added in xml --- check_run/check_run/doctype/check_run/gen_sepa_xml.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/check_run/check_run/doctype/check_run/gen_sepa_xml.py b/check_run/check_run/doctype/check_run/gen_sepa_xml.py index bdbe07d2..39bcb2e5 100644 --- a/check_run/check_run/doctype/check_run/gen_sepa_xml.py +++ b/check_run/check_run/doctype/check_run/gen_sepa_xml.py @@ -97,6 +97,8 @@ def genrate_file_for_sepa(payments, doc, posting_date): ) content += make_line(" ") content += make_line(" ") + bank_bic = frappe.db.get_value("Bank Account", doc.bank_account, "branch_code") # optional + content += make_line(" {}".format(bank_bic if bank_bic else "")) content += make_line(" NOTPROVIDED") content += make_line(" ") content += make_line(" ") From c540be807e16ffed03eb54b9a6a92ca21b804074 Mon Sep 17 00:00:00 2001 From: viral Date: Mon, 22 Apr 2024 10:29:15 +0000 Subject: [PATCH 14/24] chanhes in debetrs address --- .../doctype/check_run/gen_sepa_xml.py | 33 ++++++++++++++++++- check_run/tests/setup.py | 12 ++++++- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/check_run/check_run/doctype/check_run/gen_sepa_xml.py b/check_run/check_run/doctype/check_run/gen_sepa_xml.py index 39bcb2e5..9e6a52e4 100644 --- a/check_run/check_run/doctype/check_run/gen_sepa_xml.py +++ b/check_run/check_run/doctype/check_run/gen_sepa_xml.py @@ -69,7 +69,21 @@ def genrate_file_for_sepa(payments, doc, posting_date): content += make_line(f" {required_execution_date}") content += make_line(" ") content += make_line(f" {doc.company}") - content += make_line(" ") + # Address + addr = debtors_address(doc.company, doc.bank_account, doc.pay_to_account) + content += make_line(" ") + content += make_line( + " {}".format(addr.pincode if addr.pincode else "") + ) + content += make_line( + " {}".format(addr.address_line1 if addr.address_line1 else "") + ) + content += make_line(" {}".format(addr.city if addr.city else "")) + content += make_line( + " {}".format(addr.address_line2 if addr.address_line2 else "") + ) + content += make_line(" ") + content += make_line(" ") content += make_line(" ") content += make_line(" ") debtor_org_id = orgid.get("debtor_org_id", None) @@ -221,3 +235,20 @@ def get_party_orgid(company, bank_account, pay_to_account): as_dict=1, ) return orgid[0] + + +def debtors_address(company, bank_account, pay_to_account): + if crs_name := frappe.db.exists( + "Check Run Settings", {"bank_account": bank_account, "pay_to_account": pay_to_account} + ): + address = frappe.db.get_value("Check Run Settings", crs_name, "debtors_address") + if not address: + frappe.throw( + frappe._( + "Please enter a Debtor's Address in check run settings {}".format( + get_link_to_form("Check Run Settings", crs_name) + ) + ) + ) + address_doc = frappe.get_doc("Address", address) + return address_doc diff --git a/check_run/tests/setup.py b/check_run/tests/setup.py index 5eda43d2..19b0da10 100644 --- a/check_run/tests/setup.py +++ b/check_run/tests/setup.py @@ -180,10 +180,20 @@ def create_eur_bank_and_bank_account(settings): ba.account_name = "Primary Checking" ba.bank = "EUR Bank" ba.is_company_account = 1 + ba.account = "1202 - Primary EUR Account - CFC" ba.branch_code = "CXF6754" - ba.iban_code = "GB82 WEST 1234 5698 7654 32" + ba.iban = "GB82 WEST 1234 5698 7654 32" ba.save() + # New chart of account + account = frappe.new_doc("Account") + account.account_name = "2130 - EUR Account Payable" + account.account_type = "Payable" + account.parent_account = "2100 - Accounts Payable - CFC" + account.account_currency = "EUR" + account.root_type = "Liability" + account.save() + def setup_accounts(): frappe.rename_doc( From cfea2eadd3eed774395039588859ff801995be79 Mon Sep 17 00:00:00 2001 From: viral Date: Mon, 22 Apr 2024 11:56:12 +0000 Subject: [PATCH 15/24] new field and one time file generation access --- .../check_run/doctype/check_run/check_run.js | 13 +- .../doctype/check_run/check_run.json | 408 +++++++++--------- .../doctype/check_run/gen_sepa_xml.py | 2 - 3 files changed, 218 insertions(+), 205 deletions(-) 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 103443fc..9204bfe3 100644 --- a/check_run/check_run/doctype/check_run/check_run.js +++ b/check_run/check_run/doctype/check_run/check_run.js @@ -49,7 +49,9 @@ frappe.ui.form.on('Check Run', { permit_first_user(frm) get_defaults(frm) set_queries(frm) - if (frm.doc.docstatus == 1) { + if (frm.doc.docstatus == 1 && frm.doc.sepa_file_generated == 0) { + gen_sepa_xml(frm) + } else if (frappe.user.has_role('Accounts Manager')) { gen_sepa_xml(frm) } frappe.realtime.off('reload') @@ -438,13 +440,11 @@ function gen_sepa_xml(frm) { method: 'check_run.check_run.doctype.check_run.gen_sepa_xml.gen_sepa_xml_file', args: { doc: frm.doc, - // data: frm.doc.transactions, - // company: frm.doc.company, - // pay_to_account: frm.doc.pay_to_account, - // check_run: frm.doc.name, }, callback: function (r) { downloadXML('payments.xml', r.message) + frappe.db.set_value('Check Run', frm.doc.name, 'sepa_file_generated', 1) + frm.refresh() }, }) }) @@ -454,11 +454,8 @@ function downloadXML(filename, content) { var element = document.createElement('a') element.setAttribute('href', 'data:application/octet-stream;charset=utf-8,' + encodeURIComponent(content)) element.setAttribute('download', filename) - element.style.display = 'none' document.body.appendChild(element) - element.click() - document.body.removeChild(element) } 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 3181fabc..7897b4ff 100644 --- a/check_run/check_run/doctype/check_run/check_run.json +++ b/check_run/check_run/doctype/check_run/check_run.json @@ -1,196 +1,214 @@ { - "actions": [], - "allow_copy": 1, - "allow_events_in_timeline": 1, - "autoname": "ACC-CR-.YYYY.-.#####", - "creation": "2018-05-22 14:01:11.307993", - "doctype": "DocType", - "editable_grid": 1, - "engine": "InnoDB", - "field_order": [ - "end_date", - "posting_date", - "beg_balance", - "company_discretionary_data", - "column_break_3", - "initial_check_number", - "final_check_number", - "amount_check_run", - "column_break_6", - "company", - "bank_account", - "pay_to_account", - "amended_from", - "section_break_9", - "check_run_table", - "transactions", - "print_count", - "status" - ], - "fields": [ - { - "fieldname": "end_date", - "fieldtype": "Date", - "in_list_view": 1, - "label": "Check Run End Date" - }, - { - "fieldname": "column_break_3", - "fieldtype": "Column Break" - }, - { - "allow_on_submit": 1, - "fieldname": "initial_check_number", - "fieldtype": "Int", - "in_list_view": 1, - "label": "Initial Check Number" - }, - { - "allow_on_submit": 1, - "fieldname": "final_check_number", - "fieldtype": "Int", - "in_list_view": 1, - "label": "Final Check Number", - "read_only": 1 - }, - { - "default": "0.00", - "fieldname": "amount_check_run", - "fieldtype": "Currency", - "in_list_view": 1, - "label": "Amount in Check Run", - "read_only": 1 - }, - { - "fieldname": "column_break_6", - "fieldtype": "Column Break" - }, - { - "allow_in_quick_entry": 1, - "fieldname": "company", - "fieldtype": "Link", - "in_standard_filter": 1, - "label": "Company", - "options": "Company", - "remember_last_selected_value": 1, - "reqd": 1 - }, - { - "allow_in_quick_entry": 1, - "fetch_from": "company.default_bank_account", - "fetch_if_empty": 1, - "fieldname": "bank_account", - "fieldtype": "Link", - "label": "Paid From (Bank Account)", - "options": "Bank Account", - "remember_last_selected_value": 1, - "reqd": 1 - }, - { - "default": "company.default_payable_account", - "fieldname": "pay_to_account", - "fieldtype": "Link", - "in_standard_filter": 1, - "label": "Accounts Payable", - "options": "Account", - "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" - }, - { - "default": "0.00", - "fieldname": "beg_balance", - "fieldtype": "Currency", - "label": "Beginning Bank Account Balance", - "read_only": 1 - }, - { - "fieldname": "amended_from", - "fieldtype": "Link", - "hidden": 1, - "label": "Amended From", - "no_copy": 1, - "options": "Check Run", - "print_hide": 1, - "read_only": 1 - }, - { - "allow_on_submit": 1, - "fieldname": "transactions", - "fieldtype": "Long Text", - "hidden": 1, - "ignore_xss_filter": 1 - }, - { - "allow_on_submit": 1, - "fieldname": "print_count", - "fieldtype": "Int", - "hidden": 1 - }, - { - "allow_on_submit": 1, - "default": "Draft", - "fieldname": "status", - "fieldtype": "Select", - "hidden": 1, - "options": "Draft\nSubmitting\nSubmitted\nReady to Print\nConfirm Print\nPrinted" - }, - { - "fieldname": "check_run_table", - "fieldtype": "HTML" - }, - { - "fieldname": "posting_date", - "fieldtype": "Date", - "in_list_view": 1, - "in_standard_filter": 1, - "label": "Posting Date" - } - ], - "is_submittable": 1, - "links": [], - "modified": "2023-03-10 12:28:36.910004", - "modified_by": "Administrator", - "module": "Check Run", - "name": "Check Run", - "owner": "Administrator", - "permissions": [ - { - "create": 1, - "read": 1, - "report": 1, - "role": "Accounts User", - "select": 1, - "write": 1 - }, - { - "create": 1, - "export": 1, - "print": 1, - "read": 1, - "report": 1, - "role": "Accounts Manager", - "select": 1, - "share": 1, - "submit": 1, - "write": 1 - } - ], - "quick_entry": 1, - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 1, - "track_seen": 1, - "track_views": 1 -} + "actions": [], + "allow_copy": 1, + "allow_events_in_timeline": 1, + "autoname": "ACC-CR-.YYYY.-.#####", + "creation": "2018-05-22 14:01:11.307993", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "end_date", + "posting_date", + "beg_balance", + "company_discretionary_data", + "column_break_3", + "initial_check_number", + "final_check_number", + "amount_check_run", + "column_break_6", + "company", + "bank_account", + "pay_to_account", + "amended_from", + "section_break_9", + "check_run_table", + "transactions", + "print_count", + "status", + "sepa_file_generated", + "ach_file_generated" + ], + "fields": [ + { + "fieldname": "end_date", + "fieldtype": "Date", + "in_list_view": 1, + "label": "Check Run End Date" + }, + { + "fieldname": "column_break_3", + "fieldtype": "Column Break" + }, + { + "allow_on_submit": 1, + "fieldname": "initial_check_number", + "fieldtype": "Int", + "in_list_view": 1, + "label": "Initial Check Number" + }, + { + "allow_on_submit": 1, + "fieldname": "final_check_number", + "fieldtype": "Int", + "in_list_view": 1, + "label": "Final Check Number", + "read_only": 1 + }, + { + "default": "0.00", + "fieldname": "amount_check_run", + "fieldtype": "Currency", + "in_list_view": 1, + "label": "Amount in Check Run", + "read_only": 1 + }, + { + "fieldname": "column_break_6", + "fieldtype": "Column Break" + }, + { + "allow_in_quick_entry": 1, + "fieldname": "company", + "fieldtype": "Link", + "in_standard_filter": 1, + "label": "Company", + "options": "Company", + "remember_last_selected_value": 1, + "reqd": 1 + }, + { + "allow_in_quick_entry": 1, + "fetch_from": "company.default_bank_account", + "fetch_if_empty": 1, + "fieldname": "bank_account", + "fieldtype": "Link", + "label": "Paid From (Bank Account)", + "options": "Bank Account", + "remember_last_selected_value": 1, + "reqd": 1 + }, + { + "default": "company.default_payable_account", + "fieldname": "pay_to_account", + "fieldtype": "Link", + "in_standard_filter": 1, + "label": "Accounts Payable", + "options": "Account", + "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" + }, + { + "default": "0.00", + "fieldname": "beg_balance", + "fieldtype": "Currency", + "label": "Beginning Bank Account Balance", + "read_only": 1 + }, + { + "fieldname": "amended_from", + "fieldtype": "Link", + "hidden": 1, + "label": "Amended From", + "no_copy": 1, + "options": "Check Run", + "print_hide": 1, + "read_only": 1 + }, + { + "allow_on_submit": 1, + "fieldname": "transactions", + "fieldtype": "Long Text", + "hidden": 1, + "ignore_xss_filter": 1 + }, + { + "allow_on_submit": 1, + "fieldname": "print_count", + "fieldtype": "Int", + "hidden": 1 + }, + { + "allow_on_submit": 1, + "default": "Draft", + "fieldname": "status", + "fieldtype": "Select", + "hidden": 1, + "options": "Draft\nSubmitting\nSubmitted\nReady to Print\nConfirm Print\nPrinted" + }, + { + "fieldname": "check_run_table", + "fieldtype": "HTML" + }, + { + "fieldname": "posting_date", + "fieldtype": "Date", + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Posting Date" + }, + { + "allow_on_submit": 1, + "default": "0", + "fieldname": "sepa_file_generated", + "fieldtype": "Check", + "hidden": 1 + }, + { + "allow_on_submit": 1, + "default": "0", + "fieldname": "ach_file_generated", + "fieldtype": "Check", + "hidden": 1 + } + ], + "is_submittable": 1, + "links": [], + "modified": "2024-04-22 07:22:02.167863", + "modified_by": "Administrator", + "module": "Check Run", + "name": "Check Run", + "naming_rule": "Expression (old style)", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "read": 1, + "report": 1, + "role": "Accounts User", + "select": 1, + "write": 1 + }, + { + "create": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Accounts Manager", + "select": 1, + "share": 1, + "submit": 1, + "write": 1 + } + ], + "quick_entry": 1, + "sort_field": "modified", + "sort_order": "DESC", + "states": [], + "track_changes": 1, + "track_seen": 1, + "track_views": 1 +} \ No newline at end of file diff --git a/check_run/check_run/doctype/check_run/gen_sepa_xml.py b/check_run/check_run/doctype/check_run/gen_sepa_xml.py index 9e6a52e4..f190e0cf 100644 --- a/check_run/check_run/doctype/check_run/gen_sepa_xml.py +++ b/check_run/check_run/doctype/check_run/gen_sepa_xml.py @@ -142,8 +142,6 @@ def genrate_file_for_sepa(payments, doc, posting_date): " " ) content += make_line(" ") - if payment_record.party_type == "Employee": - name = frappe.get_value("Employee", payment_record.party, "employee_name") if payment_record.party_type == "Supplier": name = frappe.db.get_value("Supplier", payment_record.party, "supplier_name") if "&" in name: From c4be4cb0a90f255cf4bffca4f83741d517b5e05c Mon Sep 17 00:00:00 2001 From: viral Date: Thu, 25 Apr 2024 09:55:41 +0000 Subject: [PATCH 16/24] download sepa only on docstatus = 1 --- check_run/check_run/doctype/check_run/check_run.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 9204bfe3..bae1e2ff 100644 --- a/check_run/check_run/doctype/check_run/check_run.js +++ b/check_run/check_run/doctype/check_run/check_run.js @@ -51,7 +51,7 @@ frappe.ui.form.on('Check Run', { set_queries(frm) if (frm.doc.docstatus == 1 && frm.doc.sepa_file_generated == 0) { gen_sepa_xml(frm) - } else if (frappe.user.has_role('Accounts Manager')) { + } else if (frappe.user.has_role('Accounts Manager') && frm.doc.docstatus == 1) { gen_sepa_xml(frm) } frappe.realtime.off('reload') From b70614c99c2170f1339bdd898e7c6b9f04fb241c Mon Sep 17 00:00:00 2001 From: viral Date: Thu, 25 Apr 2024 10:35:55 +0000 Subject: [PATCH 17/24] sepa file only able to download by authorized user --- .../check_run/doctype/check_run/check_run.js | 29 ++++++++++--------- .../check_run/doctype/check_run/check_run.py | 11 +++++++ 2 files changed, 27 insertions(+), 13 deletions(-) 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 bae1e2ff..1cd57eff 100644 --- a/check_run/check_run/doctype/check_run/check_run.js +++ b/check_run/check_run/doctype/check_run/check_run.js @@ -49,9 +49,9 @@ frappe.ui.form.on('Check Run', { permit_first_user(frm) get_defaults(frm) set_queries(frm) - if (frm.doc.docstatus == 1 && frm.doc.sepa_file_generated == 0) { - gen_sepa_xml(frm) - } else if (frappe.user.has_role('Accounts Manager') && frm.doc.docstatus == 1) { + if (frm.doc.docstatus == 1 && frm.doc.sepa_file_generated == 0 && frm.pay_to_account_currency == 'EUR') { + downloadsepa(frm) + } else if (frm.doc.sepa_file_generated == 1 && frm.doc.docstatus == 1 && frm.pay_to_account_currency == 'EUR') { gen_sepa_xml(frm) } frappe.realtime.off('reload') @@ -435,17 +435,20 @@ function check_settings(frm) { } function gen_sepa_xml(frm) { + frappe.xcall('check_run.check_run.doctype.check_run.check_run.get_authorized_role', { doc: frm.doc }).then(r => { + if (frappe.user.has_role(r)) { + downloadsepa(frm) + } + }) +} + +function downloadsepa(frm) { frm.add_custom_button('Download SEPA', () => { - frappe.call({ - method: 'check_run.check_run.doctype.check_run.gen_sepa_xml.gen_sepa_xml_file', - args: { - doc: frm.doc, - }, - callback: function (r) { - downloadXML('payments.xml', r.message) - frappe.db.set_value('Check Run', frm.doc.name, 'sepa_file_generated', 1) - frm.refresh() - }, + frappe.xcall('check_run.check_run.doctype.check_run.gen_sepa_xml.gen_sepa_xml_file', { doc: frm.doc }).then(r => { + console.log(r) + downloadXML('payments.xml', r) + frappe.db.set_value('Check Run', frm.doc.name, 'sepa_file_generated', 1) + frm.refresh() }) }) } 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 f1a9ad28..a9cb0098 100644 --- a/check_run/check_run/doctype/check_run/check_run.py +++ b/check_run/check_run/doctype/check_run/check_run.py @@ -912,3 +912,14 @@ def ach_only(docname: str) -> dict: def process_check_run(docname: str) -> None: doc = frappe.get_doc("Check Run", docname) doc.process_check_run() + + +@frappe.whitelist() +def get_authorized_role(doc): + doc = frappe._dict(json.loads(doc)) if isinstance(doc, str) else doc + role = frappe.db.get_value( + "Check Run Settings", + {"pay_to_account": doc.pay_to_account, "bank_account": doc.bank_account}, + "role", + ) + return role From b824b27b123d92f55d03f75928200c5ef17b39f1 Mon Sep 17 00:00:00 2001 From: viral Date: Thu, 25 Apr 2024 10:45:16 +0000 Subject: [PATCH 18/24] new purchase invoice test cases --- check_run/tests/setup.py | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/check_run/tests/setup.py b/check_run/tests/setup.py index 19b0da10..9bcb1e30 100644 --- a/check_run/tests/setup.py +++ b/check_run/tests/setup.py @@ -187,7 +187,8 @@ def create_eur_bank_and_bank_account(settings): # New chart of account account = frappe.new_doc("Account") - account.account_name = "2130 - EUR Account Payable" + account.account_name = "EUR Account Payable" + account.account_number = "2130" account.account_type = "Payable" account.parent_account = "2100 - Accounts Payable - CFC" account.account_currency = "EUR" @@ -537,6 +538,26 @@ def create_invoices(settings): pi.save() pi.submit() + # EUR Purchase Invoice + pi = frappe.new_doc("Purchase Invoice") + pi.company = settings.company + pi.set_posting_time = 1 + pi.posting_date = settings.day + pi.supplier = sepa_supplier[0][0] + pi.currency = "EUR" + pi.credit_to = "2130 - EUR Account Payable - CFC" + pi.append( + "items", + { + "item_code": sepa_supplier[0][1], + "rate": 25000.00, + "qty": 1, + }, + ) + pi.supplier_address = "NRW Global Business - Dusseldorf-Billing" + pi.save() + pi.submit() + spi = frappe.get_value( "Purchase Invoice", {"supplier": "Cooperative Ag Finance"}, From 90369a0e48bff2403f21f5f0f4c56d10dac27167 Mon Sep 17 00:00:00 2001 From: viral Date: Thu, 25 Apr 2024 10:51:55 +0000 Subject: [PATCH 19/24] added a item in fixtures --- check_run/tests/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/check_run/tests/setup.py b/check_run/tests/setup.py index 9bcb1e30..c8d1ec06 100644 --- a/check_run/tests/setup.py +++ b/check_run/tests/setup.py @@ -370,7 +370,7 @@ def create_suppliers(settings): def create_items(settings): - for supplier in suppliers + tax_authority: + for supplier in suppliers + tax_authority + sepa_supplier: item = frappe.new_doc("Item") item.item_code = item.item_name = supplier[1] item.item_group = "Services" From f168a421e27c0264c63d0f543910e8455e9f76e3 Mon Sep 17 00:00:00 2001 From: ViralKansodiya-Fosserp <141210323+viralkansodiya@users.noreply.github.com> Date: Thu, 25 Apr 2024 16:56:17 +0530 Subject: [PATCH 20/24] ach_file_generated will come in another PR --- check_run/check_run/doctype/check_run/check_run.json | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) 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 7897b4ff..b4815231 100644 --- a/check_run/check_run/doctype/check_run/check_run.json +++ b/check_run/check_run/doctype/check_run/check_run.json @@ -26,8 +26,7 @@ "transactions", "print_count", "status", - "sepa_file_generated", - "ach_file_generated" + "sepa_file_generated" ], "fields": [ { @@ -165,13 +164,6 @@ "fieldname": "sepa_file_generated", "fieldtype": "Check", "hidden": 1 - }, - { - "allow_on_submit": 1, - "default": "0", - "fieldname": "ach_file_generated", - "fieldtype": "Check", - "hidden": 1 } ], "is_submittable": 1, From 134df7378b261fd6c3fd64151852098aefb2c918 Mon Sep 17 00:00:00 2001 From: viral Date: Fri, 26 Apr 2024 03:39:13 +0000 Subject: [PATCH 21/24] if condition to optimisaion --- check_run/check_run/doctype/check_run/check_run.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 1cd57eff..6cd8c069 100644 --- a/check_run/check_run/doctype/check_run/check_run.js +++ b/check_run/check_run/doctype/check_run/check_run.js @@ -447,8 +447,9 @@ function downloadsepa(frm) { frappe.xcall('check_run.check_run.doctype.check_run.gen_sepa_xml.gen_sepa_xml_file', { doc: frm.doc }).then(r => { console.log(r) downloadXML('payments.xml', r) - frappe.db.set_value('Check Run', frm.doc.name, 'sepa_file_generated', 1) - frm.refresh() + if(frm.doc.sepa_file_generated == 0){ + frappe.db.set_value('Check Run', frm.doc.name, 'sepa_file_generated', 1) + } }) }) } From bba975ffba1165e56c7624fc4e47d0a8daf41545 Mon Sep 17 00:00:00 2001 From: viral Date: Fri, 26 Apr 2024 08:29:21 +0000 Subject: [PATCH 22/24] changes role field label and bank bic tag format changes --- check_run/check_run/doctype/check_run/check_run.py | 2 +- check_run/check_run/doctype/check_run/gen_sepa_xml.py | 11 ++++++----- .../check_run_settings/check_run_settings.json | 10 +++++----- 3 files changed, 12 insertions(+), 11 deletions(-) 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 a9cb0098..0928f0a1 100644 --- a/check_run/check_run/doctype/check_run/check_run.py +++ b/check_run/check_run/doctype/check_run/check_run.py @@ -920,6 +920,6 @@ def get_authorized_role(doc): role = frappe.db.get_value( "Check Run Settings", {"pay_to_account": doc.pay_to_account, "bank_account": doc.bank_account}, - "role", + "sepa_authorized_role", ) return role diff --git a/check_run/check_run/doctype/check_run/gen_sepa_xml.py b/check_run/check_run/doctype/check_run/gen_sepa_xml.py index f190e0cf..5e05584b 100644 --- a/check_run/check_run/doctype/check_run/gen_sepa_xml.py +++ b/check_run/check_run/doctype/check_run/gen_sepa_xml.py @@ -15,7 +15,6 @@ def gen_sepa_xml_file(doc): def genrate_file_for_sepa(payments, doc, posting_date): # Message Root content = make_line("") - content += make_line("") content += make_line( "" ) @@ -110,11 +109,13 @@ def genrate_file_for_sepa(payments, doc, posting_date): " " ) content += make_line(" ") - content += make_line(" ") bank_bic = frappe.db.get_value("Bank Account", doc.bank_account, "branch_code") # optional - content += make_line(" {}".format(bank_bic if bank_bic else "")) - content += make_line(" NOTPROVIDED") - content += make_line(" ") + if bank_bic: + content += make_line(f" {bank_bic}") + else: + content += make_line(" ") + content += make_line(" NOTPROVIDED") + content += make_line(" ") content += make_line(" ") content += make_line(" ") content += make_line(" SLEV") 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 2bec78a7..cd92a9d5 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 @@ -43,7 +43,7 @@ "debtor_org_id", "column_break_lzfmw", "debtors_address", - "role" + "sepa_authorized_role" ], "fields": [ { @@ -258,15 +258,15 @@ "options": "Address" }, { - "description": "Select a Role which has rights to download XML file multiple time", - "fieldname": "role", + "description": "Users with this role are allowed to download SEPA XML file multiple times. Users without this role are allowed to download it only once.", + "fieldname": "sepa_authorized_role", "fieldtype": "Link", - "label": "Role", + "label": "Role Allowed to Download SEPA XML File Multiple Times", "options": "Role" } ], "links": [], - "modified": "2024-04-19 02:25:15.078347", + "modified": "2024-04-26 04:21:24.517639", "modified_by": "Administrator", "module": "Check Run", "name": "Check Run Settings", From 41a4c76b85316f44c21e26bf030715e292e2b955 Mon Sep 17 00:00:00 2001 From: viral Date: Fri, 26 Apr 2024 09:05:51 +0000 Subject: [PATCH 23/24] minore field label and error throw msges changes --- .../doctype/check_run/gen_sepa_xml.py | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/check_run/check_run/doctype/check_run/gen_sepa_xml.py b/check_run/check_run/doctype/check_run/gen_sepa_xml.py index 5e05584b..c13412d1 100644 --- a/check_run/check_run/doctype/check_run/gen_sepa_xml.py +++ b/check_run/check_run/doctype/check_run/gen_sepa_xml.py @@ -1,5 +1,5 @@ import frappe -from frappe.utils import getdate, get_link_to_form +from frappe.utils import getdate, get_link_to_form, get_url import time @@ -38,7 +38,13 @@ def genrate_file_for_sepa(payments, doc, posting_date): initiating_party_org_id = orgid.get("initiating_party_org_id", None) if not initiating_party_org_id: - frappe.throw(frappe._("Please specify Initiating Party OrgID in check run settings")) + frappe.throw( + frappe._( + "Please specify 'Initiating Party OrgID' in {}".format( + f"Check Run Settings" + ) + ) + ) content += make_line(" ") content += make_line(" ") content += make_line(f" {initiating_party_org_id}") @@ -87,7 +93,13 @@ def genrate_file_for_sepa(payments, doc, posting_date): content += make_line(" ") debtor_org_id = orgid.get("debtor_org_id", None) if not debtor_org_id: - frappe.throw(frappe._("Please specify Debtor Org Id in check run settings")) + frappe.throw( + frappe._( + "Please specify 'Debtor Org Id' in {}".format( + f"Check Run Settings" + ) + ) + ) content += make_line(f" {debtor_org_id}") content += make_line(" ") content += make_line(" BANK") @@ -251,3 +263,13 @@ def debtors_address(company, bank_account, pay_to_account): ) address_doc = frappe.get_doc("Address", address) return address_doc + + +def get_check_run_settings_link(doc): + url = get_url() + check_run_settings_path = "/app/check-run-settings/" + check_run_settings = frappe.db.exists( + "Check Run Settings", {"bank_account": doc.bank_account, "pay_to_account": doc.pay_to_account} + ) + check_run_settings_url = url + check_run_settings_path + check_run_settings + return str(check_run_settings_url) From dc6c242a8eba50409f29a1ae51c049c31a0344a6 Mon Sep 17 00:00:00 2001 From: viral Date: Fri, 26 Apr 2024 11:41:42 +0000 Subject: [PATCH 24/24] address filter added --- .../doctype/check_run_settings/check_run_settings.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/check_run/check_run/doctype/check_run_settings/check_run_settings.js b/check_run/check_run/doctype/check_run_settings/check_run_settings.js index 9ba74675..74ca71fa 100644 --- a/check_run/check_run/doctype/check_run_settings/check_run_settings.js +++ b/check_run/check_run/doctype/check_run_settings/check_run_settings.js @@ -27,5 +27,11 @@ frappe.ui.form.on('Check Run Settings', { }, } }) + frm.set_query('debtors_address', function () { + return { + query: 'frappe.contacts.doctype.address.address.address_query', + filters: { link_doctype: 'Company', link_name: frm.doc.company }, + } + }) }, })