From d4ab6ca0884d13de687d4e38f6fa9d28cd84aa37 Mon Sep 17 00:00:00 2001 From: maniamartial Date: Fri, 29 Nov 2024 12:26:03 +0300 Subject: [PATCH 1/5] fix - search stock movement in all branch(initial fix) --- .../kenya_compliance/apis/apis.py | 14 +- .../apis/remote_response_status_handlers.py | 13 +- ...navari_etims_registered_imported_item.json | 349 +++++++++--------- ...ri_etims_registered_stock_movement_list.js | 124 +++---- 4 files changed, 260 insertions(+), 240 deletions(-) diff --git a/kenya_compliance/kenya_compliance/apis/apis.py b/kenya_compliance/kenya_compliance/apis/apis.py index 49f0886..0c8fcf2 100644 --- a/kenya_compliance/kenya_compliance/apis/apis.py +++ b/kenya_compliance/kenya_compliance/apis/apis.py @@ -612,7 +612,6 @@ def perform_stock_movement_search(request_data: str, vendor="OSCU KRA") -> None: if headers and server_url and route_path: url = f"{server_url}{route_path}" payload = {"lastReqDt": request_date} - endpoints_builder.headers = headers endpoints_builder.url = url endpoints_builder.payload = payload @@ -627,6 +626,18 @@ def perform_stock_movement_search(request_data: str, vendor="OSCU KRA") -> None: job_name=token_hex(100), ) +@frappe.whitelist() +def perform_stock_movement_search_all_branches() -> None: + all_credentials = frappe.get_all( + SETTINGS_DOCTYPE_NAME, + ["name", "bhfid", "communication_key", "tin", "company"], + ) + + for credential in all_credentials: + request_data = json.dumps( + {"company_name": credential.company, "branch_id": credential.bhfid} + ) + perform_stock_movement_search(request_data) @frappe.whitelist() def submit_item_composition(request_data: str, vendor="OSCU KRA") -> None: @@ -727,7 +738,6 @@ def create_supplier(supplier_details: dict) -> Document: @frappe.whitelist() def create_items_from_fetched_registered_purchases(request_data: str) -> None: data = json.loads(request_data) - if data["items"]: items = data["items"] for item in items: diff --git a/kenya_compliance/kenya_compliance/apis/remote_response_status_handlers.py b/kenya_compliance/kenya_compliance/apis/remote_response_status_handlers.py index 74416e9..953c4b2 100644 --- a/kenya_compliance/kenya_compliance/apis/remote_response_status_handlers.py +++ b/kenya_compliance/kenya_compliance/apis/remote_response_status_handlers.py @@ -120,7 +120,6 @@ def submit_inventory_on_success(response: dict, document_name: str) -> None: {"custom_inventory_submitted_successfully": 1}, ) - def sales_information_submission_on_success( response: dict, invoice_type: str, @@ -370,7 +369,13 @@ def create_if_not_exists(doctype: str, code: str) -> str: for item in items: doc = frappe.new_doc(REGISTERED_IMPORTED_ITEM_DOCTYPE_NAME) - + if frappe.db.exists( + REGISTERED_IMPORTED_ITEM_DOCTYPE_NAME, + { + "task_code": item["taskCd"], + }, + ): + continue doc.item_name = item["itemNm"] doc.task_code = item["taskCd"] doc.declaration_date = datetime.strptime(item["dclDe"], "%d%m%Y") @@ -398,14 +403,14 @@ def create_if_not_exists(doctype: str, code: str) -> str: doc.invoice_foreign_currency_amount = item["invcFcurAmt"] doc.invoice_foreign_currency = item["invcFcurCd"] doc.invoice_foreign_currency_rate = item["invcFcurExcrt"] + doc.rate = item["invcFcurAmt"] / item["qty"] doc.save() frappe.msgprint( "Imported Items Fetched. Go to Navari eTims Registered Imported Item Doctype for more information" ) - - + def search_branch_request_on_success(response: dict) -> None: for branch in response["data"]["bhfList"]: doc = None diff --git a/kenya_compliance/kenya_compliance/doctype/navari_etims_registered_imported_item/navari_etims_registered_imported_item.json b/kenya_compliance/kenya_compliance/doctype/navari_etims_registered_imported_item/navari_etims_registered_imported_item.json index ffd1573..166ad8b 100644 --- a/kenya_compliance/kenya_compliance/doctype/navari_etims_registered_imported_item/navari_etims_registered_imported_item.json +++ b/kenya_compliance/kenya_compliance/doctype/navari_etims_registered_imported_item/navari_etims_registered_imported_item.json @@ -1,172 +1,179 @@ { - "actions": [], - "allow_rename": 1, - "autoname": "field:task_code", - "creation": "2024-05-06 10:19:33.747064", - "doctype": "DocType", - "engine": "InnoDB", - "field_order": [ - "item_name", - "origin_nation_code", - "declaration_date", - "item_sequence", - "gross_weight", - "package", - "quantity", - "suppliers_name", - "invoice_foreign_currency_amount", - "column_break_cbnh", - "task_code", - "export_nation_code", - "declaration_number", - "hs_code", - "net_weight", - "packaging_unit_code", - "quantity_unit_code", - "agent_name", - "invoice_foreign_currency", - "invoice_foreign_currency_rate" - ], - "fields": [ - { - "fieldname": "item_name", - "fieldtype": "Data", - "label": "Item Name" - }, - { - "fieldname": "task_code", - "fieldtype": "Data", - "label": "Task Code", - "unique": 1 - }, - { - "fieldname": "declaration_date", - "fieldtype": "Date", - "label": "Declaration Date" - }, - { - "fieldname": "item_sequence", - "fieldtype": "Int", - "label": "Item Sequence" - }, - { - "fieldname": "declaration_number", - "fieldtype": "Data", - "label": "Declaration Number" - }, - { - "fieldname": "hs_code", - "fieldtype": "Data", - "label": "HS Code" - }, - { - "fieldname": "column_break_cbnh", - "fieldtype": "Column Break" - }, - { - "fieldname": "origin_nation_code", - "fieldtype": "Link", - "label": "Origin Nation Code", - "options": "Navari eTims Country" - }, - { - "fieldname": "export_nation_code", - "fieldtype": "Link", - "label": "Export Nation Code", - "options": "Navari eTims Country" - }, - { - "fieldname": "package", - "fieldtype": "Data", - "label": "Package" - }, - { - "fieldname": "packaging_unit_code", - "fieldtype": "Link", - "label": "Packaging Unit Code", - "options": "Navari eTims Packaging Unit" - }, - { - "fieldname": "quantity", - "fieldtype": "Int", - "label": "Quantity" - }, - { - "fieldname": "quantity_unit_code", - "fieldtype": "Link", - "label": "Quantity Unit Code", - "options": "Navari eTims Unit of Quantity" - }, - { - "fieldname": "gross_weight", - "fieldtype": "Float", - "label": "Gross Weight", - "precision": "2" - }, - { - "fieldname": "net_weight", - "fieldtype": "Float", - "label": "Net Weight" - }, - { - "fieldname": "suppliers_name", - "fieldtype": "Data", - "label": "Supplier's Name" - }, - { - "fieldname": "agent_name", - "fieldtype": "Data", - "label": "Agent Name" - }, - { - "fieldname": "invoice_foreign_currency_amount", - "fieldtype": "Data", - "label": "Invoice Foreign Currency Amount" - }, - { - "fieldname": "invoice_foreign_currency", - "fieldtype": "Data", - "label": "Invoice Foreign Currency" - }, - { - "fieldname": "invoice_foreign_currency_rate", - "fieldtype": "Data", - "label": "Invoice Foreign Currency Rate" - } - ], - "in_create": 1, - "index_web_pages_for_search": 1, - "links": [ - { - "link_doctype": "Purchase Invoice", - "link_fieldname": "custom_source_registered_imported_item" - } - ], - "modified": "2024-08-30 15:47:26.632485", - "modified_by": "Administrator", - "module": "Kenya Compliance", - "name": "Navari eTims Registered Imported Item", - "naming_rule": "By fieldname", - "owner": "Administrator", - "permissions": [ - { - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "print": 1, - "read": 1, - "report": 1, - "role": "System Manager", - "share": 1, - "write": 1 - } - ], - "search_fields": "item_name, task_code", - "show_title_field_in_link": 1, - "sort_field": "modified", - "sort_order": "DESC", - "states": [], - "title_field": "item_name", - "track_changes": 1 -} + "actions": [], + "allow_rename": 1, + "autoname": "field:task_code", + "creation": "2024-05-06 10:19:33.747064", + "doctype": "DocType", + "engine": "InnoDB", + "field_order": [ + "item_name", + "origin_nation_code", + "declaration_date", + "item_sequence", + "gross_weight", + "package", + "quantity", + "suppliers_name", + "invoice_foreign_currency_amount", + "rate", + "column_break_cbnh", + "task_code", + "export_nation_code", + "declaration_number", + "hs_code", + "net_weight", + "packaging_unit_code", + "quantity_unit_code", + "agent_name", + "invoice_foreign_currency", + "invoice_foreign_currency_rate" + ], + "fields": [ + { + "fieldname": "item_name", + "fieldtype": "Data", + "label": "Item Name" + }, + { + "fieldname": "task_code", + "fieldtype": "Data", + "label": "Task Code", + "unique": 1 + }, + { + "fieldname": "declaration_date", + "fieldtype": "Date", + "label": "Declaration Date" + }, + { + "fieldname": "item_sequence", + "fieldtype": "Int", + "label": "Item Sequence" + }, + { + "fieldname": "declaration_number", + "fieldtype": "Data", + "label": "Declaration Number" + }, + { + "fieldname": "hs_code", + "fieldtype": "Data", + "label": "HS Code" + }, + { + "fieldname": "column_break_cbnh", + "fieldtype": "Column Break" + }, + { + "fieldname": "origin_nation_code", + "fieldtype": "Link", + "label": "Origin Nation Code", + "options": "Navari eTims Country" + }, + { + "fieldname": "export_nation_code", + "fieldtype": "Link", + "label": "Export Nation Code", + "options": "Navari eTims Country" + }, + { + "fieldname": "package", + "fieldtype": "Data", + "label": "Package" + }, + { + "fieldname": "packaging_unit_code", + "fieldtype": "Link", + "label": "Packaging Unit Code", + "options": "Navari eTims Packaging Unit" + }, + { + "fieldname": "quantity", + "fieldtype": "Int", + "label": "Quantity" + }, + { + "fieldname": "quantity_unit_code", + "fieldtype": "Link", + "label": "Quantity Unit Code", + "options": "Navari eTims Unit of Quantity" + }, + { + "fieldname": "gross_weight", + "fieldtype": "Float", + "label": "Gross Weight", + "precision": "2" + }, + { + "fieldname": "net_weight", + "fieldtype": "Float", + "label": "Net Weight" + }, + { + "fieldname": "suppliers_name", + "fieldtype": "Data", + "label": "Supplier's Name" + }, + { + "fieldname": "agent_name", + "fieldtype": "Data", + "label": "Agent Name" + }, + { + "fieldname": "invoice_foreign_currency_amount", + "fieldtype": "Data", + "label": "Invoice Foreign Currency Amount" + }, + { + "fieldname": "invoice_foreign_currency", + "fieldtype": "Data", + "label": "Invoice Foreign Currency" + }, + { + "fieldname": "invoice_foreign_currency_rate", + "fieldtype": "Data", + "label": "Invoice Foreign Currency Rate" + }, + { + "fieldname": "rate", + "fieldtype": "Currency", + "label": "Rate", + "options": "invoice_foreign_currency" + } + ], + "in_create": 1, + "index_web_pages_for_search": 1, + "links": [ + { + "link_doctype": "Purchase Invoice", + "link_fieldname": "custom_source_registered_imported_item" + } + ], + "modified": "2024-11-29 10:29:23.412182", + "modified_by": "Administrator", + "module": "Kenya Compliance", + "name": "Navari eTims Registered Imported Item", + "naming_rule": "By fieldname", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, + "write": 1 + } + ], + "search_fields": "item_name, task_code", + "show_title_field_in_link": 1, + "sort_field": "modified", + "sort_order": "DESC", + "states": [], + "title_field": "item_name", + "track_changes": 1 +} \ No newline at end of file diff --git a/kenya_compliance/kenya_compliance/doctype/navari_etims_registered_stock_movement/navari_etims_registered_stock_movement_list.js b/kenya_compliance/kenya_compliance/doctype/navari_etims_registered_stock_movement/navari_etims_registered_stock_movement_list.js index 6a4db63..838cf6b 100644 --- a/kenya_compliance/kenya_compliance/doctype/navari_etims_registered_stock_movement/navari_etims_registered_stock_movement_list.js +++ b/kenya_compliance/kenya_compliance/doctype/navari_etims_registered_stock_movement/navari_etims_registered_stock_movement_list.js @@ -1,30 +1,3 @@ -// const doctypeName = "Navari eTims Registered Stock Movement"; - -// frappe.listview_settings[doctypeName] = { -// onload: function (listview) { -// const companyName = frappe.boot.sysdefaults.company; - -// listview.page.add_inner_button( -// __("Get Stock Movements"), -// function (listview) { -// frappe.call({ -// method: -// "kenya_compliance.kenya_compliance.apis.apis.perform_stock_movement_search", -// args: { -// request_data: { -// company_name: companyName, -// branch_id: "", -// }, -// }, -// callback: (response) => {}, -// error: (error) => { -// // Error Handling is Defered to the Server -// }, -// }); -// }, -// ); -// }, -// }; const doctypeName = "Navari eTims Registered Stock Movement"; frappe.listview_settings[doctypeName] = { @@ -33,47 +6,72 @@ frappe.listview_settings[doctypeName] = { listview.page.add_inner_button( __("Get Stock Movements"), - function () { - // Create a dialog to select a branch - const branchDialog = new frappe.ui.Dialog({ - title: __("Select Branch"), - fields: [ - { - label: __("Branch"), - fieldname: "branch_id", - fieldtype: "Link", - options: "Branch", - reqd: true, + function (listview) { + frappe.call({ + method: + "kenya_compliance.kenya_compliance.apis.apis.perform_stock_movement_search_all_branches", + args: { + request_data: { + company_name: companyName, }, - ], - primary_action_label: __("Submit"), - primary_action: function (data) { - branchDialog.hide(); - - // Call the server method with the selected branch - frappe.call({ - method: - "kenya_compliance.kenya_compliance.apis.apis.perform_stock_movement_search", - args: { - request_data: { - company_name: companyName, - branch_id: data.branch_id, - }, - }, - callback: (response) => { - frappe.msgprint(__("Stock movements retrieved successfully.")); - }, - error: (error) => { - frappe.msgprint(__("An error occurred while fetching stock movements.")); - }, - }); + }, + callback: (response) => {}, + error: (error) => { }, }); - - // Show the dialog - branchDialog.show(); }, ); }, }; +// const doctypeName = "Navari eTims Registered Stock Movement"; + +// frappe.listview_settings[doctypeName] = { +// onload: function (listview) { +// const companyName = frappe.boot.sysdefaults.company; + +// listview.page.add_inner_button( +// __("Get Stock Movements"), +// function () { +// // Create a dialog to select a branch +// const branchDialog = new frappe.ui.Dialog({ +// title: __("Select Branch"), +// fields: [ +// { +// label: __("Branch"), +// fieldname: "branch_id", +// fieldtype: "Link", +// options: "Branch", +// reqd: true, +// }, +// ], +// primary_action_label: __("Submit"), +// primary_action: function (data) { +// branchDialog.hide(); + +// // Call the server method with the selected branch +// frappe.call({ +// method: +// "kenya_compliance.kenya_compliance.apis.apis.perform_stock_movement_search", +// args: { +// request_data: { +// company_name: companyName, +// branch_id: data.branch_id, +// }, +// }, +// callback: (response) => { +// frappe.msgprint(__("Stock movements retrieved successfully.")); +// }, +// error: (error) => { +// frappe.msgprint(__("An error occurred while fetching stock movements.")); +// }, +// }); +// }, +// }); + +// // Show the dialog +// branchDialog.show(); +// }, +// ); +// }, +// }; From cadd52f9224cac9112b5a00e493da8bd5e4c22b3 Mon Sep 17 00:00:00 2001 From: maniamartial Date: Mon, 2 Dec 2024 13:11:00 +0300 Subject: [PATCH 2/5] feat - Validate item mapped if they exist hide button on registered purchases --- .../kenya_compliance/apis/apis.py | 8 +- ...navari_etims_registered_imported_item.json | 6 +- .../navari_etims_registered_purchases.js | 75 +++- .../navari_etims_registered_purchases.py | 33 +- .../overrides/server/purchase_invoice.py | 381 ++++++++---------- .../overrides/server/sales_invoice.py | 1 + 6 files changed, 255 insertions(+), 249 deletions(-) diff --git a/kenya_compliance/kenya_compliance/apis/apis.py b/kenya_compliance/kenya_compliance/apis/apis.py index 0c8fcf2..95880c5 100644 --- a/kenya_compliance/kenya_compliance/apis/apis.py +++ b/kenya_compliance/kenya_compliance/apis/apis.py @@ -399,13 +399,13 @@ def perform_import_item_search_all_branches() -> None: perform_import_item_search(request_data) @frappe.whitelist() -def perform_purchases_search(request_data: str) -> None: +def perform_purchases_search(request_data: str, vendor: str="OSCU KRA") -> None: data: dict = json.loads(request_data) company_name = data["company_name"] - headers = build_headers(company_name) - server_url = get_server_url(company_name) + headers = build_headers(company_name, vendor) + server_url = get_server_url(company_name, vendor) route_path, last_request_date = get_route_path("TrnsPurchaseSalesReq") if headers and server_url and route_path: @@ -413,7 +413,7 @@ def perform_purchases_search(request_data: str) -> None: url = f"{server_url}{route_path}" payload = {"lastReqDt": request_date} - + frappe.throw(str(payload)) endpoints_builder.headers = headers endpoints_builder.url = url endpoints_builder.payload = payload diff --git a/kenya_compliance/kenya_compliance/doctype/navari_etims_registered_imported_item/navari_etims_registered_imported_item.json b/kenya_compliance/kenya_compliance/doctype/navari_etims_registered_imported_item/navari_etims_registered_imported_item.json index 166ad8b..2c2d5a7 100644 --- a/kenya_compliance/kenya_compliance/doctype/navari_etims_registered_imported_item/navari_etims_registered_imported_item.json +++ b/kenya_compliance/kenya_compliance/doctype/navari_etims_registered_imported_item/navari_etims_registered_imported_item.json @@ -147,9 +147,13 @@ { "link_doctype": "Purchase Invoice", "link_fieldname": "custom_source_registered_imported_item" + }, + { + "link_doctype": "Item", + "link_fieldname": "custom_referenced_imported_item" } ], - "modified": "2024-11-29 10:29:23.412182", + "modified": "2024-12-02 08:48:07.182002", "modified_by": "Administrator", "module": "Kenya Compliance", "name": "Navari eTims Registered Imported Item", diff --git a/kenya_compliance/kenya_compliance/doctype/navari_etims_registered_purchases/navari_etims_registered_purchases.js b/kenya_compliance/kenya_compliance/doctype/navari_etims_registered_purchases/navari_etims_registered_purchases.js index b34d2a9..d4a8f2f 100644 --- a/kenya_compliance/kenya_compliance/doctype/navari_etims_registered_purchases/navari_etims_registered_purchases.js +++ b/kenya_compliance/kenya_compliance/doctype/navari_etims_registered_purchases/navari_etims_registered_purchases.js @@ -30,27 +30,62 @@ frappe.ui.form.on(doctypeName, { }, __('eTims Actions'), ); - frm.add_custom_button( - __('Create Items'), - function () { - frappe.call({ - method: - 'kenya_compliance.kenya_compliance.apis.apis.create_items_from_fetched_registered_purchases', - args: { - request_data: { - name: frm.doc.name, - company_name: companyName, - items: frm.doc.items, + // frm.add_custom_button( + // __('Create Items'), + // function () { + // frappe.call({ + // method: + // 'kenya_compliance.kenya_compliance.apis.apis.create_items_from_fetched_registered_purchases', + // args: { + // request_data: { + // name: frm.doc.name, + // company_name: companyName, + // items: frm.doc.items, + // }, + // }, + // callback: (response) => {}, + // error: (error) => { + // // Error Handling is Defered to the Server + // }, + // }); + // }, + // __('eTims Actions'), + // ); + // Check for unmapped items before adding the "Create Items" button + frappe.call({ + method: 'kenya_compliance.kenya_compliance.doctype.navari_etims_registered_purchases.navari_etims_registered_purchases.validate_item_mapped_and_registered', + args: { + items: frm.doc.items, + }, + callback: (response) => { + if (response.message === false) { + frm.add_custom_button( + __('Create Items'), + function () { + frappe.call({ + method: + 'kenya_compliance.kenya_compliance.apis.apis.create_items_from_fetched_registered_purchases', + args: { + request_data: { + name: frm.doc.name, + company_name: companyName, + items: frm.doc.items, + }, }, - }, - callback: (response) => {}, - error: (error) => { - // Error Handling is Defered to the Server - }, - }); - }, - __('eTims Actions'), - ); + callback: (response) => {}, + error: (error) => { + }, + }); + }, + __('eTims Actions'), + ); + } + }, + error: (error) => { + frappe.msgprint(__('Failed to validate items.')); + }, + }); + frm.add_custom_button( __('Create Purchase Invoice'), function () { diff --git a/kenya_compliance/kenya_compliance/doctype/navari_etims_registered_purchases/navari_etims_registered_purchases.py b/kenya_compliance/kenya_compliance/doctype/navari_etims_registered_purchases/navari_etims_registered_purchases.py index d807628..132b7bb 100644 --- a/kenya_compliance/kenya_compliance/doctype/navari_etims_registered_purchases/navari_etims_registered_purchases.py +++ b/kenya_compliance/kenya_compliance/doctype/navari_etims_registered_purchases/navari_etims_registered_purchases.py @@ -1,9 +1,40 @@ # Copyright (c) 2024, Navari Ltd and contributors # For license information, please see license.txt -# import frappe +import frappe from frappe.model.document import Document class NavarieTimsRegisteredPurchases(Document): pass +import json +import frappe + +@frappe.whitelist() +def validate_item_mapped_and_registered(items): + '''I dont think this method will work + Reason: We have item with same item name which is used as item code during creation of item, + but they have different item classification''' + try: + items = json.loads(items) + + for item in items: + similar_items = frappe.get_all( + "Item", + filters={ + "item_name": item.get("item_name"), + "item_code": item.get("item_name"), + # "custom_item_classification": item.get("item_classification_code"), + #"custom_item_code_etims":item.get("item_code"), + "custom_taxation_type": item.get("taxation_type_code"), + }, + fields=["name", "item_name", "item_code"], + ) + if not similar_items: + frappe.response["message"] = False + return + + frappe.response["message"] = True + except Exception as e: + frappe.log_error(f"Error validating items: {str(e)}") + \ No newline at end of file diff --git a/kenya_compliance/kenya_compliance/overrides/server/purchase_invoice.py b/kenya_compliance/kenya_compliance/overrides/server/purchase_invoice.py index 747137c..8e9a980 100644 --- a/kenya_compliance/kenya_compliance/overrides/server/purchase_invoice.py +++ b/kenya_compliance/kenya_compliance/overrides/server/purchase_invoice.py @@ -4,246 +4,181 @@ import frappe from frappe.model.document import Document from erpnext.controllers.taxes_and_totals import get_itemised_tax_breakup_data +from frappe.utils import get_link_to_form from ...apis.api_builder import EndpointsBuilder from ...apis.remote_response_status_handlers import ( - on_error, - purchase_invoice_submission_on_success, + on_error, + purchase_invoice_submission_on_success, ) from ...utils import ( - build_headers, - extract_document_series_number, - get_route_path, - get_server_url, - quantize_number, - split_user_email, - get_taxation_types + build_headers, + extract_document_series_number, + get_route_path, + get_server_url, + quantize_number, + split_user_email, + get_taxation_types ) endpoints_builder = EndpointsBuilder() def validate(doc: Document, method: str) -> None: - item_taxes = get_itemised_tax_breakup_data(doc) - if not doc.branch: - frappe.throw("Please ensure the branch is set before submitting the document") - taxes_breakdown = defaultdict(list) - taxable_breakdown = defaultdict(list) - if not doc.taxes: - vat_acct = frappe.get_value( - "Account", {"account_type": "Tax", "tax_rate": "16"}, ["name"], as_dict=True - ) - doc.set( - "taxes", - [ - { - "account_head": vat_acct.name, - "included_in_print_rate": 1, - "description": vat_acct.name.split("-", 1)[0].strip(), - "category": "Total", - "add_deduct_tax": "Add", - "charge_type": "On Net Total", - } - ], - ) - - # else: - # tax_head = doc.taxes[0].description - # for index, item in enumerate(doc.items): - # taxes_breakdown[item.custom_taxation_type].append( - # item_taxes[index][tax_head]["tax_amount"] - # ) - # taxable_breakdown[item.custom_taxation_type].append( - # item_taxes[index]["taxable_amount"] - # ) - - # update_tax_breakdowns(doc, (taxes_breakdown, taxable_breakdown)) + item_taxes = get_itemised_tax_breakup_data(doc) + # if not doc.branch: + # frappe.throw("Please ensure the branch is set before submitting the document") + taxes_breakdown = defaultdict(list) + taxable_breakdown = defaultdict(list) + if not doc.taxes: + vat_acct = frappe.get_value( + "Account", {"account_type": "Tax", "tax_rate": "16"}, ["name"], as_dict=True + ) + doc.set( + "taxes", + [ + { + "account_head": vat_acct.name, + "included_in_print_rate": 1, + "description": vat_acct.name.split("-", 1)[0].strip(), + "category": "Total", + "add_deduct_tax": "Add", + "charge_type": "On Net Total", + } + ], + ) + def on_submit(doc: Document, method: str) -> None: - if doc.is_return == 0 and doc.update_stock == 1: - # TODO: Handle cases when item tax templates have not been picked - company_name = doc.company - vendor="OSCU KRA" - headers = build_headers(company_name,vendor, doc.branch) - server_url = get_server_url(company_name,vendor, doc.branch) - route_path, last_request_date = get_route_path("TrnsPurchaseSaveReq") - - if headers and server_url and route_path: - url = f"{server_url}{route_path}" - payload = build_purchase_invoice_payload(doc) - - endpoints_builder.url = url - endpoints_builder.headers = headers - endpoints_builder.payload = payload - endpoints_builder.success_callback = partial( - purchase_invoice_submission_on_success, document_name=doc.name - ) - - endpoints_builder.error_callback = on_error - - frappe.enqueue( - endpoints_builder.make_remote_call, - is_async=True, - queue="default", - timeout=300, - job_name=f"{doc.name}_send_purchase_information", - doctype="Purchase Invoice", - document_name=doc.name, - ) + if not doc.branch: + frappe.throw("Please ensure the branch is set before submitting the document") + validate_item_registration(doc.items) + frappe.throw(str(doc.items)) + if doc.is_return == 0 and doc.update_stock == 1: + # TODO: Handle cases when item tax templates have not been picked + company_name = doc.company + vendor="OSCU KRA" + headers = build_headers(company_name,vendor, doc.branch) + server_url = get_server_url(company_name,vendor, doc.branch) + route_path, last_request_date = get_route_path("TrnsPurchaseSaveReq") + + if headers and server_url and route_path: + url = f"{server_url}{route_path}" + payload = build_purchase_invoice_payload(doc) + + endpoints_builder.url = url + endpoints_builder.headers = headers + endpoints_builder.payload = payload + endpoints_builder.success_callback = partial( + purchase_invoice_submission_on_success, document_name=doc.name + ) + + endpoints_builder.error_callback = on_error + + frappe.enqueue( + endpoints_builder.make_remote_call, + is_async=True, + queue="default", + timeout=300, + job_name=f"{doc.name}_send_purchase_information", + doctype="Purchase Invoice", + document_name=doc.name, + ) def build_purchase_invoice_payload(doc: Document) -> dict: - series_no = extract_document_series_number(doc) - items_list = get_items_details(doc) - taxation_type=get_taxation_types(doc) - - payload = { - "invcNo": series_no, - "orgInvcNo": 0, - "spplrTin": doc.tax_id, - "spplrBhfId": doc.custom_supplier_branch_id, - "spplrNm": doc.supplier, - "spplrInvcNo": doc.bill_no, - "regTyCd": "A", - "pchsTyCd": doc.custom_purchase_type_code, - "rcptTyCd": doc.custom_receipt_type_code, - "pmtTyCd": doc.custom_payment_type_code, - "pchsSttsCd": doc.custom_purchase_status_code, - "cfmDt": None, - "pchsDt": "".join(str(doc.posting_date).split("-")), - "wrhsDt": None, - "cnclReqDt": "", - "cnclDt": "", - "rfdDt": None, - "totItemCnt": len(items_list), - - "taxRtA": taxation_type.get("A", {}).get("tax_rate", 0), - "taxRtB": taxation_type.get("B", {}).get("tax_rate", 0), - "taxRtC": taxation_type.get("C", {}).get("tax_rate", 0), - "taxRtD": taxation_type.get("D", {}).get("tax_rate", 0), - "taxRtE": taxation_type.get("E", {}).get("tax_rate", 0), - "taxAmtA": taxation_type.get("A", {}).get("tax_amount", 0), - "taxAmtB": taxation_type.get("B", {}).get("tax_amount", 0), - "taxAmtC": taxation_type.get("C", {}).get("tax_amount", 0), - "taxAmtD": taxation_type.get("D", {}).get("tax_amount", 0), - "taxAmtE": taxation_type.get("E", {}).get("tax_amount", 0), - "taxblAmtA": taxation_type.get("A", {}).get("taxable_amount", 0), - "taxblAmtB": taxation_type.get("B", {}).get("taxable_amount", 0), - "taxblAmtC": taxation_type.get("C", {}).get("taxable_amount", 0), - "taxblAmtD": taxation_type.get("D", {}).get("taxable_amount", 0), - "taxblAmtE": taxation_type.get("E", {}).get("taxable_amount", 0), - "totTaxblAmt": quantize_number(doc.base_net_total), - "totTaxAmt": quantize_number(doc.total_taxes_and_charges), - "totAmt": quantize_number(doc.grand_total), - "remark": None, - "regrNm": doc.owner, - "regrId": split_user_email(doc.owner), - "modrNm": doc.modified_by, - "modrId": split_user_email(doc.modified_by), - "itemList": items_list, - } - - return payload - -# def build_purchase_invoice_payload(doc: Document) -> dict: -# series_no = extract_document_series_number(doc) -# items_list = get_items_details(doc) -# # taxation_type=get_taxation_type(doc) - -# payload = { -# "invcNo": series_no, -# "orgInvcNo": 0, -# "spplrTin": doc.tax_id, -# "spplrBhfId": doc.custom_supplier_branch_id, -# "spplrNm": doc.supplier, -# "spplrInvcNo": doc.bill_no, -# "regTyCd": "A", -# "pchsTyCd": doc.custom_purchase_type_code, -# "rcptTyCd": doc.custom_receipt_type_code, -# "pmtTyCd": doc.custom_payment_type_code, -# "pchsSttsCd": doc.custom_purchase_status_code, -# "cfmDt": None, -# "pchsDt": "".join(str(doc.posting_date).split("-")), -# "wrhsDt": None, -# "cnclReqDt": "", -# "cnclDt": "", -# "rfdDt": None, -# "totItemCnt": len(items_list), -# "taxblAmtA": doc.custom_taxbl_amount_a or 0, -# "taxblAmtB": doc.custom_taxbl_amount_b or 0, -# "taxblAmtC": doc.custom_taxbl_amount_c or 0, -# "taxblAmtD": doc.custom_taxbl_amount_d or 0, -# "taxblAmtE": doc.custom_taxbl_amount_e or 0, -# "taxRtA": 0, -# "taxRtB": 16 if doc.custom_tax_b else 0, -# "taxRtC": 0, -# "taxRtD": 0, -# "taxRtE": 8 if doc.custom_tax_e else 0, -# "taxAmtA": doc.custom_tax_a or 0, -# "taxAmtB": doc.custom_tax_b or 0, -# "taxAmtC": doc.custom_tax_c or 0, -# "taxAmtD": doc.custom_tax_d or 0, -# "taxAmtE": doc.custom_tax_e or 0, -# "totTaxblAmt": quantize_number(doc.base_net_total), -# "totTaxAmt": quantize_number(doc.total_taxes_and_charges), -# "totAmt": quantize_number(doc.grand_total), -# "remark": None, -# "regrNm": doc.owner, -# "regrId": split_user_email(doc.owner), -# "modrNm": doc.modified_by, -# "modrId": split_user_email(doc.modified_by), -# "itemList": items_list, -# } - -# return payload + series_no = extract_document_series_number(doc) + items_list = get_items_details(doc) + taxation_type=get_taxation_types(doc) + + payload = { + "invcNo": series_no, + "orgInvcNo": 0, + "spplrTin": doc.tax_id, + "spplrBhfId": doc.custom_supplier_branch_id, + "spplrNm": doc.supplier, + "spplrInvcNo": doc.bill_no, + "regTyCd": "A", + "pchsTyCd": doc.custom_purchase_type_code, + "rcptTyCd": doc.custom_receipt_type_code, + "pmtTyCd": doc.custom_payment_type_code, + "pchsSttsCd": doc.custom_purchase_status_code, + "cfmDt": None, + "pchsDt": "".join(str(doc.posting_date).split("-")), + "wrhsDt": None, + "cnclReqDt": "", + "cnclDt": "", + "rfdDt": None, + "totItemCnt": len(items_list), + + "taxRtA": taxation_type.get("A", {}).get("tax_rate", 0), + "taxRtB": taxation_type.get("B", {}).get("tax_rate", 0), + "taxRtC": taxation_type.get("C", {}).get("tax_rate", 0), + "taxRtD": taxation_type.get("D", {}).get("tax_rate", 0), + "taxRtE": taxation_type.get("E", {}).get("tax_rate", 0), + "taxAmtA": taxation_type.get("A", {}).get("tax_amount", 0), + "taxAmtB": taxation_type.get("B", {}).get("tax_amount", 0), + "taxAmtC": taxation_type.get("C", {}).get("tax_amount", 0), + "taxAmtD": taxation_type.get("D", {}).get("tax_amount", 0), + "taxAmtE": taxation_type.get("E", {}).get("tax_amount", 0), + "taxblAmtA": taxation_type.get("A", {}).get("taxable_amount", 0), + "taxblAmtB": taxation_type.get("B", {}).get("taxable_amount", 0), + "taxblAmtC": taxation_type.get("C", {}).get("taxable_amount", 0), + "taxblAmtD": taxation_type.get("D", {}).get("taxable_amount", 0), + "taxblAmtE": taxation_type.get("E", {}).get("taxable_amount", 0), + "totTaxblAmt": quantize_number(doc.base_net_total), + "totTaxAmt": quantize_number(doc.total_taxes_and_charges), + "totAmt": quantize_number(doc.grand_total), + "remark": None, + "regrNm": doc.owner, + "regrId": split_user_email(doc.owner), + "modrNm": doc.modified_by, + "modrId": split_user_email(doc.modified_by), + "itemList": items_list, + } + + return payload def get_items_details(doc: Document) -> list: - items_list = [] - # item_taxes = get_itemised_tax_breakup_data(doc) - - for index, item in enumerate(doc.items): - # try: - # taxable_amount = item_taxes[index]["taxable_amount"] - # except IndexError as e: - # frappe.throw( - # "Please ensure tax templates are supplied as required for each item, and/or in the Purchase taxes and charges table", - # e, - # "Validation Error", - # ) - - # actual_tax_amount = 0 - # tax_head = doc.taxes[0].description # Fetch tax head from taxes table - - # actual_tax_amount = item_taxes[index][tax_head]["tax_amount"] - - # tax_amount = actual_tax_amount - - items_list.append( - { - "itemSeq": item.idx, - "itemCd": item.custom_item_code_etims, - "itemClsCd": item.custom_item_classification_code, - "itemNm": item.item_name, - "bcd": "", - "spplrItemClsCd": None, - "spplrItemCd": None, - "spplrItemNm": None, - "pkgUnitCd": item.custom_packaging_unit_code, - "pkg": 1, - "qtyUnitCd": item.custom_unit_of_quantity_code, - "qty": abs(item.qty), - "prc": item.base_rate, - "splyAmt": item.base_amount, - "dcRt": quantize_number(item.discount_percentage) or 0, - "dcAmt": quantize_number(item.discount_amount) or 0, - "taxblAmt": quantize_number(item.net_amount), - "taxTyCd": item.custom_taxation_type or "B", - "taxAmt": quantize_number(item.custom_tax_amount) or 0, - "totAmt": quantize_number(item.net_amount + item.custom_tax_amount), - "itemExprDt": None, - } - ) - - return items_list + items_list = [] + + for index, item in enumerate(doc.items): + + items_list.append( + { + "itemSeq": item.idx, + "itemCd": item.custom_item_code_etims, + "itemClsCd": item.custom_item_classification_code, + "itemNm": item.item_name, + "bcd": "", + "spplrItemClsCd": None, + "spplrItemCd": None, + "spplrItemNm": None, + "pkgUnitCd": item.custom_packaging_unit_code, + "pkg": 1, + "qtyUnitCd": item.custom_unit_of_quantity_code, + "qty": abs(item.qty), + "prc": item.base_rate, + "splyAmt": item.base_amount, + "dcRt": quantize_number(item.discount_percentage) or 0, + "dcAmt": quantize_number(item.discount_amount) or 0, + "taxblAmt": quantize_number(item.net_amount), + "taxTyCd": item.custom_taxation_type or "B", + "taxAmt": quantize_number(item.custom_tax_amount) or 0, + "totAmt": quantize_number(item.net_amount + item.custom_tax_amount), + "itemExprDt": None, + } + ) + + return items_list + +def validate_item_registration(items): + for item in items: + item_doc = frappe.get_doc("Item", item.item_code) + if item_doc.custom_item_registered == 0: + # Generate a link to the item form + item_link = get_link_to_form("Item", item.item_code) + frappe.throw(f"Go and register the item: {item_link}") + diff --git a/kenya_compliance/kenya_compliance/overrides/server/sales_invoice.py b/kenya_compliance/kenya_compliance/overrides/server/sales_invoice.py index da1b34a..ccbfc3b 100644 --- a/kenya_compliance/kenya_compliance/overrides/server/sales_invoice.py +++ b/kenya_compliance/kenya_compliance/overrides/server/sales_invoice.py @@ -25,6 +25,7 @@ def before_cancel(doc: Document, method: str) -> None: "If you need to make adjustments, please create a Credit Note instead." ) elif doc.doctype == "Purchase Invoice" and doc.custom_submitted_successfully: + frappe.throw("Here") frappe.throw( "This invoice has already been submitted to eTIMS and cannot be Canceled..\nIf you need to make adjustments, please create a Debit Note instead." ) \ No newline at end of file From 429366dea9f429f6222a8f3761ec3d315d7eaa3b Mon Sep 17 00:00:00 2001 From: maniamartial Date: Mon, 2 Dec 2024 17:37:15 +0300 Subject: [PATCH 3/5] fix - add task code on purchase invoice item, validate item before purchase invoice creation --- .../kenya_compliance/apis/apis.py | 96 ++++++++++++------- .../navari_etims_registered_imported_item.js | 3 +- .../navari_etims_registered_purchases.py | 9 +- .../overrides/server/purchase_invoice.py | 14 ++- .../patch/purchase_invoice.py | 22 +++++ kenya_compliance/patches.txt | 3 +- 6 files changed, 98 insertions(+), 49 deletions(-) create mode 100644 kenya_compliance/kenya_compliance/patch/purchase_invoice.py diff --git a/kenya_compliance/kenya_compliance/apis/apis.py b/kenya_compliance/kenya_compliance/apis/apis.py index 95880c5..f4044fe 100644 --- a/kenya_compliance/kenya_compliance/apis/apis.py +++ b/kenya_compliance/kenya_compliance/apis/apis.py @@ -68,39 +68,52 @@ def bulk_register_item(docs_list: str) -> None: for record in data: for item in all_items: if record == item.name: - item=frappe.get_doc("Item", record, for_update=False) - valuation_rate = item.valuation_rate if item.valuation_rate is not None else 0 - - request_data = { - "name": item.name, - "company_name": frappe.defaults.get_user_default("Company"), - "itemCd": item.custom_item_code_etims, - "itemClsCd": item.custom_item_classification, - "itemTyCd": item.custom_product_type, - "itemNm": item.item_name, - "temStdNm": None, - "orgnNatCd": item.custom_etims_country_of_origin_code, - "pkgUnitCd": item.custom_packaging_unit_code, - "qtyUnitCd": item.custom_unit_of_quantity_code, - "taxTyCd": item.get("custom_taxation_type", "B"), - "btchNo": None, - "bcd": None, - "dftPrc": round(valuation_rate, 2), - "grpPrcL1": None, - "grpPrcL2": None, - "grpPrcL3": None, - "grpPrcL4": None, - "grpPrcL5": None, - "addInfo": None, - "sftyQty": None, - "isrcAplcbYn": "Y", - "useYn": "Y", - "regrId": split_user_email(item.owner), - "regrNm": item.owner, - "modrId": split_user_email(item.modified_by), - "modrNm": item.modified_by, - } - perform_item_registration(request_data=json.dumps(request_data)) + process_single_item(record) + + +@frappe.whitelist() +def process_single_item(record: str) -> None: + """ + Process a single item for registration, construct the payload, and perform registration. + + Args: + record (str): Name of the item to process. + """ + item = frappe.get_doc("Item", record, for_update=False) + + valuation_rate = item.valuation_rate if item.valuation_rate is not None else 0 + + request_data = { + "name": item.name, + "company_name": frappe.defaults.get_user_default("Company"), + "itemCd": item.custom_item_code_etims, + "itemClsCd": item.custom_item_classification, + "itemTyCd": item.custom_product_type, + "itemNm": item.item_name, + "temStdNm": None, + "orgnNatCd": item.custom_etims_country_of_origin_code, + "pkgUnitCd": item.custom_packaging_unit_code, + "qtyUnitCd": item.custom_unit_of_quantity_code, + "taxTyCd": item.get("custom_taxation_type", "B"), + "btchNo": None, + "bcd": None, + "dftPrc": round(valuation_rate, 2), + "grpPrcL1": None, + "grpPrcL2": None, + "grpPrcL3": None, + "grpPrcL4": None, + "grpPrcL5": None, + "addInfo": None, + "sftyQty": None, + "isrcAplcbYn": "Y", + "useYn": "Y", + "regrId": split_user_email(item.owner), + "regrNm": item.owner, + "modrId": split_user_email(item.modified_by), + "modrNm": item.modified_by, + } + + perform_item_registration(request_data=json.dumps(request_data)) @frappe.whitelist() @@ -320,7 +333,7 @@ def create_branch_user() -> None: doc.system_user = user.email doc.branch_id = frappe.get_value( "Branch", {"custom_branch_code": "00"}, ["name"] - ) # Created users are assigned to Branch 00 + ) doc.save() @@ -746,7 +759,7 @@ def create_items_from_fetched_registered_purchases(request_data: str) -> None: def create_item(item: dict | frappe._dict) -> Document: item_code = item.get("item_code", None) - + new_item = frappe.new_doc("Item") new_item.is_stock_item = 0 # Default to 0 new_item.item_code = item["item_name"] @@ -781,7 +794,8 @@ def create_item(item: dict | frappe._dict) -> Document: new_item.custom_referenced_imported_item = item["imported_item"] new_item.insert(ignore_mandatory=True, ignore_if_duplicate=True) - + if new_item.custom_item_classification is not None: + process_single_item(new_item.name) return new_item @@ -858,9 +872,10 @@ def create_purchase_invoice_from_request(request_data: str) -> None: "custom_packaging_unit": item["packaging_unit_code"], "custom_unit_of_quantity": item["quantity_unit_code"], "custom_taxation_type": item["taxation_type_code"], + "task_code": item["task_code"], }, ) - + validate_mapping_and_registration_of_items(data["items"]) purchase_invoice.insert(ignore_mandatory=True) frappe.msgprint("Purchase Invoices have been created") @@ -928,3 +943,10 @@ def create_stock_entry_from_stock_movement(request_data: str) -> None: stock_entry.save() frappe.msgprint(f"Stock Entry {stock_entry.name} created successfully") + +def validate_mapping_and_registration_of_items(items): + for item in items: + item_code = item.get("item_code") or item.get("item_name") + from kenya_compliance.kenya_compliance.overrides.server.purchase_invoice import validation_message + validation_message(item_code) + \ No newline at end of file diff --git a/kenya_compliance/kenya_compliance/doctype/navari_etims_registered_imported_item/navari_etims_registered_imported_item.js b/kenya_compliance/kenya_compliance/doctype/navari_etims_registered_imported_item/navari_etims_registered_imported_item.js index fc831a0..f27fd92 100644 --- a/kenya_compliance/kenya_compliance/doctype/navari_etims_registered_imported_item/navari_etims_registered_imported_item.js +++ b/kenya_compliance/kenya_compliance/doctype/navari_etims_registered_imported_item/navari_etims_registered_imported_item.js @@ -78,7 +78,7 @@ frappe.ui.form.on(doctypeName, { frappe.db.get_value( 'Item', { custom_referenced_imported_item: frm.doc.name }, - ['custom_item_registered'], + ['custom_item_registered','name'], (response) => { if (parseInt(response.custom_item_registered) === 1) { frm.add_custom_button( @@ -98,6 +98,7 @@ frappe.ui.form.on(doctypeName, { currency: frm.doc.invoice_foreign_currency, amount: frm.doc.invoice_foreign_currency_amount, items: item, + task_code: frm.doc.task_code, }, }, callback: (response) => { diff --git a/kenya_compliance/kenya_compliance/doctype/navari_etims_registered_purchases/navari_etims_registered_purchases.py b/kenya_compliance/kenya_compliance/doctype/navari_etims_registered_purchases/navari_etims_registered_purchases.py index 132b7bb..dbca440 100644 --- a/kenya_compliance/kenya_compliance/doctype/navari_etims_registered_purchases/navari_etims_registered_purchases.py +++ b/kenya_compliance/kenya_compliance/doctype/navari_etims_registered_purchases/navari_etims_registered_purchases.py @@ -3,12 +3,11 @@ import frappe from frappe.model.document import Document - +import json class NavarieTimsRegisteredPurchases(Document): pass -import json -import frappe + @frappe.whitelist() def validate_item_mapped_and_registered(items): @@ -24,7 +23,7 @@ def validate_item_mapped_and_registered(items): filters={ "item_name": item.get("item_name"), "item_code": item.get("item_name"), - # "custom_item_classification": item.get("item_classification_code"), + #"custom_item_classification": item.get("item_classification_code"), #"custom_item_code_etims":item.get("item_code"), "custom_taxation_type": item.get("taxation_type_code"), }, @@ -37,4 +36,4 @@ def validate_item_mapped_and_registered(items): frappe.response["message"] = True except Exception as e: frappe.log_error(f"Error validating items: {str(e)}") - \ No newline at end of file + diff --git a/kenya_compliance/kenya_compliance/overrides/server/purchase_invoice.py b/kenya_compliance/kenya_compliance/overrides/server/purchase_invoice.py index 8e9a980..e50fc38 100644 --- a/kenya_compliance/kenya_compliance/overrides/server/purchase_invoice.py +++ b/kenya_compliance/kenya_compliance/overrides/server/purchase_invoice.py @@ -176,9 +176,13 @@ def get_items_details(doc: Document) -> list: def validate_item_registration(items): for item in items: - item_doc = frappe.get_doc("Item", item.item_code) - if item_doc.custom_item_registered == 0: - # Generate a link to the item form - item_link = get_link_to_form("Item", item.item_code) - frappe.throw(f"Go and register the item: {item_link}") + item_code = item.item_code + validation_message(item_code) + +def validation_message(item_code): + item_doc = frappe.get_doc("Item", item_code) + if item_doc.custom_item_registered == 0: + # Generate a link to the item form + item_link = get_link_to_form("Item", item_code) + frappe.throw(f"Go and register the item: {item_link}") diff --git a/kenya_compliance/kenya_compliance/patch/purchase_invoice.py b/kenya_compliance/kenya_compliance/patch/purchase_invoice.py new file mode 100644 index 0000000..b93a592 --- /dev/null +++ b/kenya_compliance/kenya_compliance/patch/purchase_invoice.py @@ -0,0 +1,22 @@ +import frappe +from frappe.custom.doctype.custom_field.custom_field import create_custom_fields + +def execute(): + frappe.delete_doc("Custom Field", "Purchase Invoice Item-task_code", force=True) + + + custom_fields = { + "Purchase Invoice Item": [ + { + "fieldname": "task_code", + "fieldtype": "Link", + "options": "Navari eTims Registered Imported Item", + "label": "Task Code", + "translatable": 1, + "insert_after": "sales_invoice_item" + }, + + ] + } + + create_custom_fields(custom_fields, update=True) \ No newline at end of file diff --git a/kenya_compliance/patches.txt b/kenya_compliance/patches.txt index f15c3a9..9f2c3c4 100644 --- a/kenya_compliance/patches.txt +++ b/kenya_compliance/patches.txt @@ -3,4 +3,5 @@ # Read docs to understand patches: https://frappeframework.com/docs/v14/user/en/database-migrations [post_model_sync] -# Patches added in this section will be executed after doctypes are migrated \ No newline at end of file +# Patches added in this section will be executed after doctypes are migrated +kenya_compliance.kenya_compliance.patch.purchase_invoice \ No newline at end of file From fe5029faec0917356fae33ec4ab2703c0bf848cc Mon Sep 17 00:00:00 2001 From: maniamartial Date: Tue, 3 Dec 2024 12:14:18 +0300 Subject: [PATCH 4/5] Fix- minor fix and Updates for validation of imported items --- .../kenya_compliance/apis/apis.py | 17 +++++++++----- .../overrides/server/purchase_invoice.py | 23 +++++++++++-------- .../overrides/server/stock_ledger_entry.py | 2 +- 3 files changed, 25 insertions(+), 17 deletions(-) diff --git a/kenya_compliance/kenya_compliance/apis/apis.py b/kenya_compliance/kenya_compliance/apis/apis.py index f4044fe..ea8f222 100644 --- a/kenya_compliance/kenya_compliance/apis/apis.py +++ b/kenya_compliance/kenya_compliance/apis/apis.py @@ -439,13 +439,13 @@ def perform_purchases_search(request_data: str, vendor: str="OSCU KRA") -> None: @frappe.whitelist() -def submit_inventory(request_data: str) -> None: +def submit_inventory(request_data: str, vendor: str="OSCU KRA") -> None: data: dict = json.loads(request_data) company_name = frappe.defaults.get_user_default("Company") - headers = build_headers(company_name, data["branch_id"]) - server_url = get_server_url(company_name, data["branch_id"]) + headers = build_headers(company_name,vendor, data["branch_id"]) + server_url = get_server_url(company_name,vendor, data["branch_id"]) route_path, last_request_date = get_route_path("StockMasterSaveReq") if headers and server_url and route_path: @@ -880,7 +880,6 @@ def create_purchase_invoice_from_request(request_data: str) -> None: frappe.msgprint("Purchase Invoices have been created") - @frappe.whitelist() def ping_server(request_data: str) -> None: url = json.loads(request_data)["server_url"] @@ -946,7 +945,13 @@ def create_stock_entry_from_stock_movement(request_data: str) -> None: def validate_mapping_and_registration_of_items(items): for item in items: - item_code = item.get("item_code") or item.get("item_name") + task_code = item.get("task_code") or item.get("item_name") + items = frappe.get_all("Item", + filters={"custom_referenced_imported_item": task_code}, + fields=["name","item_name","item_code"] + ) + if items: + item_name = items[0].name from kenya_compliance.kenya_compliance.overrides.server.purchase_invoice import validation_message - validation_message(item_code) + validation_message(item_name) \ No newline at end of file diff --git a/kenya_compliance/kenya_compliance/overrides/server/purchase_invoice.py b/kenya_compliance/kenya_compliance/overrides/server/purchase_invoice.py index e50fc38..e5f6ad3 100644 --- a/kenya_compliance/kenya_compliance/overrides/server/purchase_invoice.py +++ b/kenya_compliance/kenya_compliance/overrides/server/purchase_invoice.py @@ -54,7 +54,6 @@ def on_submit(doc: Document, method: str) -> None: if not doc.branch: frappe.throw("Please ensure the branch is set before submitting the document") validate_item_registration(doc.items) - frappe.throw(str(doc.items)) if doc.is_return == 0 and doc.update_stock == 1: # TODO: Handle cases when item tax templates have not been picked company_name = doc.company @@ -175,14 +174,18 @@ def get_items_details(doc: Document) -> list: return items_list def validate_item_registration(items): - for item in items: - item_code = item.item_code - validation_message(item_code) - + for item in items: + item_code = item.item_code + validation_message(item_code) + def validation_message(item_code): - item_doc = frappe.get_doc("Item", item_code) - if item_doc.custom_item_registered == 0: - # Generate a link to the item form - item_link = get_link_to_form("Item", item_code) - frappe.throw(f"Go and register the item: {item_link}") + item_doc = frappe.get_doc("Item", item_code) + + if item_doc.custom_referenced_imported_item and (item_doc.custom_item_registered == 0 or item_doc.custom_imported_item_submitted == 0): + item_link = get_link_to_form("Item", item_doc.name) + frappe.throw(f"Register or submit the item: {item_link}") + + elif not item_doc.custom_referenced_imported_item and item_doc.custom_item_registered == 0: + item_link = get_link_to_form("Item", item_doc.name) + frappe.throw(f"Register the item: {item_link}") diff --git a/kenya_compliance/kenya_compliance/overrides/server/stock_ledger_entry.py b/kenya_compliance/kenya_compliance/overrides/server/stock_ledger_entry.py index a020137..860d351 100644 --- a/kenya_compliance/kenya_compliance/overrides/server/stock_ledger_entry.py +++ b/kenya_compliance/kenya_compliance/overrides/server/stock_ledger_entry.py @@ -448,7 +448,7 @@ def on_update(doc: Document, method: str | None = None) -> None: else: payload["sarTyCd"] = "11" - server_url = get_server_url(company_name, record.branch) + server_url = get_server_url(company_name,vendor, record.branch) route_path, last_request_date = get_route_path("StockIOSaveReq") if headers and server_url and route_path: url = f"{server_url}{route_path}" From a9c20de93b63cff4acc0dc8e128e0295e1ab10ca Mon Sep 17 00:00:00 2001 From: maniamartial Date: Wed, 4 Dec 2024 12:10:41 +0300 Subject: [PATCH 5/5] chore - testing and removing of comented code --- .../kenya_compliance/overrides/server/item.py | 33 +------------------ .../overrides/server/stock_ledger_entry.py | 18 +--------- 2 files changed, 2 insertions(+), 49 deletions(-) diff --git a/kenya_compliance/kenya_compliance/overrides/server/item.py b/kenya_compliance/kenya_compliance/overrides/server/item.py index 164e960..7f149f1 100644 --- a/kenya_compliance/kenya_compliance/overrides/server/item.py +++ b/kenya_compliance/kenya_compliance/overrides/server/item.py @@ -54,36 +54,6 @@ def before_insert(doc: Document, method: str) -> None: perform_item_registration(json.dumps(item_registration_data)) -# def validate(doc: Document, method: str) -> None: -# # FIXME Ensure all item code numbers follow a global serial -# # FIXME Currently, the item code number for each item is incremented if there's an item with same etims item code value -# if not doc.custom_item_registered or "None" in doc.custom_item_code_etims: -# # Check if Item code contains None or if it's not present -# item_code = f"{doc.custom_etims_country_of_origin_code}{doc.custom_product_type}{doc.custom_packaging_unit_code}{doc.custom_unit_of_quantity_code}" -# count = frappe.db.count( -# "Item", {"custom_item_code_etims": ["like", f"{item_code}%"]} -# ) - -# doc.custom_item_code_etims = f"{item_code}{str(count + 1).zfill(7)}" - -# is_tax_type_changed = doc.has_value_changed( -# "custom_taxation_type" -# ) # Check if tax type field changed -# if doc.custom_taxation_type and is_tax_type_changed: -# relevant_tax_templates = frappe.get_all( -# "Item Tax Template", -# ["*"], -# { -# "custom_etims_taxation_type": doc.custom_taxation_type, -# }, -# ) - -# if relevant_tax_templates: -# doc.set("taxes", []) -# for template in relevant_tax_templates: -# doc.append("taxes", {"item_tax_template": template.name}) - - def validate(doc: Document, method: str) -> None: new_prefix = f"{doc.custom_etims_country_of_origin_code}{doc.custom_product_type}{doc.custom_packaging_unit_code}{doc.custom_unit_of_quantity_code}" @@ -113,7 +83,6 @@ def validate(doc: Document, method: str) -> None: # Start from '0000001' if no matching classification item exists existing_suffix = "0000001" - # Combine the new prefix with the existing or new suffix doc.custom_item_code_etims = f"{new_prefix}{existing_suffix}" # Check if the tax type field has changed @@ -132,5 +101,5 @@ def validate(doc: Document, method: str) -> None: @frappe.whitelist() def prevent_item_deletion(doc, method): - if doc.custom_item_registered == 1: # Assuming 1 means registered, adjust as needed + if doc.custom_item_registered == 1: frappe.throw(_("Cannot delete registered items")) \ No newline at end of file diff --git a/kenya_compliance/kenya_compliance/overrides/server/stock_ledger_entry.py b/kenya_compliance/kenya_compliance/overrides/server/stock_ledger_entry.py index 860d351..f90af3a 100644 --- a/kenya_compliance/kenya_compliance/overrides/server/stock_ledger_entry.py +++ b/kenya_compliance/kenya_compliance/overrides/server/stock_ledger_entry.py @@ -412,23 +412,7 @@ def on_update(doc: Document, method: str | None = None) -> None: tax_details = list(filter(lambda i: i["item"] == doc.item_code, item_taxes))[ 0 ] - # filter current items tax details - - # current_item[0]["taxblAmt"] = round( - # tax_details["taxable_amount"] / current_item[0]["qty"], 2 - # ) # calculate taxable amt - # current_item[0]["totAmt"] = round( - # tax_details["taxable_amount"] / current_item[0]["qty"], 2 - # ) # calculate total amt - - # actual_tax_amount = 0 - # tax_head = doc.taxes[0].description - - # actual_tax_amount = tax_details[tax_head]["tax_amount"] - - # current_item[0]["taxAmt"] = round( - # actual_tax_amount / current_item[0]["qty"], 2 - # ) # calculate tax amt + payload["itemList"] = current_item payload["totItemCnt"] = len(current_item)