# ======= SHARED HELPERS ======= import frappe from datetime import datetime 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 def _parse_load_date(value): """Parse the date formats the e-taxes loaders use ('YYYY-MM-DD' or 'DD-MM-YYYY[ HH:MM]'). Returns a datetime.date or None.""" if not value: return None token = str(value).strip().split(" ")[0] for fmt in ("%Y-%m-%d", "%d-%m-%Y"): try: return datetime.strptime(token, fmt).date() except ValueError: continue return None def exceeds_one_year(date_from, date_to): """True if [date_from, date_to] spans more than one year (366 days). Used to forbid loading more than a year of data in a single run — applies to every e-taxes load (invoices, reference data, VAT) EXCEPT Company data.""" df = _parse_load_date(date_from) dt = _parse_load_date(date_to) return bool(df and dt and (dt - df).days > 366)