Skip to content

Purchasing & Receiving Devices

Context

This documents the full purchase-to-receive workflow in the device_inventory Odoo 19 module. Reyder Enterprises purchases mobile devices from vendors like Apple Wholesale. The workflow covers creating a purchase order, confirming it, uploading an IMEI manifest, scanning devices in via barcode, and marking the manifest complete — which triggers the inventory accounting entry.


Step 1: Create Purchase Order

Path: Purchase → Orders → New

Add device product lines for the devices being purchased. Each line can specify:

  • Product (iPhone 15 Pro Max, Samsung Galaxy S24 Ultra, etc.)
  • Storage capacity (16 GB, 32 GB, 64 GB, 128 GB, 256 GB, 512 GB, 1 TB)
  • Color
  • Grade (Excellent, Good, Fair, Poor)
  • Lock Status
  • Quantity
  • Unit Price

Purchase Order Form

Purchase Orders List


Step 2: Confirm Purchase Order

Click the "Confirm Order" button on the PO form.

What happens on confirm:

  • PO status changes to "Purchase Order"
  • An receiving manifest (device.manifest with manifest_type = 'receiving') is automatically created and linked to the PO
  • The manifest starts in the awaiting_upload state
  • A "Manifests" smart button appears in the PO header chatter area showing the manifest count

Step 3: Upload IMEI Manifest

Click the "Manifests" smart button on the confirmed PO to open the manifest form.

Use the Manifest Upload Wizard to upload a CSV or Excel file containing IMEIs for the devices being received.

CSV Column Reference

Column Required Description
IMEI Yes 15-digit device IMEI
storage No Storage capacity (e.g., 128, 256)
color No Device color
grade No Device grade (Excellent/Good/Fair/Poor)
lock_status No Lock status
purchase_cost No Unit cost for this device
supplier_sku No Vendor's SKU reference
supplier_grade No Vendor's own grade designation
supplier_carton_id No Vendor carton/box identifier

The wizard displays a column-mapping preview before import so you can verify the mapping is correct.

After Upload

  • Manifest status changes to uploaded
  • Manifest lines are created — one per IMEI in the file
  • Each line contains: imei, product_id, storage_capacity, device_color, lock_status, purchase_cost
  • Lines are tagged with an origin_type:
  • po_expected — IMEI matched a PO line (expected quantity)
  • csv_new — Extra IMEI in the file that was not on the original PO

IMEI Manifests List

Manifest Form


Step 4: Barcode Receiving

Path: Barcode app → Manifest Receiving, or click "Receive Devices" on the PO form.

Scan device IMEIs one at a time using a barcode scanner.

How Each Scan Works

Each scan calls _quick_receive() on the matching manifest line:

  1. A pg_try_advisory_xact_lock(imei_hash) is acquired to prevent race conditions if two scanners are operating simultaneously
  2. A stock.lot record is created for the device, storing all specs (IMEI, product, storage, color, grade, lock status, etc.)
  3. A stock.quant record is created to track on-hand quantity at the receiving location
  4. The device's intake_date is set to the current date
  5. The device's qc_status is set to pending_qc — the device must pass QC before it can be sold or allocated
  6. The manifest line's status is updated to received and stock_lot_id is linked to the created lot
  7. The manifest progress bar updates in real-time, showing received_count / expected_count

Unexpected IMEIs

If a scanned IMEI does not match any line in the manifest, the system creates a new manifest line with origin_type = 'barcode_unexpected' rather than rejecting the scan. This handles vendor shipments that include devices not listed on the original PO.


Step 5: Mark Manifest Complete

When all expected devices have been received (or missing ones have been acknowledged), click "Mark Complete" on the manifest form.

This triggers action_mark_complete(), which performs the following in sequence:

  1. Creates the inventory GL accounting entry via _create_inventory_accounting_entry()
  2. Creates a putaway warehouse task via _create_putaway_task() to assign shelf locations
  3. Sets the manifest state to done

Accounting: Receiving GL Entry

When the manifest is marked complete, a journal entry is automatically created and posted:

DR  Device Valuation Account (asset)      $X,XXX.XX
    CR  Device Stock Input Account (GRNI)      $X,XXX.XX
Detail Value
Amount Sum of purchase_cost for all received lines, including unexpected devices
Journal Device Stock Journal (configured in Settings → Inventory)
Posting Auto-posted immediately on manifest completion
Reference Stored on the manifest as account_move_id

The Device Valuation Account and Device Stock Input Account are configured per-company in the Inventory settings under the device_inventory module configuration.


What Happens Behind the Scenes

Step Model Action
1 stock.lot Created per device with all specs: IMEI, product, storage, color, grade, lock status
2 stock.quant Created to track on-hand quantity at the receiving location
3 stock.lot intake_date set to today's date
4 stock.lot qc_status set to pending_qc — blocks sale/allocation until QC is passed
5 device.manifest.line stock_lot_id linked to the newly created lot
6 account.move Inventory GL entry created and auto-posted

Key Fields Reference

Model Field Description
purchase.order manifest_ids One2many link to all receiving manifests for this PO
purchase.order manifest_status Computed field showing receiving progress
device.manifest manifest_type 'receiving' for purchase receipts
device.manifest state draftawaiting_uploaduploadedin_progressdone
device.manifest account_move_id Many2one link to the inventory GL journal entry
device.manifest received_count Count of lines with status = 'received'
device.manifest expected_count Count of lines with origin_type = 'po_expected'
device.manifest.line status expected, received, or missing
device.manifest.line origin_type po_expected, csv_matched, csv_new, barcode_matched, barcode_unexpected
device.manifest.line stock_lot_id Many2one link to the created stock.lot device record
device.manifest.line imei The device IMEI scanned or uploaded
device.manifest.line purchase_cost Per-device cost used for GL entry valuation