Files
wms-app/app/revenue/api/engine/convert_quotation.php
T

140 lines
4.1 KiB
PHP

<?php
session_start();
require_once '../../../assets/utils/db_auth.php';
require_once '../../../assets/utils/classes/OrderManager.php';
require_once '../../../assets/utils/classes/QuotationManager.php';
require_role($user_role, ['owner', 'admin', 'staff']);
$quotation_id = (int)($data['quotation_id'] ?? 0);
$convert_items = $data['convert_items'] ?? [];
if (!$quotation_id) {
$answer['message'] = 'Quotation ID required.';
exit(json_encode($answer));
}
$qm = new QuotationManager($pdo2, $company_id);
// Load quotation — must be Accepted
$q = $qm->getById($quotation_id);
if (!$q || (int)$q['status'] !== 2) {
$answer['message'] = 'Quotation not found or not in Accepted status.';
exit(json_encode($answer));
}
$qt_items = $q['items'];
if (empty($qt_items)) {
$answer['message'] = 'Quotation has no items.';
exit(json_encode($answer));
}
if ((float)$q['total_remaining'] <= 0.000001) {
$answer['message'] = 'Quotation is already fully converted.';
exit(json_encode($answer));
}
// Index by item_id for validation
$qt_by_id = [];
foreach ($qt_items as $qi) {
$qt_by_id[(int)$qi['item_id']] = $qi;
}
// Default to all remaining when caller sends no selection
if (empty($convert_items)) {
$convert_items = [];
foreach ($qt_items as $qi) {
$remaining = (float)$qi['remaining_qty'];
if ($remaining > 0.000001) {
$convert_items[] = ['item_id' => (int)$qi['item_id'], 'quantity' => $remaining];
}
}
}
// Validate quantities and build order items
$ord_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($qt_by_id[$item_id])) {
$answer['message'] = "Item #{$item_id} not found in this quotation.";
exit(json_encode($answer));
}
$qi = $qt_by_id[$item_id];
$remaining = (float)$qi['remaining_qty'];
if ($qty - $remaining > 0.000001) {
$name = $qi['product_name'] ?: $qi['product_sku'];
$answer['message'] = "Cannot convert {$qty} for \"{$name}\": only {$remaining} remaining.";
exit(json_encode($answer));
}
$unit_price = (float)$qi['unit_price'];
$total_price = round($qty * $unit_price, 4);
$tax_amount = round($total_price * (float)($qi['tax_amount'] / max((float)$qi['total_price'], 0.000001)), 4);
$ord_items[] = [
'item_id' => $item_id - 1,
'product_sku' => $qi['product_sku'],
'product_name' => $qi['product_name'],
'warehouse_id' => 0,
'lot_number' => '',
'quantity' => $qty,
'unit_price' => $unit_price,
'total_price' => $total_price,
'tax_amount' => $tax_amount,
'stock_out_id' => 0,
];
$validated[] = ['item_id' => $item_id, 'quantity' => $qty];
}
if (empty($ord_items)) {
$answer['message'] = 'No valid items to convert.';
exit(json_encode($answer));
}
$order_data = [
'source' => 'quotation',
'source_id' => $quotation_id,
'contact_id' => (int)$q['contact_id'],
'department_id'=> (int)($q['department_id'] ?? 0),
'order_date' => date('Y-m-d'),
'items' => $ord_items,
'discount' => 0,
'shipping_fee' => 0,
'shipping_tracking_number' => '',
'notes' => $q['notes'] ?? '',
];
try {
$new_order_id = null;
dbTransaction($pdo2, function($pdo) use (
$order_data, $company_id, $logging, $quotation_id, $validated, $qm, &$new_order_id
) {
$om = new OrderManager($pdo, $company_id);
$new_order_id = $om->saveOrder($order_data, $logging);
$qm2 = new QuotationManager($pdo, $company_id);
$qm2->incrementConvertedQty($quotation_id, $validated);
});
$answer['success'] = 1;
$answer['message'] = 'Order created successfully.';
$answer['order_id'] = $new_order_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));