softDelete features
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../classes_ac/PostingWindowGuard.php';
|
||||
|
||||
/**
|
||||
* OrderManager
|
||||
@@ -992,6 +993,111 @@ class OrderManager {
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Soft-delete an order by negating company_id on the header, items, and all
|
||||
* linked stock-out rows. Approved stock-out side effects are reversed first.
|
||||
* Blocked if any invoice or return (not yet soft-deleted) exists for this order.
|
||||
*/
|
||||
public function softDelete(int $id): void
|
||||
{
|
||||
$sth = $this->pdo->prepare(
|
||||
"SELECT * FROM td_order WHERE company_id = :cid AND id = :id"
|
||||
);
|
||||
$sth->execute([':cid' => $this->company_id, ':id' => $id]);
|
||||
$order = $sth->fetch(PDO::FETCH_ASSOC);
|
||||
if (!$order) throw new Exception('Sales order not found.');
|
||||
|
||||
global $pdo1;
|
||||
if (isset($pdo1) && $pdo1 instanceof PDO) {
|
||||
$guard = new PostingWindowGuard($pdo1, $this->company_id);
|
||||
$guard->assertOpenDate($order['order_date'] ?: date('Y-m-d'), 'Order deletion');
|
||||
}
|
||||
|
||||
$sth2 = $this->pdo->prepare(
|
||||
"SELECT COUNT(*) FROM td_invoice
|
||||
WHERE company_id = :cid AND order_id = :id"
|
||||
);
|
||||
$sth2->execute([':cid' => $this->company_id, ':id' => $id]);
|
||||
if ((int)$sth2->fetchColumn() > 0) {
|
||||
throw new Exception('Cannot delete — this order has linked invoices. Delete the invoices first.');
|
||||
}
|
||||
|
||||
$sth3 = $this->pdo->prepare(
|
||||
"SELECT COUNT(*) FROM td_return
|
||||
WHERE company_id = :cid AND order_id = :id"
|
||||
);
|
||||
$sth3->execute([':cid' => $this->company_id, ':id' => $id]);
|
||||
if ((int)$sth3->fetchColumn() > 0) {
|
||||
throw new Exception('Cannot delete — this order has linked returns. Delete the returns first.');
|
||||
}
|
||||
|
||||
// Block if any approved stock-out rows exist; user must reverse via ICS first
|
||||
$sth4 = $this->pdo->prepare(
|
||||
"SELECT table_name FROM information_schema.tables
|
||||
WHERE table_schema = DATABASE() AND table_name LIKE 'td_stock_%'"
|
||||
);
|
||||
$sth4->execute();
|
||||
$tables = $sth4->fetchAll(PDO::FETCH_COLUMN);
|
||||
|
||||
foreach ($tables as $table) {
|
||||
$chk = $this->pdo->prepare(
|
||||
"SELECT COUNT(*) FROM `{$table}`
|
||||
WHERE company_id = :cid AND source = 'order' AND source_id = :id AND type = 'out' AND status = 1"
|
||||
);
|
||||
$chk->execute([':cid' => $this->company_id, ':id' => $id]);
|
||||
if ((int)$chk->fetchColumn() > 0) {
|
||||
throw new Exception('Cannot delete — stock-out for this order has been approved. Reverse via ICS first.');
|
||||
}
|
||||
}
|
||||
|
||||
// Negate draft/pending stock-out rows (status != 1)
|
||||
foreach ($tables as $table) {
|
||||
$this->pdo->prepare(
|
||||
"UPDATE `{$table}` SET company_id = company_id * -1
|
||||
WHERE company_id = :cid AND source = 'order' AND source_id = :id AND type = 'out' AND status != 1"
|
||||
)->execute([':cid' => $this->company_id, ':id' => $id]);
|
||||
}
|
||||
|
||||
// Release converted_qty on source quotation
|
||||
$source = (string)($order['source'] ?? '');
|
||||
$source_id = (int)($order['source_id'] ?? 0);
|
||||
if ($source === 'quotation' && $source_id > 0) {
|
||||
$sth5 = $this->pdo->prepare(
|
||||
"SELECT item_id, quantity FROM td_order_item
|
||||
WHERE order_id = :id AND company_id = :cid ORDER BY item_id"
|
||||
);
|
||||
$sth5->execute([':id' => $id, ':cid' => $this->company_id]);
|
||||
$items = $sth5->fetchAll(PDO::FETCH_ASSOC);
|
||||
$dec = $this->pdo->prepare(
|
||||
"UPDATE td_quotation_item
|
||||
SET converted_qty = GREATEST(0, converted_qty - :qty)
|
||||
WHERE quotation_id = :qid AND item_id = :item_id AND company_id = :cid"
|
||||
);
|
||||
foreach ($items as $item) {
|
||||
$dec->execute([
|
||||
':qty' => (float)($item['quantity'] ?? 0),
|
||||
':qid' => $source_id,
|
||||
':item_id' => (int)($item['item_id'] ?? 0),
|
||||
':cid' => $this->company_id,
|
||||
]);
|
||||
}
|
||||
$this->pdo->prepare(
|
||||
"UPDATE td_quotation SET status = 2
|
||||
WHERE id = :id AND company_id = :cid AND status = 5"
|
||||
)->execute([':id' => $source_id, ':cid' => $this->company_id]);
|
||||
}
|
||||
|
||||
$this->pdo->prepare(
|
||||
"UPDATE td_order_item SET company_id = company_id * -1
|
||||
WHERE order_id = :id AND company_id = :cid"
|
||||
)->execute([':id' => $id, ':cid' => $this->company_id]);
|
||||
|
||||
$this->pdo->prepare(
|
||||
"UPDATE td_order SET company_id = company_id * -1
|
||||
WHERE id = :id AND company_id = :cid"
|
||||
)->execute([':id' => $id, ':cid' => $this->company_id]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update shipping tracking number. Fulfillment itself is derived from
|
||||
* linked stock-out rows and tracking, not selected manually.
|
||||
|
||||
Reference in New Issue
Block a user