diff --git a/landa/organization_management/doctype/landa_member/landa_member.py b/landa/organization_management/doctype/landa_member/landa_member.py index 16bac362..18127785 100644 --- a/landa/organization_management/doctype/landa_member/landa_member.py +++ b/landa/organization_management/doctype/landa_member/landa_member.py @@ -68,3 +68,24 @@ def revert_series(self): def get_full_name(first_name, last_name): return (first_name or "") + (" " if (last_name and first_name) else "") + (last_name or "") + + +def get_address_or_contact(doctype: str, landa_member: str): + """Returns a single Address or Contact linked to the given LANDA member. + + If there are no or multiple linked addresses or contacts, None is returned. + """ + filters = [ + ["Dynamic Link", "link_doctype", "=", "LANDA Member"], + ["Dynamic Link", "link_name", "=", landa_member], + ] + if doctype == "Address": + filters.append(["disabled", "=", 0]) + + records = frappe.get_list( + doctype, + filters=filters, + pluck="name", + limit=2, + ) + return frappe.get_doc(doctype, records[0]) if len(records) == 1 else None diff --git a/landa/organization_management/doctype/organization/organization.js b/landa/organization_management/doctype/organization/organization.js index 095a9622..bea691e9 100644 --- a/landa/organization_management/doctype/organization/organization.js +++ b/landa/organization_management/doctype/organization/organization.js @@ -41,11 +41,68 @@ frappe.ui.form.on("Organization", { frappe.contacts.render_address_and_contact(frm); } - if (frappe.user_roles.includes("System Manager") && !frm.is_new()) { + if (frappe.user.has_role("System Manager") && !frm.is_dirty()) { frm.page.add_menu_item(__("Update Naming Series"), () => frm.trigger("update_naming_series") ); } + + if (frappe.user.has_role("LANDA Regional Organization Management") && !frm.is_dirty()) { + frm.page.add_menu_item(__("Link Member as Contact"), () => { + frappe.prompt( + [ + { + fieldname: "landa_member", + label: __("LANDA Member"), + fieldtype: "Link", + options: "LANDA Member", + reqd: 1, + get_query: function () { + return { + filters: { + organization: frm.doc.name, + }, + }; + }, + }, + { + fieldname: "is_default_billing", + label: __("Is Default Billing Contact"), + fieldtype: "Check", + reqd: 1, + }, + { + fieldname: "is_default_shipping", + label: __("Is Default Shipping Contact"), + fieldtype: "Check", + reqd: 1, + }, + ], + (values) => { + frm.call({ + method: "link_contact", + doc: frm.doc, + freeze: true, + freeze_message: __("Linking Contact ..."), + args: { + landa_member: values.landa_member, + is_default_billing: values.is_default_billing, + is_default_shipping: values.is_default_shipping, + }, + callback: (r) => { + if (!r.exc) { + frappe.show_alert({ + message: __("The LANDA Member is now linked as a contact of this Organization and the related Customer"), + indicator: "green", + }); + frm.reload_doc(); + } + }, + }); + } + ); + }); + } }, onload: function (frm) { frm.set_query("public_address", erpnext.queries.address_query); diff --git a/landa/organization_management/doctype/organization/organization.json b/landa/organization_management/doctype/organization/organization.json index f82c5880..689396db 100644 --- a/landa/organization_management/doctype/organization/organization.json +++ b/landa/organization_management/doctype/organization/organization.json @@ -210,7 +210,6 @@ "fieldtype": "Column Break" } ], - "index_web_pages_for_search": 1, "is_tree": 1, "links": [ { @@ -248,13 +247,18 @@ "link_doctype": "Sales Invoice", "link_fieldname": "organization" }, + { + "group": "Bestellwesen", + "link_doctype": "Customer", + "link_fieldname": "organization" + }, { "group": "Gew\u00e4sserverwaltung", "link_doctype": "Water Body Management Local Organization", "link_fieldname": "organization" } ], - "modified": "2023-03-13 23:47:37.901969", + "modified": "2023-08-14 23:44:16.066620", "modified_by": "Administrator", "module": "Organization Management", "name": "Organization", diff --git a/landa/organization_management/doctype/organization/organization.py b/landa/organization_management/doctype/organization/organization.py index 2bd55de6..75f285d6 100644 --- a/landa/organization_management/doctype/organization/organization.py +++ b/landa/organization_management/doctype/organization/organization.py @@ -12,9 +12,11 @@ from frappe.desk.treeview import make_tree_args from frappe.model.naming import make_autoname, revert_series_if_last from frappe.permissions import has_permission -from frappe.utils import cint +from frappe.utils.data import cint, get_link_to_form from frappe.utils.nestedset import NestedSet +from landa.organization_management.doctype.landa_member.landa_member import get_address_or_contact + class Organization(NestedSet): nsm_parent_field = "parent_organization" @@ -195,6 +197,56 @@ def check_permission_on_parent(self, ptype): if not has_permission("Organization", ptype=ptype, doc=parent_organization): frappe.throw(_("Not permitted"), frappe.PermissionError) + @frappe.whitelist() + def link_contact( + self, landa_member: str, is_default_billing: int = 0, is_default_shipping: int = 0 + ): + self.has_permission("write") + + contact = get_address_or_contact("Contact", landa_member) + if not contact: + frappe.throw( + _("There is no single contact linked to {0}.").format( + get_link_to_form("LANDA Member", landa_member) + ) + ) + + address = get_address_or_contact("Address", landa_member) + if not address: + frappe.throw( + _("There is no single address linked to {0}.").format( + get_link_to_form("LANDA Member", landa_member) + ) + ) + + add_links(contact, self.name) + add_links(address, self.name) + + customer = frappe.get_doc("Customer", self.name) + if is_default_billing: + customer.default_billing_contact = contact.name + customer.default_billing_address = address.name + if is_default_shipping: + customer.default_shipping_contact = contact.name + customer.default_shipping_address = address.name + + customer.save() + + +def add_links(address_or_contact, organization: str): + existing_links = {(link.link_doctype, link.link_name) for link in address_or_contact.links} + for doctype in ("Organization", "Customer"): + if (doctype, organization) not in existing_links: + address_or_contact.append( + "links", + { + "link_doctype": doctype, + "link_name": organization, + }, + ) + + address_or_contact.save() + @frappe.whitelist() def get_children(doctype, parent=None, organization=None, is_root=False): diff --git a/landa/translations/de.csv b/landa/translations/de.csv index 0e20fb5d..42c23e40 100644 --- a/landa/translations/de.csv +++ b/landa/translations/de.csv @@ -25,4 +25,12 @@ Water Body Export,Export Gewässerverzeichnis, No permission to set Member Function Category {0},"Sie haben nicht die nötigen Rechte, um eine Mitgliedsfunktion der Kategorie {0} zu vergeben", The {0} Function Category can only be assigned once per member in the same organization., Die Mitgliedsfunktion {0} kann nur einmal pro Mitglied in der gleichen Organisation vergeben werden., Only One per Organization, Nur eine pro Organisation, -LANDA Deliveries and Payments Summaries,Kostenübersicht Zusammenfassung, \ No newline at end of file +LANDA Deliveries and Payments Summaries,Kostenübersicht Zusammenfassung, +Link Member as Contact,Mitglied als Kontakt verknüpfen, +Linking Contact ...,Kontakt wird verknüpft ..., +Is Default Billing Contact,Ist Standard-Rechnungskontakt, +Is Default Shipping Contact,Ist Standard-Lieferkontakt, +Contact has been linked to Organization and Customer, +The LANDA Member is now linked as a contact of this Organization and the related Customer,Das Mitglied ist nun als Kontakt dieses Vereins und des entsprechenden Bestellwesenkontos verknüpft, +There is no single contact linked to {0}.,Es ist kein einzelner Kontakt mit {0} verknüpft., +There is no single address linked to {0}.,Es ist keine einzelne Adresse mit {0} verknüpft.,