diff --git a/check_run/check_run/custom/sales_taxes_and_charges.json b/check_run/check_run/custom/sales_taxes_and_charges.json new file mode 100644 index 00000000..ad216fb9 --- /dev/null +++ b/check_run/check_run/custom/sales_taxes_and_charges.json @@ -0,0 +1,343 @@ +{ + "custom_fields": [ + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2024-03-18 16:34:51.370673", + "default": null, + "depends_on": null, + "description": "Computed from Party's Default Payment Terms Template", + "docstatus": 0, + "dt": "Sales Taxes and Charges", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "due_date", + "fieldtype": "Date", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 12, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "insert_after": "rate", + "is_system_generated": 0, + "is_virtual": 0, + "label": "Due Date", + "length": 0, + "mandatory_depends_on": null, + "modified": "2024-03-18 16:35:47.872089", + "modified_by": "Administrator", + "module": "Check Run", + "name": "Sales Taxes and Charges-due_date", + "no_copy": 0, + "non_negative": 0, + "options": null, + "owner": "Administrator", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 1, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2024-03-17 15:02:35.468133", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Sales Taxes and Charges", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "party", + "fieldtype": "Dynamic Link", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 16, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "insert_after": "party_type", + "is_system_generated": 0, + "is_virtual": 0, + "label": "Party", + "length": 0, + "mandatory_depends_on": null, + "modified": "2024-03-17 15:03:08.556714", + "modified_by": "Administrator", + "module": "Check Run", + "name": "Sales Taxes and Charges-party", + "no_copy": 0, + "non_negative": 0, + "options": "party_type", + "owner": "Administrator", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 0, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2024-03-17 15:02:12.828520", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Sales Taxes and Charges", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "column_break_w4usy", + "fieldtype": "Column Break", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 14, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "insert_after": "due_date", + "is_system_generated": 0, + "is_virtual": 0, + "label": "", + "length": 0, + "mandatory_depends_on": null, + "modified": "2024-03-17 15:02:12.828520", + "modified_by": "Administrator", + "module": "Check Run", + "name": "Sales Taxes and Charges-column_break_w4usy", + "no_copy": 0, + "non_negative": 0, + "options": null, + "owner": "Administrator", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 0, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2024-03-17 15:00:24.982447", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Sales Taxes and Charges", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "party_type", + "fieldtype": "Link", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 15, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "insert_after": "column_break_w4usy", + "is_system_generated": 0, + "is_virtual": 0, + "label": "Party Type", + "length": 0, + "mandatory_depends_on": null, + "modified": "2024-03-17 15:01:18.595361", + "modified_by": "Administrator", + "module": "Check Run", + "name": "Sales Taxes and Charges-party_type", + "no_copy": 0, + "non_negative": 0, + "options": "DocType", + "owner": "Administrator", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 0, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2024-03-17 15:00:24.982447", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Sales Taxes and Charges", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "outstanding_amount", + "fieldtype": "Currency", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 25, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "insert_after": "base_tax_amount_after_discount_amount", + "is_system_generated": 0, + "is_virtual": 0, + "label": "Outstanding Amount", + "length": 0, + "mandatory_depends_on": null, + "modified": "2024-03-17 15:01:18.595361", + "modified_by": "Administrator", + "module": "Check Run", + "name": "Sales Taxes and Charges-outstanding_amount", + "no_copy": 0, + "non_negative": 0, + "options": null, + "owner": "Administrator", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 1, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "unique": 0, + "width": null + } + ], + "custom_perms": [], + "doctype": "Sales Taxes and Charges", + "links": [], + "property_setters": [ + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2024-03-21 19:34:38.165497", + "default_value": null, + "doc_type": "Sales Taxes and Charges", + "docstatus": 0, + "doctype_or_field": "DocType", + "field_name": null, + "idx": 0, + "is_system_generated": 0, + "modified": "2024-03-21 19:34:38.165497", + "modified_by": "Administrator", + "module": "Check Run", + "name": "Sales Taxes and Charges-main-field_order", + "owner": "Administrator", + "property": "field_order", + "property_type": "Data", + "row_name": null, + "value": "[\"charge_type\", \"row_id\", \"account_head\", \"col_break_1\", \"description\", \"included_in_print_rate\", \"included_in_paid_amount\", \"accounting_dimensions_section\", \"cost_center\", \"dimension_col_break\", \"section_break_8\", \"rate\", \"due_date\", \"column_break_w4usy\", \"party_type\", \"party\", \"section_break_9\", \"account_currency\", \"tax_amount\", \"total\", \"tax_amount_after_discount_amount\", \"column_break_13\", \"base_tax_amount\", \"base_total\", \"base_tax_amount_after_discount_amount\", \"outstanding_amount\", \"item_wise_tax_detail\", \"dont_recompute_tax\"]" + } + ], + "sync_on_migrate": 1 +} diff --git a/check_run/check_run/doctype/check_run/check_run.py b/check_run/check_run/doctype/check_run/check_run.py index 009f3d9d..ffc74ef9 100644 --- a/check_run/check_run/doctype/check_run/check_run.py +++ b/check_run/check_run/doctype/check_run/check_run.py @@ -317,6 +317,8 @@ def create_payment_entries(self: Self, transactions: list[frappe._dict]) -> list party = frappe.db.get_value("Expense Claim", group[0].name, "employee") elif group[0].doctype == "Journal Entry": party = frappe.db.get_value("Journal Entry Account", group[0].name, "party") + elif group[0].doctype == "Sales Invoice": + party = group[0].party pe = frappe.new_doc("Payment Entry") pe.payment_type = "Pay" pe.posting_date = nowdate() @@ -353,14 +355,17 @@ def create_payment_entries(self: Self, transactions: list[frappe._dict]) -> list ): if frappe.get_value(reference.doctype, reference.name, "on_hold"): frappe.db.set_value(reference.doctype, reference.name, "on_hold", 0) - if reference.doctype == "Journal Entry": + if reference.doctype in ("Journal Entry", "Sales Invoice"): reference_name = reference.ref_number else: reference_name = reference.name or reference.ref_number + pe.append( "references", { - "reference_doctype": reference.doctype, + "reference_doctype": reference.doctype + if reference.doctype != "Sales Invoice" + else "Sales Taxes and Charges", "reference_name": reference_name, "due_date": reference.get("due_date"), "outstanding_amount": flt(reference.amount), @@ -433,7 +438,7 @@ def render_check_pdf(self: Self, reprint_check_number: int | None = None) -> Non initial_check_number = int(self.initial_check_number) if reprint_check_number and reprint_check_number != "undefined": self.initial_check_number = int(reprint_check_number) - # output = PdfFileWriter() + output = PdfWriter() transactions = json.loads(self.transactions) check_increment = 0 @@ -675,6 +680,37 @@ def get_entries(doc: CheckRun | str) -> dict: .where((journal_entries.name).notin(sub_q)) ) + # build Sales Taxes and Charges query + sales_taxes = frappe.qb.DocType("Sales Taxes and Charges") + sales_invoice = frappe.qb.DocType("Sales Invoice") + st_qb = ( + frappe.qb.from_(sales_taxes) + .inner_join(sales_invoice) + .on(sales_taxes.parent == sales_invoice.name) + .inner_join(suppliers) + .on(suppliers.name == sales_taxes.party) + .select( + ConstantColumn("Sales Invoice").as_("doctype"), + sales_taxes.party_type, + sales_taxes.parent.as_("ref_number"), + sales_taxes.name, + sales_taxes.party, + (sales_taxes.party).as_("party_name"), + (sales_taxes.tax_amount_after_discount_amount).as_("amount"), + Coalesce(sales_taxes.due_date, sales_invoice.posting_date).as_("due_date"), + sales_invoice.posting_date, + Coalesce( + NullIf(suppliers.supplier_default_mode_of_payment, ""), + f"{settings.tax_payable}" or "\n", + ).as_("mode_of_payment"), + ConstantColumn("").as_("payment_term"), + ) + .where(sales_invoice.company == company) + .where(sales_invoice.docstatus == 1) + .where(sales_taxes.account_head == pay_to_account) + .where(sales_invoice.posting_date <= end_date) + ) + if not settings: query = pi_qb.union(ec_qb).union(je_qb) else: @@ -683,8 +719,9 @@ def get_entries(doc: CheckRun | str) -> dict: settings.include_purchase_invoices, settings.include_expense_claims, settings.include_journal_entries, + settings.include_tax_payable, ) - for flag, qb in zip(flags, (pi_qb, ec_qb, je_qb)): + for flag, qb in zip(flags, (pi_qb, ec_qb, je_qb, st_qb)): if not flag: continue if not query: 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 61f88ea0..2b05d4f3 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,276 +1,282 @@ { - "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", - "role_allowed_to_download_ach_file_multiple_times" - ], - "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" - }, - { - "description": "Users with this role are allowed to download ACH file multiple times. Users without this role are allowed to download it only once.", - "fieldname": "role_allowed_to_download_ach_file_multiple_times", - "fieldtype": "Link", - "label": "Role Allowed to Download ACH File Multiple Times", - "options": "Role" - } - ], - "links": [], - "modified": "2024-04-29 08:51:46.252826", - "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", + "include_tax_payable", + "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", + "tax_payable", + "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" + }, + { + "default": "0", + "fieldname": "include_tax_payable", + "fieldtype": "Check", + "label": "Include Tax Payable from Sales Invoices" + }, + { + "fieldname": "tax_payable", + "fieldtype": "Link", + "label": "Sales Tax Payable", + "options": "Mode of Payment" + } + ], + "links": [], + "modified": "2024-03-18 19:55:45.662405", + "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 } diff --git a/check_run/hooks.py b/check_run/hooks.py index 1def385d..f44d4c9f 100644 --- a/check_run/hooks.py +++ b/check_run/hooks.py @@ -96,9 +96,11 @@ # DocType Class # --------------- # Override standard doctype classes + override_doctype_class = { - # "Bank": "check_run.overrides.bank.CustomBank", "Payment Entry": "check_run.overrides.payment_entry.CheckRunPaymentEntry", + "Sales Invoice": "check_run.overrides.sales_invoice.CheckRunSalesInvoice", + "Sales Taxes and Charges": "check_run.overrides.sales_taxes_and_charges.CheckRunSalesTaxesandCharges", } # Document Events @@ -112,7 +114,10 @@ "check_run.overrides.payment_entry.validate_duplicate_check_number", "check_run.overrides.payment_entry.validate_add_payment_term", ], - "on_submit": ["check_run.overrides.payment_entry.update_check_number"], + "on_submit": [ + "check_run.overrides.payment_entry.update_check_number", + "check_run.overrides.payment_entry.update_sales_tax_payable_outstanding", + ], }, "Purchase Invoice": { "before_cancel": ["check_run.check_run.disallow_cancellation_if_in_check_run"] diff --git a/check_run/overrides/payment_entry.py b/check_run/overrides/payment_entry.py index 8656185e..46ca7473 100644 --- a/check_run/overrides/payment_entry.py +++ b/check_run/overrides/payment_entry.py @@ -1,16 +1,19 @@ # Copyright (c) 2023, AgriTheory and contributors # For license information, please see license.txt +import json import frappe -from frappe.utils import get_link_to_form, comma_and, flt + +from frappe import _, scrub from erpnext.accounts.general_ledger import make_gl_entries, process_gl_map -from frappe.utils.data import getdate +from frappe.utils import comma_or, comma_and, flt, getdate, get_link_to_form from erpnext.accounts.doctype.payment_entry.payment_entry import ( PaymentEntry, get_outstanding_reference_documents, ) -from frappe import _ -import json +from erpnext.accounts.doctype.invoice_discounting.invoice_discounting import ( + get_party_account_based_on_invoice_discounting, +) class CheckRunPaymentEntry(PaymentEntry): @@ -51,12 +54,84 @@ def get_valid_reference_doctypes(self): if self.party_type == "Customer": return ("Sales Order", "Sales Invoice", "Journal Entry", "Dunning") elif self.party_type == "Supplier": - return ("Purchase Order", "Purchase Invoice", "Journal Entry") + return ( + "Purchase Order", + "Purchase Invoice", + "Journal Entry", + "Sales Taxes and Charges", + ) # Tax Payable elif self.party_type == "Shareholder": return ("Journal Entry",) elif self.party_type == "Employee": return ("Journal Entry", "Expense Claim") # Expense Claim + def validate_reference_documents(self): + valid_reference_doctypes = self.get_valid_reference_doctypes() + + if not valid_reference_doctypes: + return + + for d in self.get("references"): + if not d.allocated_amount: + continue + if d.reference_doctype not in valid_reference_doctypes: + frappe.throw( + _("Reference Doctype must be one of {0}").format( + comma_or(_(d) for d in valid_reference_doctypes) + ) + ) + + elif d.reference_name: + if not frappe.db.exists(d.reference_doctype, d.reference_name): + frappe.throw(_("{0} {1} does not exist").format(d.reference_doctype, d.reference_name)) + else: + ref_doc = frappe.get_doc(d.reference_doctype, d.reference_name) + if d.reference_doctype == "Sales Taxes and Charges": + if self.party != ref_doc.party: + frappe.throw( + _("{0} {1} is not associated with {2} {3}").format( + _(d.reference_doctype), d.reference_name, _(self.party_type), self.party + ) + ) + elif d.reference_doctype != "Journal Entry": + if self.party != ref_doc.get(scrub(self.party_type)): + frappe.throw( + _("{0} {1} is not associated with {2} {3}").format( + _(d.reference_doctype), d.reference_name, _(self.party_type), self.party + ) + ) + else: + self.validate_journal_entry() + + if d.reference_doctype in frappe.get_hooks("invoice_doctypes"): + if self.party_type == "Customer": + ref_party_account = ( + get_party_account_based_on_invoice_discounting(d.reference_name) or ref_doc.debit_to + ) + elif self.party_type == "Supplier": + ref_party_account = ref_doc.credit_to + elif self.party_type == "Employee": + ref_party_account = ref_doc.payable_account + + if ( + ref_party_account != self.party_account + and not self.book_advance_payments_in_separate_party_account + ): + frappe.throw( + _("{0} {1} is associated with {2}, but Party Account is {3}").format( + _(d.reference_doctype), d.reference_name, ref_party_account, self.party_account + ) + ) + + if ref_doc.doctype == "Purchase Invoice" and ref_doc.get("on_hold"): + frappe.throw( + _("{0} {1} is on hold").format(_(d.reference_doctype), d.reference_name), + title=_("Invalid Purchase Invoice"), + ) + + if ref_doc.docstatus != 1: + frappe.throw(_("{0} {1} must be submitted").format(_(d.reference_doctype), d.reference_name)) + """ Because Check Run processes multiple payment entries in a background queue, errors generally do not include enough data to identify the problem since there were written and remain appropriate for the context of an individual @@ -126,8 +201,9 @@ def validate_allocated_amount_with_latest_data(self): latest_lookup.setdefault((d.voucher_type, d.voucher_no), frappe._dict())[d.payment_term] = d for idx, d in enumerate(self.get("references"), start=1): + if d.reference_doctype == "Sales Taxes and Charges": + continue latest = latest_lookup.get((d.reference_doctype, d.reference_name)) or frappe._dict() - # If term based allocation is enabled, throw if ( d.payment_term is None or d.payment_term == "" @@ -273,3 +349,18 @@ def validate_add_payment_term(doc: PaymentEntry, method: str | None = None): ), title=frappe._("Payment Schedule Term Added"), ) + + +@frappe.whitelist() +def update_sales_tax_payable_outstanding(doc, method=None): + for r in doc.get("references"): + if r.reference_doctype == "Sales Taxes and Charges": + currently_outstanding = frappe.db.get_value( + "Sales Taxes and Charges", r.reference_name, "outstanding_amount" + ) + frappe.db.set_value( + "Sales Taxes and Charges", + r.reference_name, + "outstanding_amount", + flt(currently_outstanding - r.allocated_amount), + ) diff --git a/check_run/overrides/sales_invoice.py b/check_run/overrides/sales_invoice.py new file mode 100644 index 00000000..88e4f3ef --- /dev/null +++ b/check_run/overrides/sales_invoice.py @@ -0,0 +1,60 @@ +import frappe +from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( + get_accounting_dimensions, +) +from erpnext.accounts.doctype.sales_invoice.sales_invoice import SalesInvoice +from erpnext.accounts.party import get_due_date +from erpnext.accounts.utils import get_account_currency +from frappe.utils.data import cint, flt + + +class CheckRunSalesInvoice(SalesInvoice): + def validate(self): + super().validate() + for row in self.taxes: + if not row.party: + continue + due_date = get_due_date(self.posting_date, row.party_type, row.party, self.company) + row.due_date = due_date or self.posting_date + row.outstanding_amount = row.tax_amount + + def on_submit(self): + for row in self.taxes: + if row.party and row.party_type: + row.outstanding_amount = row.tax_amount + super().on_submit() + + def make_tax_gl_entries(self, gl_entries): + enable_discount_accounting = cint( + frappe.db.get_single_value("Selling Settings", "enable_discount_accounting") + ) + + accounting_dimensions = get_accounting_dimensions() + for tax in self.get("taxes"): + amount, base_amount = self.get_tax_amounts(tax, enable_discount_accounting) + if flt(tax.base_tax_amount_after_discount_amount): + account_currency = get_account_currency(tax.account_head) + is_payable_account = bool( + frappe.get_value("Account", tax.account_head, "account_type") == "Payable" + ) + dimensions = {d: tax.get(d) for d in accounting_dimensions} + gl_entries.append( + self.get_gl_dict( + { + "account": tax.account_head, + "against": self.customer, + "credit": flt(base_amount, tax.precision("tax_amount_after_discount_amount")), + "credit_in_account_currency": ( + flt(base_amount, tax.precision("base_tax_amount_after_discount_amount")) + if account_currency == self.company_currency + else flt(amount, tax.precision("tax_amount_after_discount_amount")) + ), + "cost_center": tax.cost_center, + "party_type": tax.party_type if is_payable_account else None, + "party": tax.party if is_payable_account else None, + **dimensions, + }, + account_currency, + item=tax, + ) + ) diff --git a/check_run/overrides/sales_taxes_and_charges.py b/check_run/overrides/sales_taxes_and_charges.py new file mode 100644 index 00000000..0cc1bcd4 --- /dev/null +++ b/check_run/overrides/sales_taxes_and_charges.py @@ -0,0 +1,10 @@ +import frappe +from erpnext.accounts.doctype.sales_taxes_and_charges.sales_taxes_and_charges import ( + SalesTaxesandCharges, +) + + +class CheckRunSalesTaxesandCharges(SalesTaxesandCharges): + @property + def company(self): + return frappe.get_value("Sales Invoice", self.parent, "company") diff --git a/check_run/public/js/check_run/CheckRun.vue b/check_run/public/js/check_run/CheckRun.vue index eec835c5..5db3e759 100644 --- a/check_run/public/js/check_run/CheckRun.vue +++ b/check_run/public/js/check_run/CheckRun.vue @@ -63,7 +63,7 @@ {{ item.party_name || item.party }} - {{ item.ref_number || item.name }} + {{ item.doctype != 'Sales Invoice' ? item.ref_number : item.name }}