Skip to content

Commit

Permalink
feat: add genericode importers
Browse files Browse the repository at this point in the history
  • Loading branch information
blaggacao committed Sep 29, 2024
1 parent 1431ee5 commit e26dec7
Show file tree
Hide file tree
Showing 10 changed files with 461 additions and 19 deletions.
47 changes: 42 additions & 5 deletions erpnext/edi/doctype/code_list/code_list.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,45 @@
// Copyright (c) 2024, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt

// frappe.ui.form.on("Code List", {
// refresh(frm) {

// },
// });
frappe.ui.form.on("Code List", {
refresh: (frm) => {
frm.add_custom_button(
__("Genericode"),
function () {
erpnext.edi.import_genericode(frm);
},
__("Import")
);
},
setup: (frm) => {
frm.savetrash = () => {
frm.validate_form_action("Delete");
frappe.confirm(
__(
"Are you sure you want to delete {0}?<p>This action will also delete all associated Common Code documents.</p>",
[frm.docname.bold()]
),
function () {
return frappe.call({
method: "frappe.client.delete",
args: {
doctype: frm.doctype,
name: frm.docname,
},
freeze: true,
freeze_message: __("Deleting {0} and all associated Common Code documents...", [
frm.docname,
]),
callback: function (r) {
if (!r.exc) {
frappe.utils.play_sound("delete");
frappe.model.clear_doc(frm.doctype, frm.docname);
window.history.back();
}
},
});
}
);
};
},
});
25 changes: 22 additions & 3 deletions erpnext/edi/doctype/code_list/code_list.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
{
"actions": [],
"allow_copy": 1,
"allow_rename": 1,
"autoname": "prompt",
"creation": "2024-09-29 06:55:03.920375",
"doctype": "DocType",
"engine": "InnoDB",
"field_order": [
"title",
"publisher",
"canonical_uri",
"column_break_nkls",
"version",
"publisher",
"section_break_npxp",
"description"
],
"fields": [
Expand All @@ -24,6 +28,7 @@
"label": "Publisher"
},
{
"columns": 1,
"fieldname": "version",
"fieldtype": "Data",
"in_list_view": 1,
Expand All @@ -33,6 +38,20 @@
"fieldname": "description",
"fieldtype": "Small Text",
"label": "Description"
},
{
"fieldname": "canonical_uri",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Canonical URI"
},
{
"fieldname": "column_break_nkls",
"fieldtype": "Column Break"
},
{
"fieldname": "section_break_npxp",
"fieldtype": "Section Break"
}
],
"index_web_pages_for_search": 1,
Expand All @@ -42,7 +61,7 @@
"link_fieldname": "code_list"
}
],
"modified": "2024-09-29 07:24:21.123903",
"modified": "2024-09-29 22:46:37.878075",
"modified_by": "Administrator",
"module": "EDI",
"name": "Code List",
Expand All @@ -66,4 +85,4 @@
"sort_order": "DESC",
"states": [],
"title_field": "title"
}
}
46 changes: 46 additions & 0 deletions erpnext/edi/doctype/code_list/code_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@

import frappe
from frappe.model.document import Document
from lxml import etree

from erpnext.edi.doctype.common_code.common_code import CommonCode


class CodeList(Document):
Expand All @@ -14,12 +17,27 @@ class CodeList(Document):
if TYPE_CHECKING:
from frappe.types import DF

canonical_uri: DF.Data | None
description: DF.SmallText | None
publisher: DF.Data | None
title: DF.Data | None
version: DF.Data | None
# end: auto-generated types

def on_trash(self):
if not frappe.flags.in_bulk_delete:
self.__delete_linked_docs()

def __delete_linked_docs(self):
linked_docs = frappe.get_all(
"Common Code",
filters={"code_list": self.name},
fields=["name"],
)

for doc in linked_docs:
frappe.delete_doc("Common Code", doc.name, force=1)

def get_code_for(self, doctype: str, name: str):
"""Get code for a doctype and name"""
CommonCode = frappe.qb.DocType("Common Code")
Expand All @@ -38,3 +56,31 @@ def get_code_for(self, doctype: str, name: str):
).run()

return code[0][0] if code else None

def import_genericode(self, file_path, code_column, title_column=None, filters=None):
"""Import genericode file and create Common Code entries"""
parser = etree.XMLParser(remove_blank_text=True)
tree = etree.parse(file_path, parser=parser)
root = tree.getroot()

# Extract Code List details
self.title = root.find(".//Identification/ShortName").text
self.version = root.find(".//Identification/Version").text
self.canonical_uri = root.find(".//CanonicalUri").text
# optionals
self.description = getattr(root.find(".//Identification/LongName"), "text", None)
self.publisher = getattr(root.find(".//Identification/Agency/ShortName"), "text", None)

