accounting workflows
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
<?php
|
||||
session_start();
|
||||
require '../../../assets/utils/db_auth.php';
|
||||
require '../../../assets/utils/classes/PurchaseOrderManager.php';
|
||||
require '../../../assets/utils/classes/PurchaseRequestManager.php';
|
||||
require_role($user_role, ['owner', 'admin', 'staff']);
|
||||
|
||||
$request_id = (int)($data['request_id'] ?? 0);
|
||||
$contact_id = (int)($data['contact_id'] ?? 0);
|
||||
$convert_items = $data['convert_items'] ?? [];
|
||||
$discount = (float)($data['discount'] ?? 0);
|
||||
$shipping_fee = (float)($data['shipping_fee'] ?? 0);
|
||||
|
||||
if (!$request_id) {
|
||||
exit(json_encode(['success' => 0, 'message' => 'Purchase request ID is required.']));
|
||||
}
|
||||
if (!$contact_id) {
|
||||
exit(json_encode(['success' => 0, 'message' => 'Supplier (contact_id) is required for the PO.']));
|
||||
}
|
||||
|
||||
$prm = new PurchaseRequestManager($pdo2, $company_id);
|
||||
|
||||
// Load PR — must be Approved
|
||||
$pr = $prm->getById($request_id);
|
||||
if (!$pr || (int)$pr['status'] !== 2) {
|
||||
exit(json_encode(['success' => 0, 'message' => 'Purchase request not found or not in Approved status.']));
|
||||
}
|
||||
|
||||
$pr_items = $pr['items'];
|
||||
if (empty($pr_items)) {
|
||||
exit(json_encode(['success' => 0, 'message' => 'Purchase request has no items.']));
|
||||
}
|
||||
|
||||
if ((float)$pr['total_remaining'] <= 0.000001) {
|
||||
exit(json_encode(['success' => 0, 'message' => 'Purchase request is already fully converted.']));
|
||||
}
|
||||
|
||||
// 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])) {
|
||||
exit(json_encode(['success' => 0, 'message' => "Item #{$item_id} not found in this purchase request."]));
|
||||
}
|
||||
|
||||
$pi = $pr_by_id[$item_id];
|
||||
$remaining = (float)$pi['remaining_qty'];
|
||||
|
||||
if ($qty - $remaining > 0.000001) {
|
||||
$name = $pi['product_name'] ?: $pi['product_sku'];
|
||||
exit(json_encode([
|
||||
'success' => 0,
|
||||
'message' => "Cannot convert {$qty} for \"{$name}\": only {$remaining} remaining.",
|
||||
]));
|
||||
}
|
||||
|
||||
$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)) {
|
||||
exit(json_encode(['success' => 0, 'message' => 'No valid items to convert.']));
|
||||
}
|
||||
|
||||
$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));
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
session_start();
|
||||
require '../../../assets/utils/db_auth.php';
|
||||
require '../../../assets/utils/classes/PurchaseRequestManager.php';
|
||||
require_role($user_role, ['owner', 'admin', 'staff']);
|
||||
|
||||
$action = $data['action'] ?? '';
|
||||
$id = (int)($data['id'] ?? 0);
|
||||
$items = json_decode($data['items'] ?? '[]', true) ?: [];
|
||||
|
||||
$prm = new PurchaseRequestManager($pdo2, $company_id);
|
||||
|
||||
try {
|
||||
if ($action === 'create') {
|
||||
$new_id = $prm->save(array_merge($data, ['id' => 0, 'items' => $items]), $logging);
|
||||
$answer['success'] = 1;
|
||||
$answer['message'] = 'Purchase request created.';
|
||||
$answer['new_id'] = $new_id;
|
||||
} elseif ($action === 'update') {
|
||||
$prm->save(array_merge($data, ['id' => $id, 'items' => $items]), $logging);
|
||||
$answer['success'] = 1;
|
||||
$answer['message'] = 'Purchase request updated.';
|
||||
} else {
|
||||
throw new Exception('Unknown action.');
|
||||
}
|
||||
} 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));
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
session_start();
|
||||
require '../../../assets/utils/db_auth.php';
|
||||
require_role($user_role, ['owner', 'admin', 'staff']);
|
||||
require '../../../assets/utils/classes/InvoiceManager.php';
|
||||
|
||||
try {
|
||||
$new_id = null;
|
||||
|
||||
dbTransaction($pdo2, function($pdo) use ($data, $company_id, $logging, &$new_id) {
|
||||
$inv = new InvoiceManager($pdo, $company_id);
|
||||
$new_id = $inv->createManualDebitNote($data, $logging);
|
||||
});
|
||||
|
||||
$answer['success'] = 1;
|
||||
$answer['new_id'] = $new_id;
|
||||
$answer['message'] = 'Supplier credit note created.';
|
||||
|
||||
} 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));
|
||||
?>
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
session_start();
|
||||
require '../../../assets/utils/db_auth.php';
|
||||
require '../../../assets/utils/classes/PurchaseRequestManager.php';
|
||||
|
||||
$id = (int)($data['id'] ?? 0);
|
||||
$prm = new PurchaseRequestManager($pdo2, $company_id);
|
||||
|
||||
if ($id > 0) {
|
||||
$row = $prm->getById($id);
|
||||
if (!$row) {
|
||||
http_response_code(404);
|
||||
exit(json_encode(['success' => 0, 'message' => 'Purchase request not found.']));
|
||||
}
|
||||
$answer['output'] = $row;
|
||||
} else {
|
||||
$answer['output'] = $prm->getList();
|
||||
}
|
||||
|
||||
$answer['success'] = 1;
|
||||
exit(json_encode($answer));
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
session_start();
|
||||
require '../../../assets/utils/db_auth.php';
|
||||
require '../../../assets/utils/classes/PurchaseRequestManager.php';
|
||||
require_role($user_role, ['owner', 'admin', 'staff']);
|
||||
|
||||
$id = (int)($data['id'] ?? 0);
|
||||
$action = $data['action_type'] ?? '';
|
||||
|
||||
if (!$id || !$action) {
|
||||
exit(json_encode(['success' => 0, 'message' => 'ID and action are required.']));
|
||||
}
|
||||
|
||||
$prm = new PurchaseRequestManager($pdo2, $company_id);
|
||||
|
||||
try {
|
||||
$prm->updateStatus($id, $action, $logging);
|
||||
$answer['success'] = 1;
|
||||
$answer['message'] = 'Status updated.';
|
||||
} 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));
|
||||
Reference in New Issue
Block a user