| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- <?php
- require_once __DIR__ . '/../lib/identity.php';
- require_once __DIR__ . '/../lib/jobs.php';
- [$actor, $vendor_id] = resolve_request_actor();
- $pdo = db();
- $job_id = (int) ($_POST['job_id'] ?? 0);
- $action = $_POST['action'] ?? '';
- $column = $_POST['column'] ?? '';
- $value = $_POST['value'] ?? '';
- if ($job_id <= 0) {
- http_response_code(400);
- echo 'Bad job_id';
- return;
- }
- $stmt = $pdo->prepare('SELECT * FROM jobs WHERE id = ?');
- $stmt->execute([$job_id]);
- $job = $stmt->fetch();
- if (!$job) {
- http_response_code(404);
- echo 'Job not found';
- return;
- }
- // Vendor-side requests are scoped to their own jobs.
- if ($actor !== 'ICG' && (int) $job['vendor_id'] !== $vendor_id) {
- http_response_code(403);
- echo 'Wrong vendor';
- return;
- }
- // --- Button-driven state transitions ---
- // Undo is dynamic: it reverses one step based on current status. Vendors only.
- // Once ICG marks Received, undo is no longer available (vendor would need to
- // message ICG to get them to back it out).
- if ($action === 'undo') {
- if ($actor === 'ICG') {
- http_response_code(403);
- echo 'Undo is a vendor action';
- return;
- }
- if ($job['status'] === 'Finished') {
- apply_job_change($job, 'status', '', $actor);
- } elseif ($job['status'] === 'Shipped') {
- apply_job_change($job, 'status', 'Finished', $actor);
- } else {
- http_response_code(400);
- echo 'Nothing to undo from current status';
- return;
- }
- echo 'Success';
- return;
- }
- if ($action !== '') {
- $allowed = [
- 'acknowledge' => ['ack', '', ['vendor']],
- 'mark_finished' => ['status', 'Finished', ['vendor']],
- 'mark_shipped' => ['status', 'Shipped', ['vendor']],
- 'mark_received' => ['status', 'Received', ['ICG']],
- ];
- if (!isset($allowed[$action])) {
- http_response_code(400);
- echo 'Unknown action';
- return;
- }
- [$col, $new, $roles] = $allowed[$action];
- $role = $actor === 'ICG' ? 'ICG' : 'vendor';
- if (!in_array($role, $roles, true)) {
- http_response_code(403);
- echo 'Action not allowed for this role';
- return;
- }
- apply_job_change($job, $col, $new, $actor);
- echo 'Success';
- return;
- }
- // --- Field edits (ICG only) ---
- if ($actor !== 'ICG') {
- http_response_code(403);
- echo 'Edits restricted to ICG';
- return;
- }
- $editable = ['job', 'material', 'description', 'qty', 'due_date'];
- if (!in_array($column, $editable, true)) {
- http_response_code(400);
- echo 'Unknown column';
- return;
- }
- $value = trim($value);
- if ($column === 'qty') {
- if ($value === '' || !is_numeric($value)) {
- http_response_code(400);
- echo 'Qty must be a number';
- return;
- }
- $value = (string) (int) $value;
- } elseif ($column === 'due_date') {
- $value = parse_due_date($value);
- }
- apply_job_change($job, $column, $value, $actor);
- // An ICG edit to a content field bumps an already-acknowledged row back to
- // 'changed' so the vendor sees it at the top of their list. We leave 'new'
- // alone — the row still needs acknowledgement, just for a different reason.
- if ($job['ack'] === '') {
- apply_job_change($job, 'ack', 'changed', $actor);
- }
- echo 'Success';
|