Skip to content

Commit 102ca1f

Browse files
committed
fix: resolve missing item, tax account and payment schedule in PEPPOL parser
Three issues preventing Purchase Invoice creation from incoming EDocuments: 1. Items not matched by name: when no matching_data, buyer_item_id or seller_product_id match exists, try matching by item_name (exact match on Item doctype). Without item_code, set_missing_item_details skips the item and expense_account is never resolved. 2. Tax account_head left empty: the tax guessing stub was a no-op. Now looks up account_head from existing Purchase Taxes templates matching the rate and company. 3. Payment schedule entry with only due_date (no payment_amount) caused a TypeError in set_payment_schedule. Don't create a default entry; let ERPNext compute it from payment_terms_template.
1 parent 3748406 commit 102ca1f

File tree

1 file changed

+31
-13
lines changed

1 file changed

+31
-13
lines changed

edocument/edocument/profiles/peppol/parser.py

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -464,9 +464,9 @@ def parse_peppol_payment_terms(root, namespaces, default_due_date=None):
464464

465465
payment_schedule.append(schedule_item)
466466

467-
# If no payment terms found, add default one
468-
if not payment_schedule and default_due_date:
469-
payment_schedule.append({"doctype": "Payment Schedule", "due_date": default_due_date})
467+
# Don't add a default payment_schedule entry with only due_date.
468+
# ERPNext will compute the schedule from payment_terms_template (set via supplier defaults)
469+
# or the user can add it manually. Adding an entry without payment_amount causes errors.
470470

471471
return payment_schedule
472472

@@ -578,6 +578,17 @@ def guess_missing_values(pi_data):
578578
except Exception:
579579
pass
580580

581+
# Guess item code from item name (exact match)
582+
if not item.get("item_code") and item.get("item_name"):
583+
item_name = item["item_name"]
584+
# Try item_code = item_name first, then search by item_name field
585+
if frappe.db.exists("Item", item_name):
586+
item["item_code"] = item_name
587+
else:
588+
item_code = frappe.db.get_value("Item", {"item_name": item_name}, "name")
589+
if item_code:
590+
item["item_code"] = item_code
591+
581592
# Remove temporary fields (if they exist)
582593
if "seller_product_id" in item:
583594
item.pop("seller_product_id")
@@ -593,17 +604,24 @@ def guess_missing_values(pi_data):
593604
if not item.get("purchase_order"):
594605
item["purchase_order"] = pi_data["purchase_order"]
595606

596-
# Guess tax accounts for taxes (simplified - you may need to map based on your tax setup)
607+
# Guess tax accounts for taxes from existing Purchase Taxes templates
608+
company = pi_data.get("company")
597609
for tax in pi_data.get("taxes", []):
598-
if not tax.get("account_head") and tax.get("rate"):
599-
# Try to find a default tax account based on rate
600-
# This is a simplified approach - you may need to customize this
601-
try:
602-
# Get default tax account from company settings or tax template
603-
# For now, leave it empty - user will need to set it manually
604-
pass
605-
except Exception:
606-
pass
610+
if not tax.get("account_head") and tax.get("rate") and company:
611+
tax_rate = tax["rate"]
612+
# Find a Purchase Taxes template for this company with a matching rate
613+
account_head = frappe.db.sql(
614+
"""SELECT child.account_head
615+
FROM `tabPurchase Taxes and Charges` child
616+
JOIN `tabPurchase Taxes and Charges Template` parent ON child.parent = parent.name
617+
WHERE child.rate = %s AND parent.company = %s
618+
LIMIT 1""",
619+
(tax_rate, company),
620+
)
621+
if account_head:
622+
tax["account_head"] = account_head[0][0]
623+
if not tax.get("description") and tax.get("rate"):
624+
tax["description"] = f"VAT {tax['rate']}%"
607625

608626

609627
def guess_po_details(pi_data):

0 commit comments

Comments
 (0)