self.save()

common_codes = CommonCode.import_genericode(file_path, self.name, code_column, title_column, filters)

# Bulk insert common codes
if common_codes:
frappe.db.bulk_insert(
"Common Code",
fields=["name", "code_list", "common_code", "title"],
values=[(cc["name"], cc["code_list"], cc["common_code"], cc["title"]) for cc in common_codes],
)

return {"code_list": self, "common_codes_count": len(common_codes)}
160 changes: 160 additions & 0 deletions erpnext/edi/doctype/code_list/code_list_import.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
frappe.provide("erpnext.edi");

erpnext.edi.import_genericode = function (listview_or_form) {
let doctype = "Code List";
let docname = undefined;
if (listview_or_form.doc !== undefined) {
docname = listview_or_form.doc.name;
}
new frappe.ui.FileUploader({
method: "erpnext.edi.doctype.code_list.code_list_import.import_genericode",
doctype: doctype,
docname: docname,
allow_toggle_private: false,
on_success: function (_file_doc, r) {
listview_or_form.refresh();
show_column_selection_dialog(r.message);
},
});
};

function show_column_selection_dialog(context) {
let fields = [
{
fieldname: "import_column",
label: __("Import"),
fieldtype: "Column Break",
},
{
fieldname: "title_column",
label: __("as Title"),
fieldtype: "Select",
options: [null].concat(context.columns),
},
{
fieldname: "code_column",
label: __("as Code"),
fieldtype: "Select",
options: context.columns,
reqd: 1,
},
{
fieldname: "filters_column",
label: __("Filter"),
fieldtype: "Column Break",
},
];

// Add filterable columns
for (let column in context.filterable_columns) {
fields.push({
fieldname: `filter_${column}`,
label: __(`by ${column}`),
fieldtype: "Select",
options: [null].concat(context.filterable_columns[column]),
});
}

fields.push(
{
fieldname: "preview_section",
label: __("Preview"),
fieldtype: "Section Break",
},
{
fieldname: "preview_html",
fieldtype: "HTML",
}
);

let d = new frappe.ui.Dialog({
title: __("Select Columns and Filters"),
fields: fields,
primary_action_label: __("Import"),
size: "large", // This will make the modal wider
primary_action(values) {
let filters = {};
for (let field in values) {
if (field.startsWith("filter_") && values[field]) {
filters[field.replace("filter_", "")] = values[field];
}
}
frappe.call({
method: "erpnext.edi.doctype.code_list.code_list_import.process_genericode_import",
args: {
code_list_name: context.code_list,
file_path: context.file_path,
code_column: values.code_column,
title_column: values.title_column,
filters: filters,
},
callback: function (r) {
frappe.msgprint(
__("Import completed. {0} common codes created.", [r.message.common_codes_count])
);
},
});
d.hide();
},
});

d.fields_dict.code_column.df.onchange = () => update_preview(d, context);
d.fields_dict.title_column.df.onchange = () => update_preview(d, context);

// Add onchange events for filterable columns
for (let column in context.filterable_columns) {
d.fields_dict[`filter_${column}`].df.onchange = () => update_preview(d, context);
}

d.show();
update_preview(d, context);
}

function update_preview(dialog, context) {
let code_column = dialog.get_value("code_column");
let title_column = dialog.get_value("title_column");

let html = '<table class="table table-bordered"><thead><tr>';
if (title_column) html += `<th>${__("Title")}</th>`;
if (code_column) html += `<th>${__("Code")}</th>`;

// Add headers for filterable columns
for (let column in context.filterable_columns) {
if (dialog.get_value(`filter_${column}`)) {
html += `<th>${__(column)}</th>`;
}
}

html += "</tr></thead><tbody>";

for (let i = 0; i < 3; i++) {
html += "<tr>";
if (title_column) {
let title = context.example_values[title_column][i] || "";
html += `<td title="${title}">${truncate(title)}</td>`;
}
if (code_column) {
let code = context.example_values[code_column][i] || "";
html += `<td title="${code}">${truncate(code)}</td>`;
}

// Add values for filterable columns
for (let column in context.filterable_columns) {
if (dialog.get_value(`filter_${column}`)) {
let value = context.example_values[column][i] || "";
html += `<td title="${value}">${truncate(value)}</td>`;
}
}

html += "</tr>";
}

html += "</tbody></table>";

dialog.fields_dict.preview_html.$wrapper.html(html);
}

function truncate(value, maxLength = 40) {
if (typeof value !== "string") return "";
return value.length > maxLength ? value.substring(0, maxLength - 3) + "..." : value;
}
Loading

0 comments on commit e26dec7

Please sign in to comment.