getById($request_id); if (!$pr || (int)$pr['status'] !== 2) { $answer['message'] = 'Purchase request not found or not in Approved status.'; exit(json_encode($answer)); } $pr_items = $pr['items']; if (empty($pr_items)) { $answer['message'] = 'Purchase request has no items.'; exit(json_encode($answer)); } if ((float)$pr['total_remaining'] <= 0.000001) { $answer['message'] = 'Purchase request is already fully converted.'; exit(json_encode($answer)); } // Index by item_id for validation $pr_by_id = []; foreach ($pr_items as $pi) { $pr_by_id[(int)$pi['item_id']] = $pi; } // Default to all remaining if (empty($convert_items)) { $convert_items = []; foreach ($pr_items as $pi) { $remaining = (float)$pi['remaining_qty']; if ($remaining > 0.000001) { $convert_items[] = ['item_id' => (int)$pi['item_id'], 'quantity' => $remaining]; } } } // Validate quantities and build PO items $po_items = []; $validated = []; foreach ($convert_items as $ci) { $item_id = (int)($ci['item_id'] ?? 0); $qty = (float)($ci['quantity'] ?? 0); if ($qty <= 0) continue; if (!isset($pr_by_id[$item_id])) { $answer['message'] = "Item #{$item_id} not found in this purchase request."; exit(json_encode($answer)); } $pi = $pr_by_id[$item_id]; $remaining = (float)$pi['remaining_qty']; if ($qty - $remaining > 0.000001) { $name = $pi['product_name'] ?: $pi['product_sku']; $answer['message'] = "Cannot convert {$qty} for \"{$name}\": only {$remaining} remaining."; exit(json_encode($answer)); } $unit_price = (float)$pi['unit_price']; $total_price = round($qty * $unit_price, 4); $tax_amount = round($total_price * (float)($pi['tax_amount'] / max((float)$pi['total_price'], 0.000001)), 4); $po_items[] = [ 'item_id' => $item_id - 1, 'product_sku' => $pi['product_sku'], 'product_name' => $pi['product_name'], 'quantity' => $qty, 'unit_price' => $unit_price, 'total_price' => $total_price, 'tax_amount' => $tax_amount, 'received_qty' => 0, 'stock_in_id' => 0, ]; $validated[] = ['item_id' => $item_id, 'quantity' => $qty]; } if (empty($po_items)) { $answer['message'] = 'No valid items to convert.'; exit(json_encode($answer)); } $po_data = [ 'source' => 'purchase_request', 'source_id' => $request_id, 'contact_id' => $contact_id, 'department_id' => (int)($pr['department_id'] ?? 0), 'po_date' => date('Y-m-d'), 'expected_date' => $pr['required_date'] ?: '', 'warehouse_id' => 0, 'items' => $po_items, 'discount' => $discount, 'shipping_fee' => $shipping_fee, 'notes' => $pr['notes'] ?? '', ]; try { $new_po_id = null; dbTransaction($pdo2, function($pdo) use ( $po_data, $company_id, $logging, $request_id, $validated, $prm, &$new_po_id ) { $po = new PurchaseOrderManager($pdo, $company_id); $new_po_id = $po->savePo($po_data, $logging); $prm2 = new PurchaseRequestManager($pdo, $company_id); $prm2->incrementConvertedQty($request_id, $validated); }); $answer['success'] = 1; $answer['message'] = 'Purchase order created.'; $answer['po_id'] = $new_po_id; } catch (PDOException $e) { $answer['message'] = 'Database error, please try again.'; http_response_code(500); } catch (Exception $e) { $answer['message'] = $e->getMessage(); http_response_code(400); } exit(json_encode($answer));