{% extends "base.html" %} {% load static erp_tags %} {% block title %}{{ page_title }}{% endblock %} {% block content %}
{% csrf_token %} {% if object_pk %} {% endif %} {# Non-field errors #} {% if form.non_field_errors %}
{% for error in form.non_field_errors %}

{{ error }}

{% endfor %}
{% endif %} {# All field errors — surfaces hidden-tab errors that inline rendering would miss. #} {% if form.errors %}

Please fix the following:

{% endif %} {# Tab Navigation — 2 tabs: Details + More Info #}
{# ===== TAB 1: DETAILS ===== #}
{# Section 1: Order Header #}
{{ doc_type_label|default:"Order" }} Header
{% if doc_number %} {{ doc_number }} {% endif %}
{% for field_name in header_fields %} {% with field=form|get_form_field:field_name %} {% if field %}
{% if field_name == "customer" %}
{{ field|add_class:"form-control form-control-sm" }}
{% else %} {{ field|add_class:"form-control form-control-sm" }} {% endif %} {% if field.errors %}
{{ field.errors.0 }}
{% endif %}
{% endif %} {% endwith %} {% endfor %}
{# Section 2: Address and Contact #}
Address & Contact
{% for field_name in address_fields %} {% with field=form|get_form_field:field_name %} {% if field %}
{% if field_name == 'customer_message' %} {{ field|add_class:"form-control form-control-sm customer-message-sm" }} {% else %} {{ field|add_class:"form-control form-control-sm" }} {% endif %} {% if field_name == "billing_address" or field_name == "shipping_address" %} {% endif %} {% if field_name == "shipping_address" %} {% endif %} {% if field_name == "contact" %} {% endif %}
{% if field_name == "billing_address" or field_name == "shipping_address" %}
{% endif %} {% if field.errors %}
{{ field.errors.0 }}
{% endif %}
{% endif %} {% endwith %} {% endfor %}
{% if is_edit and people_url %}
{% include "erp/_doc_people.html" %}
{% endif %} {# Section 3: Line Items #} {{ line_item_formset.management_form }} {% if show_shipment_groups %} {# ── Shipment-grouped line items (Orders & Quotes) ── #}
{% for sg in shipment_groups_data %}
{# Row 1: Group name + fulfillment toggle + delete #}
{# Row 2: Fulfillment controls #}
{# Drop Ship controls #}
{% if doc_type_label != "Quote" %} {% if sg.existing_po %} {{ sg.existing_po.number }} {% else %} Create PO {% endif %} {% endif %}
{# Internal controls #}
{% if doc_type_label != "Quote" %} {% if sg.existing_pt %} {{ sg.existing_pt.number }} {% else %} {% endif %} {% endif %}
{% for li_form in sg.forms %} {% endfor %}
# Item Code Item Name Qty Rate Disc % Amount Shipment and remove
{% if li_form.move_lock %} Locked to this shipment. {{ li_form.move_lock }} {% else %} {% endif %} {{ li_form.id }} {{ li_form.DELETE|aria_label:"Remove line" }} {{ li_form.sg_index }} {{ li_form.shipment_group }} {{ forloop.counter }}
{{ li_form.variant }}
{% with sku_field=li_form|get_form_field:li_sku_field %}{% endwith %}
{{ li_form.item_name|add_class:"form-control form-control-sm" }}
{{ li_form|get_form_field:li_qty_field|add_class:"form-control form-control-sm text-center li-qty" }}
{{ li_form|get_form_field:li_rate_field|add_class:"form-control form-control-sm text-end li-rate" }}
{{ li_form.discount_percent|add_class:"form-control form-control-sm text-center" }}
{{ li_form|get_form_field:li_total_field|add_class:"form-control form-control-sm text-end li-amount" }}
{% if not li_form.move_lock %} {# Keyboard / touch alternative to dragging. No name: never submitted; the JS fills the options and rewrites sg_index. #} {% endif %} {# A locked line cannot be removed either (the formset refuses it); the button stays in the row so a clone of it (Add Row) gets one. #}
{% endfor %}
{# ── SubOrder Tracking ── #} {% if sub_orders_tracking %}
Tracking
{% for item in sub_orders_tracking %}
{{ item.sub_order.sub_order_number }} {% if item.sub_order.purchase_order %} PO {{ item.sub_order.purchase_order.po_number }} {% elif item.sub_order.pick_ticket %} PT {{ item.sub_order.pick_ticket.ticket_number }} {% endif %}
{% with sub_order=item.sub_order has_customer_email=item.has_customer_email %} {% include "erp/_tracking_section.html" %} {% endwith %}
{% endfor %}
{% endif %} {% else %} {# ── Flat line items table (POs) ── #}
Items
{% for li_form in line_item_formset %} {% endfor %}
# Item Code Item Name Qty Rate Disc % Amount
{{ li_form.id }} {% if li_form.order_line_item %}{{ li_form.order_line_item }}{% endif %} {{ li_form.DELETE|aria_label:"Remove line" }} {{ forloop.counter }}
{{ li_form.variant }}
{% with sku_field=li_form|get_form_field:li_sku_field %}{% endwith %}
{{ li_form.item_name|add_class:"form-control form-control-sm" }}
{{ li_form|get_form_field:li_qty_field|add_class:"form-control form-control-sm text-center li-qty" }}
{{ li_form|get_form_field:li_rate_field|add_class:"form-control form-control-sm text-end li-rate" }}
{{ li_form.discount_percent|add_class:"form-control form-control-sm text-center" }}
{{ li_form|get_form_field:li_total_field|add_class:"form-control form-control-sm text-end li-amount" }}
{% endif %} {# Section 4: Taxes #} {% if tax_fields %}
Taxes
{% for field_name in tax_fields %} {% with field=form|get_form_field:field_name %} {% if field %}
{% if field.field.widget.input_type == "checkbox" %}
{{ field }}
{% else %} {{ field|add_class:"form-control form-control-sm" }} {% endif %}
{% endif %} {% endwith %} {% endfor %}
{% endif %} {# Section 5: Terms #} {% if terms_fields %}
Terms
{% for field_name in terms_fields %} {% with field=form|get_form_field:field_name %} {% if field %}
{% if field.field.widget.input_type == "checkbox" %}
{{ field }}
{% else %} {{ field|add_class:"form-control form-control-sm" }} {% endif %} {% if field.errors %}
{{ field.errors.0 }}
{% endif %}
{% endif %} {% endwith %} {% endfor %}
{% endif %} {# Section 6: Totals #}
Totals
{% for field_name in totals_fields %} {% with field=form|get_form_field:field_name %} {% if field %} {% endif %} {% endwith %} {% endfor %}
{{ field.label }} {% if field_name == "shipping_cost_ex_tax" or field_name == "shipping_cost" %}
{{ field|add_class:"form-control form-control-sm text-end" }}
{% else %} {{ field|add_class:"form-control form-control-sm text-end" }} {% endif %}
{# ===== TAB 2: MORE INFO ===== #}
{% for section in more_info_sections %}
{{ section.title }}
{% if section.collapsible %}{% endif %}
{% for field_name in section.fields %} {% with field=form|get_form_field:field_name %} {% if field %}
{% if field.field.widget.input_type == "checkbox" %}
{{ field }}
{% else %} {{ field|add_class:"form-control form-control-sm" }} {% endif %} {% if field.errors %}
{{ field.errors.0 }}
{% endif %}
{% endif %} {% endwith %} {% endfor %}
{% endfor %} {# ── PO Tracking (linked SubOrder) ── #} {% if po_sub_order_tracking %}
Tracking
{% with sub_order=po_sub_order_tracking.sub_order has_customer_email=po_sub_order_tracking.has_customer_email %} {% include "erp/_tracking_section.html" %} {% endwith %}
{% endif %} {# ── PickTicket Tracking (linked SubOrder) ── #} {% if pt_sub_order_tracking %}
Tracking
{% with sub_order=pt_sub_order_tracking.sub_order has_customer_email=pt_sub_order_tracking.has_customer_email %} {% include "erp/_tracking_section.html" %} {% endwith %}
{% endif %}
{# ===== ACTION BAR ===== #}
{% if is_edit %} {{ object.get_status_display }} {% endif %} {% if is_edit and status_transitions %}
{% endif %} {% comment %} Gated on can_cancel, NOT on doc_type_label. This button used to render on all four documents while only Sales Order handled _action=cancel_order, so cancelling a Purchase Order or Pick Ticket silently just saved it and redirected -- the user believed they had cancelled it. Each view now opts in, and Pick Ticket has no cancelled state so it opts out. {% endcomment %} {% if is_edit and can_cancel and object.status != "cancelled" %} {% endif %} {% if is_edit and doc_type_label == "Sales Order" and object.status != "incomplete" and object.status != "cancelled" %} {% if existing_invoice %} View Invoice {% if existing_invoice.balance_due > 0 and existing_invoice.status != "void" and existing_invoice.status != "cancelled" %} Record Payment {% endif %} {% if existing_invoice.amount_paid > 0 and existing_invoice.status != "void" and existing_invoice.status != "cancelled" %} Refund {% endif %} PDF {% comment %} The real lives OUTSIDE #document-form (see below) and is reached by the form= attribute. A nested is dropped by the HTML5 parser, which silently rebinds this button to #document-form and turns Email into a plain Save. {% endcomment %} {% else %} {% endif %} {% endif %} {% if is_edit and doc_type_label == "Purchase Order" and can_receive %} Receive {% endif %} {% if is_edit and doc_type_label == "Quote" and object.status != "cancelled" %} PDF {% if object.converted_to_order_id %} View Sales Order {% else %} {% endif %} {% if object.superseded_by_id %} View revision {% else %} {% endif %} {% endif %}
Cancel
{% comment %} Send forms, deliberately siblings of #document-form rather than children. Nesting a
is a parse error: the HTML5 parser drops the inner tag, its submit button silently becomes a submit control for the OUTER form, and "Email" POSTs to the edit URL and just saves the document. Verified in Chrome: the nested form does not exist in the DOM at all. Buttons reach these via form="...". {% endcomment %} {% if is_edit and doc_type_label == "Sales Order" and existing_invoice %} {% csrf_token %}{% once_field %}
{% endif %} {% if is_edit and people_url %}
{% csrf_token %}
{% endif %} {% if is_edit and doc_type_label == "Quote" and object.status != "cancelled" %}
{% csrf_token %}{% once_field %}
{% csrf_token %}{% once_field %}
{% endif %} {# ===== RESEND EMAIL MODAL ===== #} {% if is_edit and doc_type_label == "Sales Order" %} {% endif %} {# ===== ADDRESS MODAL ===== #} {# ===== CUSTOMER MODAL ===== #} {# ===== CONTACT MODAL ===== #} {# ===== SHIPPING RATES MODAL ===== #} {# ===== TOAST CONTAINER ===== #}
{% endblock %} {% block javascripts %} {% if show_shipment_groups %} {% endif %} {% if sub_orders_tracking %} {% include "erp/_tracking_section_js.html" %} {% endif %} {% if po_sub_order_tracking %} {% include "erp/_tracking_section_js.html" %} {% endif %} {% if pt_sub_order_tracking %} {% include "erp/_tracking_section_js.html" %} {% endif %} {% if is_edit and people_url %} {% endif %} {% endblock %}