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 a63c533d..cc41d85a 100644 --- a/check_run/check_run/doctype/check_run/check_run.js +++ b/check_run/check_run/doctype/check_run/check_run.js @@ -34,9 +34,7 @@ frappe.ui.form.on("Check Run", { } } }) - // print is only accessible from custom buttom - $('[data-original-title="Print"]').hide() - render_page(frm) + get_entries(frm) confirm_print(frm) if(frm.doc.docstatus > 0){ frm.set_df_property('initial_check_number', 'read_only', 1) @@ -46,24 +44,19 @@ frappe.ui.form.on("Check Run", { onload_post_render: frm => { frm.page.wrapper.find('.layout-side-section').hide() permit_first_user(frm) - setup_keyboard_navigation(frm) }, end_date: frm => { - warn_on_field_reset().then(get_entries(frm, true)) + get_entries(frm) }, start_date: frm => { - warn_on_field_reset().then(() => { - frappe.xcall("get_balance",{ doc: frm.doc}) - .then(() => { - get_entries(frm, true) - frm.refresh_field("beg_balance") - }).fail((f) => { - console.error(f) - }) + frappe.xcall('check_run.check_run.doctype.check_run.check_run.get_balance',{ doc: frm.doc }) + .then(r => { + frm.set_value('beg_balance', r) + get_entries(frm) }) }, onload: frm => { - frm.$check_run = $(frm.fields_dict['html_10'].wrapper) + frm.$check_run = undefined frm.transactions = [] frm.check_run_sort = { partyInput: '', @@ -74,16 +67,10 @@ frappe.ui.form.on("Check Run", { } }, pay_to_account: frm => { - warn_on_field_reset().then(get_entries(frm, true)) + get_entries(frm) } }) -function render_page(frm) { - return new Promise((resolve) => { - resolve(get_entries(frm, false)) - }) -} - function set_queries(frm){ frm.set_query("bank_account", function() { return { @@ -102,25 +89,17 @@ function set_queries(frm){ }) } -function get_entries(frm, reload){ - return new Promise((resolve) => { - frappe.call({ - method: 'check_run.check_run.doctype.check_run.check_run.get_entries', - args: { doc: frm.doc, reload: reload}, - }).done((r) => { - // console.log("TRANSACTIONS", r.message.transactions) - frm.transactions = r.message.transactions.slice(0, 10) - frm.modes_of_payment = r.message.modes_of_payment - check_run.mount_table(frm, frm.$check_run) - if (!frappe.user.has_role(["Accounts Manager"])) { - frm.disable_form() - frm.$check_run.css({ 'pointer-events': 'none' }) - } - resolve() - }).fail((r) => { - console.log(r) - resolve() - }) +function get_entries(frm){ + frappe.xcall('check_run.check_run.doctype.check_run.check_run.get_entries', { doc: frm.doc} + ).then((r) => { + console.log("TRANSACTIONS", frm.transactions.length, r.transactions.length) + frm.transactions = r.transactions + frm.modes_of_payment = r.modes_of_payment + check_run.mount_table(frm) + if (!frappe.user.has_role(["Accounts Manager"])) { + frm.disable_form() + frm.$check_run.css({ 'pointer-events': 'none' }) + } }) } @@ -134,7 +113,6 @@ function total_check_run(frm){ frm.set_value("amount_check_run", Number(total)) } - function get_defaults(frm){ if(!frm.is_new()){ return } frm.set_value('start_date', moment().startOf('week').format()) @@ -147,206 +125,18 @@ function get_defaults(frm){ } function get_last_check_number(frm){ + // TODO: refactor to xcall if(frm.doc.__islocal && frm.doc.start_date){ frappe.call({ method: "set_last_check_number", doc: frm.doc, }).then((r) => { - console.log(r) frm.refresh_field("last_check") frm.refresh_field("initial_check_number") - }).fail((f) => { - console.error(f) }) } } - -function setup_keyboard_navigation (frm) { - const focus_first_row = () => { - let first_row = frm.$check_run.find(".checkrun-row-container:first") - $(first_row[0]).focus() - } - let focus_next = () => { - $(document.activeElement).next().focus() - } - let focus_prev = () => { - $(document.activeElement).prev().focus() - } - let list_row_focused = () => { - return $(document.activeElement).is(".checkrun-row-container") - } - let check_row = ($row) => { - let $input = $row.find("input[type=checkbox]") - $input.click() - } - - let get_list_row_if_focused = () => list_row_focused() ? $(document.activeElement) : null - - let is_current_page = () => frm.page.wrapper.is(":visible") - let is_input_focused = () => $(document.activeElement).is("input") - - let handle_navigation = (direction) => { - if (!is_current_page() || is_input_focused()) return false; - - let $list_row = get_list_row_if_focused() - if ($list_row) { - direction === "down" ? focus_next() : focus_prev() - } else { - focus_first_row() - } - } - - frappe.ui.keys.add_shortcut({ - shortcut: "down", - action: () => handle_navigation("down"), - description: __("Navigate down"), - page: frm.page, - }) - - frappe.ui.keys.add_shortcut({ - shortcut: "up", - action: () => handle_navigation("up"), - description: __("Navigate up"), - page: frm.page, - }) - - frappe.ui.keys.add_shortcut({ - shortcut: "shift+down", - action: () => { - if (!is_current_page() || is_input_focused()) return false; - let $list_row = get_list_row_if_focused(); - check_row($list_row); - focus_next(); - }, - description: __("Select multiple list items"), - page: frm.page, - }) - - frappe.ui.keys.add_shortcut({ - shortcut: "shift+up", - action: () => { - if (!is_current_page() || is_input_focused()) { return false } - let $list_row = get_list_row_if_focused() - check_row($list_row) - focus_prev() - }, - description: __("Select multiple list items"), - page: frm.page, - }) - - frappe.ui.keys.add_shortcut({ - shortcut: "space", - action: () => { - let $list_row = get_list_row_if_focused() - if ($list_row) { - check_row($list_row) - return true - } - return false - }, - description: __("Select list item"), - page: frm.page, - }) - - frappe.ui.keys.add_shortcut({ - shortcut: "c", - action: () => { - let $list_row = get_list_row_if_focused() - if ($list_row) { - let el = $list_row.find("[data-mop-index]") - set_mop_input(frm, el, 'Check') - return true - } - return false - }, - description: __("Select list item"), - page: frm.page, - }) - - frappe.ui.keys.add_shortcut({ - shortcut: "a", - action: () => { - let $list_row = get_list_row_if_focused() - if ($list_row) { - let el = $list_row.find("[data-mop-index]") - set_mop_input(frm, el, 'ACH/EFT') - return true - } - return false - }, - description: __("Select list item"), - page: frm.page, - }) - - frappe.ui.keys.add_shortcut({ - shortcut: "e", - action: () => { - let $list_row = get_list_row_if_focused() - if ($list_row) { - let el = $list_row.find("[data-mop-index]") - set_mop_input(frm, el, 'ECheck') - return true - } - return false - }, - description: __("Select list item"), - page: frm.page, - }) -} - -function show_mop_input(frm, el) { - if (el[0].tagName == "SPAN") - el = $(el[0].parentNode) - el.find("span").hide() - el.find("select").show().focus() - el.find("[data-mop]").unbind('change blur keyup').on("click", (e) => { - set_mop_input(frm, el, el.children()[0].value) - }).on("blur", () => { - el.find("span").show() - el.find("select").hide() - }) -} - -function show_party_filter(frm, el) { - if (el[0].tagName == "SPAN") - el = $(el[0].parentNode) - el.find("span").hide() - el.find("input").show().focus() - el.find("#party-input").unbind('change blur keyup').on("keyup", frappe.utils.debounce((e) => { - if(e.target.value != ''){ - frm.check_run_sort.partyFilter = e.target.value - let transactions = frm.check_run_state.transactions.filter(row => row.party.toLowerCase().search(e.target.value.toLowerCase()) !== -1) - frm.$check_run.html(frappe.render_template("check_run", { - "transactions": frm.check_run_state.transactions, 'modes_of_payment': frm.modes_of_payment - })) - //setup_sort_and_filter(frm) - } else { - frm.$check_run.html(frappe.render_template("check_run", { - "transactions": frm.check_run_state.transactions, 'modes_of_payment': frm.modes_of_payment - })) - //setup_sort_and_filter(frm) - } - }, 400)) - el.on("blur", () => { - if (!el.find("input").value){ - frm.check_run_sort.partyFilter = '' - frm.$check_run.html(frappe.render_template("check_run", { - "transactions": frm.check_run_state.transactions, 'modes_of_payment': frm.modes_of_payment - })) - //setup_sort_and_filter(frm) - el.find("span").show() - el.find("input").hide() - } - }) -} - -function set_mop_input(frm, el, value){ - frm.check_run_state.transactions[el.data('mopIndex')].mode_of_payment = value - //$(el.children()[0]).html(value) - frm.dirty() -} - function permit_first_user(frm){ let viewers = frm.get_docinfo()['viewers'] if(!viewers){ @@ -386,7 +176,6 @@ function confirm_print(frm){ .then(() => { d.hide() frm.reload_doc() - render_page(frm) }) }) d.wrapper.find('#reprint').on('click', () => { @@ -422,12 +211,4 @@ function reprint_checks(frm){ d.hide() }) d.show() -} - - -async function warn_on_field_reset(callback){ - await frappe.confirm( - __("Changing this field will reload transactions"), - callback - ) } \ No newline at end of file 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 259fa9f2..8a7d918f 100644 --- a/check_run/check_run/doctype/check_run/check_run.json +++ b/check_run/check_run/doctype/check_run/check_run.json @@ -21,7 +21,7 @@ "bank_account", "pay_to_account", "section_break_9", - "html_10", + "check_run_table", "transactions", "amended_from", "print_count", @@ -51,7 +51,6 @@ }, { "allow_on_submit": 1, - "description": "Final check number in this check run.", "fieldname": "final_check_number", "fieldtype": "Int", "in_list_view": 1, @@ -100,10 +99,6 @@ "fieldname": "section_break_9", "fieldtype": "Section Break" }, - { - "fieldname": "html_10", - "fieldtype": "HTML" - }, { "default": "0.00", "fieldname": "beg_balance", @@ -146,11 +141,15 @@ "fieldtype": "Select", "hidden": 1, "options": "Draft\nSubmitted\nConfirm Print\nPrinted" + }, + { + "fieldname": "check_run_table", + "fieldtype": "HTML" } ], "is_submittable": 1, "links": [], - "modified": "2022-07-03 11:25:38.873413", + "modified": "2022-07-04 05:50:56.817736", "modified_by": "Administrator", "module": "Check Run", "name": "Check Run", 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 4403071e..bf9dc9ce 100644 --- a/check_run/check_run/doctype/check_run/check_run.py +++ b/check_run/check_run/doctype/check_run/check_run.py @@ -32,6 +32,19 @@ def validate(self): else: self.validate_last_check_number() + def is_dirty(self, doc): + dirty = False + for key in ('start_date', 'end_date', 'check_run_date', 'initial_check_number', 'company', 'bank_account', 'pay_to_account'): + if self.get(key) != doc.get(key): + return True + for db_row in json.loads(self.transactions): + for frm_row in doc.transactions: + if db_row.get('name') == frm_row.get('name'): + if db_row.get('mode_of_payment') != frm_row.get('mode_of_payment'): + return True + if db_row.get('pay') != frm_row.get('pay'): + return True + def set_status(self, status=None): if status: self.status = status @@ -68,11 +81,6 @@ def validate_last_check_number(self, check_number=None): if int(check_number) < int(account_check_number): frappe.throw(f'Initial Check Number cannot be lower than the last used check number {account_check_number} for {self.bank_account}') - @frappe.whitelist() - def get_balance(self): - gl_account = frappe.get_value('Bank Account', self.bank_account, 'account') - return get_balance_on(gl_account, self.check_run_date) - @frappe.whitelist() def before_submit(self): self.payment_entries = [] @@ -259,18 +267,18 @@ def check_for_draft_check_run(company, bank_account): @frappe.whitelist() def confirm_print(docname): - frappe.db.set_value('Check Run', docname, 'status', 'Printed') - return + return frappe.db.set_value('Check Run', docname, 'status', 'Printed') @frappe.whitelist() def get_entries(doc): doc = frappe._dict(json.loads(doc)) if isinstance(doc, str) else doc modes_of_payment = frappe.get_all('Mode of Payment', order_by='name') - docstatus = frappe.get_value('Check Run', doc.name, 'docstatus') - if docstatus and docstatus > 0: - return {'transactions': json.loads(frappe.get_value('Check Run', doc.name, 'transactions')), 'modes_of_payment': modes_of_payment} - + if frappe.db.exists('Check Run', doc.name): + db_doc = frappe.get_doc('Check Run', doc.name) + print("dirty", db_doc.is_dirty(doc)) + if db_doc.docstatus > 0 or not db_doc.is_dirty(doc): + return {'transactions': json.loads(frappe.get_value('Check Run', doc.name, 'transactions')), 'modes_of_payment': modes_of_payment} transactions = frappe.db.sql(""" ( SELECT @@ -341,6 +349,16 @@ def get_entries(doc): return {'transactions': transactions, 'modes_of_payment': modes_of_payment} +@frappe.whitelist() +def get_balance(doc): + doc = frappe._dict(json.loads(doc)) if isinstance(doc, str) else doc + print(doc) + if not doc.bank_account or not doc.check_run_date: + return + gl_account = frappe.get_value('Bank Account', doc.bank_account, 'account') + return get_balance_on(gl_account, doc.check_run_date) + + def mode_dimensions_from_doc_items(doc, dimension='cost_center'): return mode_dimensions(doc.items, dimension) diff --git a/check_run/check_run/doctype/check_run/test_data.py b/check_run/check_run/doctype/check_run/test_data.py index 077a03b6..a42d3168 100644 --- a/check_run/check_run/doctype/check_run/test_data.py +++ b/check_run/check_run/doctype/check_run/test_data.py @@ -96,7 +96,7 @@ def create_invoices(): for supplier in suppliers: pi = frappe.new_doc('Purchase Invoice') pi.company = company - pi.set_posting_date = 1 + pi.set_posting_time = 1 pi.posting_date = day pi.supplier = supplier[0] pi.append('items', { @@ -109,7 +109,7 @@ def create_invoices(): # two electric meters / test invoice aggregation pi = frappe.new_doc('Purchase Invoice') pi.company = company - pi.set_posting_date = 1 + pi.set_posting_time = 1 pi.posting_date = day pi.supplier = suppliers[0][0] pi.append('items', { @@ -125,7 +125,7 @@ def create_invoices(): for supplier in suppliers: pi = frappe.new_doc('Purchase Invoice') pi.company = company - pi.set_posting_date = 1 + pi.set_posting_time = 1 pi.posting_date = next_day pi.supplier = supplier[0] pi.append('items', { @@ -138,7 +138,7 @@ def create_invoices(): # two electric meters / test invoice aggregation pi = frappe.new_doc('Purchase Invoice') pi.company = company - pi.set_posting_date = 1 + pi.set_posting_time = 1 pi.posting_date = next_day pi.supplier = suppliers[0][0] pi.append('items', { diff --git a/check_run/public/js/check_run/CheckRun.vue b/check_run/public/js/check_run/CheckRun.vue index 9244139a..d7b64f55 100644 --- a/check_run/public/js/check_run/CheckRun.vue +++ b/check_run/public/js/check_run/CheckRun.vue @@ -1,107 +1,104 @@ diff --git a/check_run/public/js/check_run/check_run.js b/check_run/public/js/check_run/check_run.js index fcd6328a..4b3e9d49 100644 --- a/check_run/public/js/check_run/check_run.js +++ b/check_run/public/js/check_run/check_run.js @@ -2,9 +2,16 @@ import CheckRun from './CheckRun.vue' frappe.provide('check_run') -check_run.mount_table = (frm, wrapper) => { - if (frm.$check_run instanceof Vue) { return } - window.Vue.component('CheckRun', CheckRun) +check_run.mount_table = frm => { + if (frm.$check_run instanceof Vue) { + console.log('existing vue app') + frm.check_run_state.docstatus = frm.doc.docstatus + frm.check_run_state.transactions = frm.transactions + frm.check_run_state.modes_of_payment = state.modes_of_payment + frm.check_run_state.state = state + frm.$check_run.$forceUpdate() + return + } const state = Vue.observable({ transactions: frm.transactions, party_filter: "", @@ -12,27 +19,19 @@ check_run.mount_table = (frm, wrapper) => { modes_of_payment: frm.modes_of_payment, show_party_filter: false }) - if (frm.$check_run instanceof Vue) { - frm.check_run_state.docstatus = frm.doc.docstatus; - frm.check_run_state.transactions = frm.transactions; - frm.check_run_state.modes_of_payment = state.modes_of_payment; - frm.check_run_state.state = state; - frm.$check_run_vue.$forceUpdate(); - return; - } - frm.check_run_state = state; + frm.check_run_state = state + // if (frm.$check_run instanceof Vue) { return } frm.$check_run = new window.Vue({ - el: wrapper.get(0), + el: $(frm.fields_dict['check_run_table'].wrapper).get(0), render: h => h( CheckRun, { props: { transactions: state.transactions, //list of transtactions - modes_of_payment: state.modes_of_payment, // populate modes_of_payment select. doesn't get updated + modes_of_payment: state.modes_of_payment, // populate modes_of_payment select. doesn't get updated docstatus: state.docstatus, // used to conditionally render column inputs based on submission status. doesn't get updated state: state } - }), + }) }) -} -// }) \ No newline at end of file +} \ No newline at end of file