Skip to content

Purchase Order

Module: purchase_order. The commitment to a vendor, raised from an approved RFQ bid or straight from a requisition, approved through routing, printed on the client's template, and the trigger for expediting and goods receipt.

How this page was verified

Written from master on 2026-09-06 and compared with the big five the same day. No earlier page existed. A map, not a line-by-line trace: 33 files, about 580 database calls.

Where it sits

Requisition (spb_id) / RFQ bid (rfq_id, vendor_prop_quo_id)  →  Purchase Order
        →  Expediting (expedite, milestones)  →  Goods Received Report (mrr)  →  invoices

The data

TableHolds
ts_purchase_orderthe header. Identity: po_no, po_title, po_desc, po_date, revision, project_id, category_id. Sources: spb_id, rfq_id, vendor_prop_quo_id, so_id, ref_number, doc_ref. Vendor: vendor_id, vendor_contact_id, vendor_reference, contact, phone. Commercial: currency_id, tax, discount, freight_and_handling, insurance, other_charges, documentation, fob_charges, comission, total, payment_terms_id, invoicing_terms, condition_terms_*. Delivery: delivery_date, delivery_place, delivery_address, delivery_option, deliver_to_id, incoterms_id, mode_transport_id, packing_type_id, shipping_mark, origin_country, ex_factory_date, milestone_list. Contract: contract_id, agreement_type_code, effective_date. Approval: status_save, submit_approval, status_approval, fg_approval, person_prepared_by, person_approved_by, person_for_info.
ts_purchase_order_itemthe line items
ts_file_referenceuploads and the generated PDF
ts_procurement_documents, ts_map_procurement_doc_file, ts_procurement_doc_librarywhere the approved PDF is filed

The screen

purchase_order.php with purchase_order_browse.htm: grid, a header form split into main, commercial and delivery tabs (each with its own post handler), an items grid, attachments (upload, select, import), a vendor and vendor-contact sub-register, print, export (CSV, matrix), move item up or down, and the routing form. Toolbar: New, Edit, Delete, Cancel, Print, Export, Help.

Numbering: increment_po, increment_po_a, increment_po_t per years, with proc_number_temp before save. A revision is a new header row for the same po_no; findPurchaseOrderByNumberAndRev() in the class resolves the pair.

Approval and what happens after

  1. Routing form (purchase_order_handler_routing_form.php and _routing_post.php, on $pdo): the user picks the vendor, the document reference (requisition or RFQ), the agreement type, attention and cc contacts, the preparer and the document date (the IR20___* fields), then submits.
  2. Routing: purchase_order_handler_post.php posts with 'rout_group_mod' => 'procurement' and sets submit_approval = 1, status_approval = 0. The routing is an ordinary Document Routing entry with routing_procure = 1.
  3. On completion, RoutingProcurementUc calls purchase_order.class.php, which implements RoutingProcurementInterface:
    • ProcessProcurement() updates the header;
    • GenerateDocument() renders the PO through purchase_order_print_process.php and the print flavour;
    • StoreDocumentsToProcumentDocs() registers it in Procurement Documents under a per-PO folder;
    • handlerExpediteModule() creates the expediting record and its milestone details from milestone_list, so the PO appears in Material Expediting;
    • NotificationProcurement() notifies.

Cancel (act=cancelPurchaseOrder, cancelpo) resets submit_approval and status_approval to 0.

Printing

The PO print layout is editable: template_po_updates.php and _json_template_po.php hold the box-and-grid JSON, the same mechanism as so_templates in inweb_config. Which flavour class renders it comes from procure_print_template_code. A discount variant exists in purchase_order_handler_print_browse_discount.inc.php.

What still runs on the legacy helper

Counted on 2026-09-06: 112 calls to iw_mysql_query() against 471 uses of $pdo, and 106 of the 112 are in purchase_order_handler_form_041214.php, a dated backup that is not routed. The live module is on $pdo except the multi-file upload (purchase_order_multiupload_upload.php, 4 legacy calls) and one call in the post handler. Of the four chain modules this is the one that was migrated.

Gotchas

  • Two ways in. A PO can reference a requisition directly (spb_id) or an approved bid (rfq_id plus vendor_prop_quo_id). Reports that count "POs from RFQs" miss the direct ones.
  • A revision is a new row. Queries by po_no alone return every revision.
  • Expediting is created on approval, not on save. A PO that never completes routing never appears in Material Expediting.
  • The multi-file upload is dead where the legacy helper throws; use the attachment select path.

Instance differences

Checked on 2026-09-06.

InstanceDifference
JOTREInstalled. Twelve files differ from master and one is added. The form, print, preview and routing post handlers push approved POs to Accurate (accurate_push_po.php and the sync crons). Carries a purchase_order.inc.php.bak_costcode leftover.
Jadestone, Medco, TimasNot installed in their QA databases. Two or three files differ from master.