django_program.registration.services.purchase_orders¶
Service layer for purchase order lifecycle management.
Handles PO creation, payment recording, credit note issuance, status transitions, cancellation, and invoice PDF generation. All state-mutating functions use atomic transactions to maintain consistency.
Functions
|
Cancel a purchase order. |
|
Create a purchase order with line items and computed totals. |
|
Generate a professional invoice PDF for a purchase order. |
Generate a unique PO reference like |
|
|
Issue a credit note against a purchase order and update its status. |
|
Record a payment against a purchase order and update its status. |
|
Transition a draft purchase order to sent status. |
|
Recompute and save the PO status based on payments and credits. |
- django_program.registration.services.purchase_orders.generate_po_reference()[source]¶
Generate a unique PO reference like
PO-A1B2C3.Uses cryptographically random alphanumeric characters. Retries on collision up to a fixed limit.
- Return type:
- Returns:
A unique reference string.
- Raises:
RuntimeError – If a unique reference cannot be generated after multiple attempts.
- django_program.registration.services.purchase_orders.create_purchase_order(*, conference, organization_name, contact_email, contact_name, billing_address='', line_items, notes='', created_by=None)[source]¶
Create a purchase order with line items and computed totals.
Each entry in
line_itemsshould be a dict with keys:description,quantity,unit_price, and optionallyticket_typeandaddon(model instances or None).- Parameters:
conference (
Conference) – The conference this PO belongs to.organization_name (
str) – Name of the purchasing organization.contact_email (
str) – Primary contact email address.contact_name (
str) – Primary contact person name.billing_address (
str) – Optional billing address text.line_items (
list[dict[str,object]]) – List of line item dicts to create.notes (
str) – Optional internal notes.created_by (
AbstractBaseUser|None) – The staff user creating the PO.
- Return type:
- Returns:
The newly created PurchaseOrder with line items.
- Raises:
RuntimeError – If a unique reference cannot be generated.
IntegrityError – On reference collision (extremely unlikely).
- django_program.registration.services.purchase_orders.record_payment(purchase_order, *, amount, method, reference='', payment_date, entered_by=None, note='')[source]¶
Record a payment against a purchase order and update its status.
- Parameters:
purchase_order (
PurchaseOrder) – The PO to record payment against.amount (
Decimal) – Payment amount (must be positive).method (
str) – Payment method (one of PurchaseOrderPayment.Method values).reference (
str) – Optional external reference (e.g. wire transfer ID).payment_date (
date) – Date the payment was received.entered_by (
AbstractBaseUser|None) – Staff user recording the payment.note (
str) – Optional note about the payment.
- Return type:
- Returns:
The newly created PurchaseOrderPayment.
- Raises:
ValueError – If the amount is not positive, the method is invalid, or the PO is cancelled.
- django_program.registration.services.purchase_orders.issue_credit_note(purchase_order, *, amount, reason, issued_by=None)[source]¶
Issue a credit note against a purchase order and update its status.
- Parameters:
purchase_order (
PurchaseOrder) – The PO to issue a credit note against.amount (
Decimal) – Credit note amount (must be positive).reason (
str) – Explanation for the credit.issued_by (
AbstractBaseUser|None) – Staff user issuing the credit note.
- Return type:
- Returns:
The newly created PurchaseOrderCreditNote.
- Raises:
ValueError – If the amount is not positive or the PO is cancelled.
- django_program.registration.services.purchase_orders.update_po_status(purchase_order)[source]¶
Recompute and save the PO status based on payments and credits.
Status transitions: -
draftremains if no payments/credits and status is draft -paidwhen balance_due is exactly zero and financial activity exists -overpaidwhen balance_due is negative -partially_paidwhen some payments exist but balance remains -sentwhen no payments exist and status is not draftThis function expects the caller to hold a row-level lock on the PO (via
select_for_update) when called inside a transaction.- Parameters:
purchase_order (
PurchaseOrder) – The PO whose status should be recomputed.- Return type:
- django_program.registration.services.purchase_orders.send_purchase_order(purchase_order)[source]¶
Transition a draft purchase order to sent status.
- Parameters:
purchase_order (
PurchaseOrder) – The PO to mark as sent.- Raises:
ValueError – If the PO is not in draft status.
- Return type:
- django_program.registration.services.purchase_orders.cancel_purchase_order(purchase_order)[source]¶
Cancel a purchase order.
Sets the status to CANCELLED. Does not delete any associated payment or credit note records for audit purposes.
- Parameters:
purchase_order (
PurchaseOrder) – The PO to cancel.- Return type:
- django_program.registration.services.purchase_orders.generate_invoice_pdf(purchase_order)[source]¶
Generate a professional invoice PDF for a purchase order.
Produces a PDF with conference letterhead, billing details, line items, financial summary, and payment history. Uses the same reportlab pattern as the invitation letter generator.
- Parameters:
purchase_order (
PurchaseOrder) – The purchase order to generate an invoice for.- Return type:
- Returns:
The raw PDF bytes.