fix(api): wire order_item_reason_policy into POST/PUT and persist reason fields (#345)
Adds `reason_code`, `reason_label_snapshot`, `reason_comment` columns to `order_items` and integrates the `order_item_reason_policy` class into the POST and PUT /order/items routes. Validation order on audited products (consistent across POST and PUT): 1. If `reason_code` is present, validate reason first — emits the most specific error (invalid code, deprecated code, missing reason_comment). 2. If notes are provided but empty/whitespace, return "Notes is required for this product" (the legacy message). 3. Otherwise run reason validation — covers the missing-reason_code case. PHP api suite went from 284/290 to 290/290 (was 6 OrderItemsApiTest failures, now 0). Wired `addItemToOrder`, `updateOrderItem`, and `getItemAsArray` to persist and return the new columns.
This commit is contained in:
@@ -60,6 +60,21 @@ class order_items_o extends db
|
||||
* @var object_property
|
||||
*/
|
||||
public object_property $include_in_invoice;
|
||||
/**
|
||||
* Approved reason code (e.g. customer_approved_extra_work) for audited products
|
||||
* @var object_property
|
||||
*/
|
||||
public object_property $reason_code;
|
||||
/**
|
||||
* Snapshot of the human-readable label for the reason code at write time
|
||||
* @var object_property
|
||||
*/
|
||||
public object_property $reason_label_snapshot;
|
||||
/**
|
||||
* Free-text reason comment when the policy requires one
|
||||
* @var object_property
|
||||
*/
|
||||
public object_property $reason_comment;
|
||||
|
||||
public function structure(): void
|
||||
{
|
||||
@@ -90,6 +105,9 @@ class order_items_o extends db
|
||||
$this->quantity = new object_property($this->table, $this->id, 'quantity', 'int', true);
|
||||
$this->related_item_id = new object_property($this->table, $this->id, 'related_item_id', 'int', false);
|
||||
$this->include_in_invoice = new object_property($this->table, $this->id, 'include_in_invoice', 'bool', false);
|
||||
$this->reason_code = new object_property($this->table, $this->id, 'reason_code', 'string', false);
|
||||
$this->reason_label_snapshot = new object_property($this->table, $this->id, 'reason_label_snapshot', 'string', false);
|
||||
$this->reason_comment = new object_property($this->table, $this->id, 'reason_comment', 'string', false);
|
||||
}
|
||||
|
||||
private static function validatedRelatedItemId(int $orderId, mixed $relatedItemId): ?int
|
||||
@@ -204,7 +222,7 @@ class order_items_o extends db
|
||||
}
|
||||
}
|
||||
|
||||
public function addItemToOrder(int $order_id, int $product_id, int $cashier_id, int $quantity, $related_item_id = null, $notes = null, $forcePrice = null): order_items_o
|
||||
public function addItemToOrder(int $order_id, int $product_id, int $cashier_id, int $quantity, $related_item_id = null, $notes = null, $forcePrice = null, ?string $reason_code = null, ?string $reason_label_snapshot = null, ?string $reason_comment = null): order_items_o
|
||||
{
|
||||
global $db, $response;
|
||||
try {
|
||||
@@ -230,7 +248,7 @@ class order_items_o extends db
|
||||
}
|
||||
|
||||
// Create a new record in the database
|
||||
$sql = "INSERT INTO $this->table (order_id, product_id, price, cashier_id, quantity) VALUES ($order_id, $product_id, $price, $cashier_id, $quantity)";
|
||||
$sql = "INSERT INTO $this->table (order_id, product_id, price, cashier_id, quantity, reason_code, reason_label_snapshot, reason_comment) VALUES ($order_id, $product_id, $price, $cashier_id, $quantity, " . ($reason_code !== null ? "'" . $db->escape_string($reason_code) . "'" : "NULL") . ", " . ($reason_label_snapshot !== null ? "'" . $db->escape_string($reason_label_snapshot) . "'" : "NULL") . ", " . ($reason_comment !== null ? "'" . $db->escape_string($reason_comment) . "'" : "NULL") . ")";
|
||||
$db->query($sql);
|
||||
// Get the id of the new record
|
||||
$this->id = $db->insert_id();
|
||||
@@ -288,6 +306,9 @@ class order_items_o extends db
|
||||
'product' => (array)(new products_o())->getProductById($this->product_id->value())->asArray(),
|
||||
'cashier' => (array)(new users_o())->getUserById($this->cashier_id->value())->asArray(),
|
||||
'include_in_invoice' => (bool)$this->include_in_invoice->value(),
|
||||
'reason_code' => $this->reason_code->value(),
|
||||
'reason_label_snapshot' => $this->reason_label_snapshot->value(),
|
||||
'reason_comment' => $this->reason_comment->value(),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -314,7 +335,7 @@ class order_items_o extends db
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function updateOrderItem(int $id, int $price, string $notes, string $reference, int $quantity): void
|
||||
public function updateOrderItem(int $id, int $price, string $notes, string $reference, int $quantity, ?string $reason_code = null, ?string $reason_label_snapshot = null, ?string $reason_comment = null): void
|
||||
{
|
||||
global $db, $response;
|
||||
$this->select((int)$id);
|
||||
@@ -332,6 +353,15 @@ class order_items_o extends db
|
||||
$this->notes->set($notes);
|
||||
$this->reference->set($reference);
|
||||
$this->quantity->set($quantity);
|
||||
if ($reason_code !== null) {
|
||||
$this->reason_code->set($reason_code);
|
||||
}
|
||||
if ($reason_label_snapshot !== null) {
|
||||
$this->reason_label_snapshot->set($reason_label_snapshot);
|
||||
}
|
||||
if ($reason_comment !== null) {
|
||||
$this->reason_comment->set($reason_comment);
|
||||
}
|
||||
// Set the values of the object properties
|
||||
$this->getObjectProperties();
|
||||
$this->objectChanged();
|
||||
|
||||
Reference in New Issue
Block a user