fix: don't assign group-type Customer/Supplier Group to auto-created parties
Recent ERPNext rejects assigning a group-type Customer Group to a Customer
("Cannot select a Group type Customer Group"); customer_group is also no
longer mandatory. The integration fell back to "All Customer Groups" (a
group node), so every auto-created party failed.
- add invoice_az/utils.py:resolve_customer_group() — returns the configured
group only if it exists and is not a group node, else None
- api.py / vat_api.py: skip customer_group when no valid non-group value;
create the Customer without a group instead of forcing "All Customer Groups"
- add link_filters (is_group=0) to all Customer/Supplier Group pickers in
E-Taxes Settings and the mapping child tables
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
530289e94c
commit
a90fe340d5
|
|
@ -11,6 +11,7 @@ import time
|
|||
|
||||
# Импорты из модуля аутентификации
|
||||
from invoice_az.auth import record_etaxes_activity, get_default_asan_login
|
||||
from .utils import resolve_customer_group
|
||||
from .sales_api import get_sales_invoices
|
||||
|
||||
|
||||
|
|
@ -3153,12 +3154,16 @@ def create_unmapped_customers():
|
|||
customer_doc.customer_name = etaxes_customer.etaxes_party_name
|
||||
customer_doc.customer_type = "Company" # Can be configured if needed
|
||||
|
||||
# Apply settings considering individual priorities
|
||||
customer_group = individual_settings.get('customer_group', settings_doc.default_customer_group)
|
||||
if not frappe.db.exists('Customer Group', customer_group):
|
||||
customer_group = "All Customer Groups"
|
||||
customer_doc.customer_group = customer_group
|
||||
|
||||
# Apply settings considering individual priorities.
|
||||
# Only assign a Customer Group if a valid, non-group one is configured;
|
||||
# otherwise leave it empty (ERPNext rejects group-type Customer Groups
|
||||
# and the field is no longer mandatory).
|
||||
customer_group = resolve_customer_group(
|
||||
individual_settings.get('customer_group') or settings_doc.default_customer_group
|
||||
)
|
||||
if customer_group:
|
||||
customer_doc.customer_group = customer_group
|
||||
|
||||
# Territory
|
||||
territory = individual_settings.get('territory', "All Territories")
|
||||
if not frappe.db.exists('Territory', territory):
|
||||
|
|
@ -3401,12 +3406,16 @@ def create_unmapped_customers_v2():
|
|||
customer_doc.customer_name = customer_name
|
||||
customer_doc.customer_type = "Company" # Can be configured if needed
|
||||
|
||||
# Apply settings considering individual priorities
|
||||
customer_group = individual_settings.get('customer_group', settings_doc.default_customer_group)
|
||||
if not frappe.db.exists('Customer Group', customer_group):
|
||||
customer_group = "All Customer Groups"
|
||||
customer_doc.customer_group = customer_group
|
||||
|
||||
# Apply settings considering individual priorities.
|
||||
# Only assign a Customer Group if a valid, non-group one is configured;
|
||||
# otherwise leave it empty (ERPNext rejects group-type Customer Groups
|
||||
# and the field is no longer mandatory).
|
||||
customer_group = resolve_customer_group(
|
||||
individual_settings.get('customer_group') or settings_doc.default_customer_group
|
||||
)
|
||||
if customer_group:
|
||||
customer_doc.customer_group = customer_group
|
||||
|
||||
# Territory
|
||||
territory = individual_settings.get('territory', "All Territories")
|
||||
if not frappe.db.exists('Territory', territory):
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
"fieldname": "customer_group",
|
||||
"fieldtype": "Link",
|
||||
"label": "Customer Group",
|
||||
"link_filters": "[[\"Customer Group\",\"is_group\",\"=\",0]]",
|
||||
"options": "Customer Group"
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@
|
|||
"fieldname": "supplier_group",
|
||||
"fieldtype": "Link",
|
||||
"label": "Supplier Group",
|
||||
"link_filters": "[[\"Supplier Group\",\"is_group\",\"=\",0]]",
|
||||
"options": "Supplier Group"
|
||||
},
|
||||
{
|
||||
|
|
@ -78,6 +79,7 @@
|
|||
"fieldname": "customer_group",
|
||||
"fieldtype": "Link",
|
||||
"label": "Customer Group",
|
||||
"link_filters": "[[\"Customer Group\",\"is_group\",\"=\",0]]",
|
||||
"options": "Customer Group"
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -103,12 +103,14 @@
|
|||
"fieldname": "default_supplier_group",
|
||||
"fieldtype": "Link",
|
||||
"label": "Default Supplier Group",
|
||||
"link_filters": "[[\"Supplier Group\",\"is_group\",\"=\",0]]",
|
||||
"options": "Supplier Group"
|
||||
},
|
||||
{
|
||||
"fieldname": "default_customer_group",
|
||||
"fieldtype": "Link",
|
||||
"label": "Default Customer Group",
|
||||
"link_filters": "[[\"Customer Group\",\"is_group\",\"=\",0]]",
|
||||
"options": "Customer Group"
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
"fieldname": "supplier_group",
|
||||
"fieldtype": "Link",
|
||||
"label": "Supplier Group",
|
||||
"link_filters": "[[\"Supplier Group\",\"is_group\",\"=\",0]]",
|
||||
"options": "Supplier Group"
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
# ======= SHARED HELPERS =======
|
||||
|
||||
import frappe
|
||||
|
||||
|
||||
def resolve_customer_group(preferred=None):
|
||||
"""Return a usable (non-group) Customer Group, or None.
|
||||
|
||||
Newer ERPNext rejects assigning a Customer to a "group" type Customer Group
|
||||
(e.g. the root "All Customer Groups"), and `customer_group` is no longer a
|
||||
mandatory field. So:
|
||||
- if a valid, non-group Customer Group is configured -> use it
|
||||
- otherwise return None and let the Customer be created without a group
|
||||
"""
|
||||
if preferred and frappe.db.exists("Customer Group", preferred):
|
||||
if not frappe.db.get_value("Customer Group", preferred, "is_group"):
|
||||
return preferred
|
||||
return None
|
||||
|
||||
|
||||
def resolve_territory(preferred=None):
|
||||
"""Return a usable Territory, or None if the configured one is missing.
|
||||
|
||||
Mirrors :func:`resolve_customer_group`; Territory root nodes are still
|
||||
accepted by ERPNext, so we only validate existence.
|
||||
"""
|
||||
if preferred and frappe.db.exists("Territory", preferred):
|
||||
return preferred
|
||||
return None
|
||||
|
|
@ -8,6 +8,7 @@ import json
|
|||
from datetime import datetime
|
||||
from frappe.utils import now_datetime, getdate
|
||||
from invoice_az.auth import record_etaxes_activity, get_default_asan_login
|
||||
from invoice_az.utils import resolve_customer_group
|
||||
|
||||
# API Endpoint
|
||||
VAT_OPERATIONS_URL = "https://new.e-taxes.gov.az/api/po/vatacc/public/v1/operation/find.outbox"
|
||||
|
|
@ -349,17 +350,19 @@ def find_or_create_customer_from_vat_operation(tin, name, settings_doc, auto_cre
|
|||
return customer['name']
|
||||
|
||||
# Шаг 4: Создание нового Customer
|
||||
# Получаем default customer group
|
||||
default_customer_group = settings_doc.default_customer_group if settings_doc else None
|
||||
if not default_customer_group or not frappe.db.exists('Customer Group', default_customer_group):
|
||||
default_customer_group = 'All Customer Groups'
|
||||
# Берём настроенную группу только если она валидна и не является group-узлом;
|
||||
# иначе создаём Customer без группы (ERPNext запрещает group-type Customer Group).
|
||||
default_customer_group = resolve_customer_group(
|
||||
settings_doc.default_customer_group if settings_doc else None
|
||||
)
|
||||
|
||||
# Создаем Customer (с защитой от race condition)
|
||||
try:
|
||||
customer_doc = frappe.new_doc('Customer')
|
||||
customer_doc.customer_name = name or f"Customer-{tin}"
|
||||
customer_doc.customer_type = 'Company'
|
||||
customer_doc.customer_group = default_customer_group
|
||||
if default_customer_group:
|
||||
customer_doc.customer_group = default_customer_group
|
||||
customer_doc.territory = 'All Territories'
|
||||
customer_doc.tax_id = tin
|
||||
|
||||
|
|
@ -410,7 +413,7 @@ def _create_or_update_etaxes_customer_and_mapping(tin, etaxes_name, erp_customer
|
|||
if settings_doc:
|
||||
if existing_mapping_row:
|
||||
# Используем прямое обновление child table через SQL
|
||||
default_customer_group = settings_doc.default_customer_group if settings_doc.default_customer_group else 'All Customer Groups'
|
||||
default_customer_group = resolve_customer_group(settings_doc.default_customer_group)
|
||||
|
||||
# Обновляем через frappe.db.sql напрямую
|
||||
frappe.db.sql("""
|
||||
|
|
@ -438,7 +441,7 @@ def _create_or_update_etaxes_customer_and_mapping(tin, etaxes_name, erp_customer
|
|||
'etaxes_customer_name': etaxes_name or f"Customer-{tin}",
|
||||
'etaxes_tax_id': tin,
|
||||
'erp_customer': erp_customer,
|
||||
'customer_group': settings_doc.default_customer_group if settings_doc.default_customer_group else 'All Customer Groups',
|
||||
'customer_group': resolve_customer_group(settings_doc.default_customer_group),
|
||||
'territory': 'All Territories',
|
||||
'mapping_type': 'Automatic'
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in New Issue