po process
This commit is contained in:
@@ -133,9 +133,50 @@
|
||||
if (page >= 1 && page <= totalPages) currentPage = page;
|
||||
}
|
||||
|
||||
let showApprovalModal = false;
|
||||
let approvalForm = {
|
||||
po_number: "",
|
||||
approval: "",
|
||||
approved_by: "",
|
||||
approved_date: "",
|
||||
reject_comment: ""
|
||||
};
|
||||
|
||||
let currentUserId = "";
|
||||
let currentUserFullName = "";
|
||||
|
||||
async function fetchCurrentUser() {
|
||||
const {
|
||||
data: { user }
|
||||
} = await supabase.auth.getUser();
|
||||
|
||||
if (user) {
|
||||
currentUserId = user.id;
|
||||
|
||||
const { data, error } = await supabase
|
||||
.from("vb_users")
|
||||
.select("full_name")
|
||||
.eq("id", user.id)
|
||||
.single();
|
||||
|
||||
if (!error && data) {
|
||||
currentUserFullName = data.full_name;
|
||||
}
|
||||
}
|
||||
}
|
||||
function openApprovalModal(row) {
|
||||
selectedPO = row;
|
||||
|
||||
approvalForm = {
|
||||
po_number: row.purchase_order_number || "",
|
||||
approval: row.approval ? "approve" : "reject",
|
||||
approved_by: currentUserId,
|
||||
approved_date: new Date().toISOString().split("T")[0],
|
||||
reject_comment: row.reject_comment || ""
|
||||
};
|
||||
|
||||
showApprovalModal = true;
|
||||
}
|
||||
let showPaymentModal = false;
|
||||
let paymentForm = {
|
||||
payment_method: "",
|
||||
@@ -155,6 +196,27 @@
|
||||
due_remaining: 0
|
||||
};
|
||||
|
||||
let showAcknowledgedModal = false;
|
||||
|
||||
let acknowledgedForm = {
|
||||
po_number: "",
|
||||
acknowledged: "",
|
||||
acknowledged_by: "",
|
||||
acknowledged_date: ""
|
||||
};
|
||||
|
||||
function openAcknowledgedModal(row) {
|
||||
selectedPO = row;
|
||||
|
||||
acknowledgedForm = {
|
||||
po_number: row.purchase_order_number || "",
|
||||
acknowledged: row.acknowledged ? "acknowledged" : "reject",
|
||||
acknowledged_by: currentUserId,
|
||||
acknowledged_date: new Date().toISOString().split("T")[0]
|
||||
};
|
||||
|
||||
showAcknowledgedModal = true;
|
||||
}
|
||||
|
||||
let showPreparedModal = false;
|
||||
let selectedPO = null;
|
||||
@@ -181,7 +243,81 @@
|
||||
total_approved_order_amount: 0
|
||||
};
|
||||
|
||||
let showReceivedModal = false;
|
||||
let receivedForm = {
|
||||
po_number: "",
|
||||
received: "",
|
||||
received_by: "",
|
||||
received_date: ""
|
||||
};
|
||||
function openReceivedModal(row) {
|
||||
selectedPO = row;
|
||||
|
||||
receivedForm = {
|
||||
po_number: row.purchase_order_number || "",
|
||||
received: row.received ? "received" : "reject",
|
||||
received_by: currentUserId,
|
||||
received_date: new Date().toISOString().split("T")[0]
|
||||
};
|
||||
|
||||
showReceivedModal = true;
|
||||
}
|
||||
|
||||
let showCompletedModal = false;
|
||||
|
||||
let completedForm = {
|
||||
po_number: "",
|
||||
completed: "",
|
||||
completed_by: "",
|
||||
completed_date: ""
|
||||
};
|
||||
|
||||
function openCompletedModal(row) {
|
||||
selectedPO = row;
|
||||
|
||||
completedForm = {
|
||||
po_number: row.purchase_order_number || "",
|
||||
completed: row.completed ? "completed" : "reject",
|
||||
completed_by: currentUserId,
|
||||
completed_date: new Date().toISOString().split("T")[0]
|
||||
};
|
||||
|
||||
showCompletedModal = true;
|
||||
}
|
||||
async function saveCompleted() {
|
||||
const { error } = await supabase
|
||||
.from("vb_purchase_orders")
|
||||
.update({
|
||||
completed: completedForm.completed === "completed",
|
||||
completed_by: completedForm.completed === "completed" ? currentUserId : null,
|
||||
completed_date: completedForm.completed_date
|
||||
})
|
||||
.eq("id", selectedPO.id);
|
||||
|
||||
if (error) {
|
||||
console.error("Error saving completed:", error);
|
||||
alert("Failed to save.");
|
||||
return;
|
||||
}
|
||||
// ✅ Fire the webhook after saving:
|
||||
try {
|
||||
await fetch("https://flow.catalis.app/webhook-test/vb_need_complete_new", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
po_id: selectedPO.id,
|
||||
completed: completedForm.completed === "completed",
|
||||
completed_by: completedForm.completed === "completed" ? currentUserId : null,
|
||||
completed_date: completedForm.completed_date
|
||||
})
|
||||
});
|
||||
} catch (webhookError) {
|
||||
console.error("Webhook failed:", webhookError);
|
||||
alert("Saved, but webhook failed.");
|
||||
}
|
||||
showCompletedModal = false;
|
||||
await fetchPurchaseOrder();
|
||||
}
|
||||
async function openPreparedModal(row) {
|
||||
selectedPO = row;
|
||||
|
||||
@@ -329,6 +465,7 @@
|
||||
onMount(() => {
|
||||
fetchPurchaseOrder();
|
||||
fetchVendors();
|
||||
fetchCurrentUser();
|
||||
});
|
||||
|
||||
$: currentPage = 1; // Reset to first page when allRows changes
|
||||
@@ -567,6 +704,40 @@
|
||||
}
|
||||
return true;
|
||||
}
|
||||
async function saveReceived() {
|
||||
const { error } = await supabase
|
||||
.from("vb_purchase_orders")
|
||||
.update({
|
||||
received: receivedForm.received === "received",
|
||||
received_by: receivedForm.received === "received" ? currentUserId : null,
|
||||
received_date: receivedForm.received_date
|
||||
})
|
||||
.eq("id", selectedPO.id);
|
||||
|
||||
if (error) {
|
||||
console.error("Error saving received:", error);
|
||||
alert("Failed to save.");
|
||||
return;
|
||||
}
|
||||
// ✅ Fire the webhook after the DB update succeeds:
|
||||
try {
|
||||
await fetch("https://flow.catalis.app/webhook-test/vb_need_received_new", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
po_id: selectedPO.id,
|
||||
received: receivedForm.received === "received",
|
||||
received_by: receivedForm.received === "received" ? currentUserId : null,
|
||||
received_date: receivedForm.received_date
|
||||
})
|
||||
});
|
||||
} catch (webhookError) {
|
||||
console.error("Webhook failed:", webhookError);
|
||||
alert("Saved, but webhook failed.");
|
||||
}
|
||||
showReceivedModal = false;
|
||||
await fetchPurchaseOrder();
|
||||
}
|
||||
|
||||
function validateInputProsesToAprroval() {
|
||||
const requiredFields = ["po_type", "po_quantity", "po_price"];
|
||||
@@ -673,6 +844,43 @@
|
||||
await fetchPurchaseOrder();
|
||||
}
|
||||
|
||||
async function saveAcknowledged() {
|
||||
const { error } = await supabase
|
||||
.from("vb_purchase_orders")
|
||||
.update({
|
||||
acknowledged: acknowledgedForm.acknowledged === "acknowledged",
|
||||
acknowledge_by: acknowledgedForm.acknowledged === "acknowledged" ? currentUserId : null,
|
||||
acknowledged_date: acknowledgedForm.acknowledged_date
|
||||
})
|
||||
.eq("id", selectedPO.id);
|
||||
|
||||
if (error) {
|
||||
console.error("Error saving acknowledged:", error);
|
||||
alert("Failed to save.");
|
||||
return;
|
||||
}
|
||||
|
||||
// ✅ Fire the webhook after successful update:
|
||||
try {
|
||||
await fetch("https://flow.catalis.app/webhook/vb_acknowledged_new", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
po_id: selectedPO.id,
|
||||
acknowledged: acknowledgedForm.acknowledged === "acknowledged",
|
||||
acknowledged_by: acknowledgedForm.acknowledged === "acknowledged" ? currentUserId : null,
|
||||
acknowledged_date: acknowledgedForm.acknowledged_date
|
||||
})
|
||||
});
|
||||
} catch (webhookError) {
|
||||
console.error("Failed to fire webhook:", webhookError);
|
||||
alert("Saved, but webhook failed.");
|
||||
}
|
||||
|
||||
showAcknowledgedModal = false;
|
||||
await fetchPurchaseOrder();
|
||||
}
|
||||
|
||||
async function receivedOk(id: string, status: boolean) {
|
||||
const sessionId = await getSessionAuthId();
|
||||
if (!sessionId) {
|
||||
@@ -838,7 +1046,27 @@
|
||||
showPaymentModal = false;
|
||||
await fetchPurchaseOrder();
|
||||
}
|
||||
async function saveApproval() {
|
||||
const { error } = await supabase
|
||||
.from("vb_purchase_orders")
|
||||
.update({
|
||||
approved: approvalForm.approval === "approve",
|
||||
approved_by: approvalForm.approval === "approve" ? currentUserId : null,
|
||||
approved_date: approvalForm.approved_date,
|
||||
reject_comment: approvalForm.reject_comment || null,
|
||||
po_status: "approved"
|
||||
})
|
||||
.eq("id", selectedPO.id);
|
||||
|
||||
if (error) {
|
||||
console.error("Error saving approval:", error);
|
||||
alert("Failed to save.");
|
||||
return;
|
||||
}
|
||||
|
||||
showApprovalModal = false;
|
||||
await fetchPurchaseOrder();
|
||||
}
|
||||
</script>
|
||||
|
||||
<div>
|
||||
@@ -932,10 +1160,94 @@
|
||||
{row.prepared === true ? "Prepared" : "Set Prepared"}
|
||||
</button>
|
||||
</td>
|
||||
{:else if col.key === "approved" || col.key === "acknowledged" || col.key === "completed" || col.key === "received"}
|
||||
{:else if col.key === "approved"}
|
||||
<td class="px-4 py-2 text-center">
|
||||
<input type="checkbox" checked={row[col.key]} disabled />
|
||||
<button
|
||||
class="inline-flex items-center gap-1 rounded bg-yellow-600 px-3 py-1.5 text-white text-xs font-medium
|
||||
hover:bg-yellow-700 disabled:bg-gray-400 disabled:cursor-not-allowed"
|
||||
on:click={() => openApprovalModal(row)}
|
||||
disabled={
|
||||
row.approved === true ||
|
||||
row.approved === false ||
|
||||
row.po_status !== 'prepared'
|
||||
}
|
||||
>
|
||||
{#if row.approved === true}
|
||||
Approved
|
||||
{:else if row.approved === false}
|
||||
Rejected
|
||||
{:else if row.po_status !== 'prepared'}
|
||||
Not Prepared
|
||||
{:else}
|
||||
Approval
|
||||
{/if}
|
||||
</button>
|
||||
</td>
|
||||
{:else if col.key === "acknowledged"}
|
||||
<td class="px-4 py-2 text-center">
|
||||
<button
|
||||
class="inline-flex items-center gap-1 rounded bg-green-600 px-3 py-1.5 text-white text-xs font-medium
|
||||
hover:bg-green-700 disabled:bg-gray-400 disabled:cursor-not-allowed"
|
||||
on:click={() => openAcknowledgedModal(row)}
|
||||
disabled={
|
||||
row.approved !== true || row.acknowledged === true || row.acknowledged === false
|
||||
}
|
||||
>
|
||||
{#if row.acknowledged === true}
|
||||
Acknowledged
|
||||
{:else if row.acknowledged === false}
|
||||
Rejected
|
||||
{:else if row.approved !== true}
|
||||
Pending
|
||||
{:else}
|
||||
Acknowledge
|
||||
{/if}
|
||||
</button>
|
||||
</td>
|
||||
{:else if col.key === "completed"}
|
||||
<td class="px-4 py-2 text-center">
|
||||
<button
|
||||
class="inline-flex items-center gap-1 rounded bg-purple-600 px-3 py-1.5 text-white text-xs font-medium
|
||||
hover:bg-purple-700 disabled:bg-gray-400 disabled:cursor-not-allowed"
|
||||
on:click={() => openCompletedModal(row)}
|
||||
disabled={
|
||||
row.acknowledged !== true || row.completed === true || row.completed === false
|
||||
}
|
||||
>
|
||||
{#if row.completed === true}
|
||||
Completed
|
||||
{:else if row.completed === false}
|
||||
Rejected
|
||||
{:else if row.acknowledged !== true}
|
||||
Pending
|
||||
{:else}
|
||||
Complete
|
||||
{/if}
|
||||
</button>
|
||||
</td>
|
||||
|
||||
{:else if col.key === "received"}
|
||||
<td class="px-4 py-2 text-center">
|
||||
<button
|
||||
class="inline-flex items-center gap-1 rounded bg-green-600 px-3 py-1.5 text-white text-xs font-medium
|
||||
hover:bg-green-700 disabled:bg-gray-400 disabled:cursor-not-allowed"
|
||||
on:click={() => openReceivedModal(row)}
|
||||
disabled={
|
||||
row.completed !== true || row.received === true || row.received === false
|
||||
}
|
||||
>
|
||||
{#if row.received === true}
|
||||
Received
|
||||
{:else if row.received === false}
|
||||
Rejected
|
||||
{:else if row.completed !== true}
|
||||
Pending
|
||||
{:else}
|
||||
Receive
|
||||
{/if}
|
||||
</button>
|
||||
</td>
|
||||
|
||||
{:else if col.key === "payment"}
|
||||
<td class="px-4 py-2 text-center">
|
||||
<button
|
||||
@@ -1371,3 +1683,160 @@
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{#if showApprovalModal}
|
||||
<div class="fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50 overflow-y-auto">
|
||||
<div class="min-h-screen flex items-center justify-center p-4">
|
||||
<div class="bg-white rounded-lg shadow-lg w-full max-w-md max-h-[90vh] overflow-y-auto p-6 space-y-4">
|
||||
<h2 class="text-xl font-bold">Approve Purchase Order</h2>
|
||||
|
||||
<!-- PO Number -->
|
||||
<label>PO Number</label>
|
||||
<input
|
||||
type="text"
|
||||
value={approvalForm.po_number}
|
||||
disabled
|
||||
class="w-full border p-2 bg-gray-100"
|
||||
/>
|
||||
|
||||
<!-- Approval -->
|
||||
<label>Approval</label>
|
||||
<select bind:value={approvalForm.approval} class="w-full border p-2">
|
||||
<option value="" disabled>Select Approval</option>
|
||||
<option value="approve">Approve</option>
|
||||
<option value="reject">Reject</option>
|
||||
</select>
|
||||
{#if approvalForm.approval === 'reject'}
|
||||
<label>Reject Comment</label>
|
||||
<textarea
|
||||
bind:value={approvalForm.reject_comment}
|
||||
class="w-full border p-2"
|
||||
rows="3"
|
||||
placeholder="Enter reason for rejection..."
|
||||
></textarea>
|
||||
{/if}
|
||||
|
||||
<!-- Hidden: approved_by -->
|
||||
<input type="hidden" value={approvalForm.approved_by} />
|
||||
|
||||
<!-- Hidden: approved_date -->
|
||||
<input type="hidden" value={approvalForm.approved_date} />
|
||||
|
||||
<!-- Actions -->
|
||||
<div class="flex justify-end space-x-2 pt-4">
|
||||
<button on:click={saveApproval} class="bg-blue-600 text-white px-4 py-2 rounded">Save</button>
|
||||
<button on:click={() => showApprovalModal = false} class="px-4 py-2 rounded border">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if showAcknowledgedModal}
|
||||
<div class="fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50 overflow-y-auto">
|
||||
<div class="min-h-screen flex items-center justify-center p-4">
|
||||
<div class="bg-white rounded-lg shadow-lg w-full max-w-md max-h-[90vh] overflow-y-auto p-6 space-y-4">
|
||||
<h2 class="text-xl font-bold">Acknowledge Purchase Order</h2>
|
||||
|
||||
<!-- PO Number -->
|
||||
<label>PO Number</label>
|
||||
<input
|
||||
type="text"
|
||||
value={acknowledgedForm.po_number}
|
||||
disabled
|
||||
class="w-full border p-2 bg-gray-100"
|
||||
/>
|
||||
|
||||
<!-- Acknowledged -->
|
||||
<label>Acknowledged</label>
|
||||
<select bind:value={acknowledgedForm.acknowledged} class="w-full border p-2">
|
||||
<option value="" disabled>Select Acknowledgement</option>
|
||||
<option value="acknowledged">Acknowledged</option>
|
||||
<option value="reject">Reject</option>
|
||||
</select>
|
||||
|
||||
<!-- Hidden fields -->
|
||||
<input type="hidden" value={acknowledgedForm.acknowledged_by} />
|
||||
<input type="hidden" value={acknowledgedForm.acknowledged_date} />
|
||||
|
||||
<!-- Actions -->
|
||||
<div class="flex justify-end space-x-2 pt-4">
|
||||
<button on:click={saveAcknowledged} class="bg-blue-600 text-white px-4 py-2 rounded">Save</button>
|
||||
<button on:click={() => showAcknowledgedModal = false} class="px-4 py-2 rounded border">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if showCompletedModal}
|
||||
<div class="fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50 overflow-y-auto">
|
||||
<div class="min-h-screen flex items-center justify-center p-4">
|
||||
<div class="bg-white rounded-lg shadow-lg w-full max-w-md max-h-[90vh] overflow-y-auto p-6 space-y-4">
|
||||
<h2 class="text-xl font-bold">Complete Purchase Order</h2>
|
||||
|
||||
<!-- PO Number -->
|
||||
<label>PO Number</label>
|
||||
<input
|
||||
type="text"
|
||||
value={completedForm.po_number}
|
||||
disabled
|
||||
class="w-full border p-2 bg-gray-100"
|
||||
/>
|
||||
|
||||
<!-- Completed -->
|
||||
<label>Completion</label>
|
||||
<select bind:value={completedForm.completed} class="w-full border p-2">
|
||||
<option value="" disabled>Select Status</option>
|
||||
<option value="completed">Completed</option>
|
||||
<option value="reject">Reject</option>
|
||||
</select>
|
||||
|
||||
<!-- Hidden -->
|
||||
<input type="hidden" value={completedForm.completed_by} />
|
||||
<input type="hidden" value={completedForm.completed_date} />
|
||||
|
||||
<!-- Actions -->
|
||||
<div class="flex justify-end space-x-2 pt-4">
|
||||
<button on:click={saveCompleted} class="bg-blue-600 text-white px-4 py-2 rounded">Save</button>
|
||||
<button on:click={() => showCompletedModal = false} class="px-4 py-2 rounded border">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{#if showReceivedModal}
|
||||
<div class="fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50 overflow-y-auto">
|
||||
<div class="min-h-screen flex items-center justify-center p-4">
|
||||
<div class="bg-white rounded-lg shadow-lg w-full max-w-md max-h-[90vh] overflow-y-auto p-6 space-y-4">
|
||||
<h2 class="text-xl font-bold">Receive Purchase Order</h2>
|
||||
|
||||
<!-- PO Number -->
|
||||
<label>PO Number</label>
|
||||
<input
|
||||
type="text"
|
||||
value={receivedForm.po_number}
|
||||
disabled
|
||||
class="w-full border p-2 bg-gray-100"
|
||||
/>
|
||||
|
||||
<!-- Received -->
|
||||
<label>Received</label>
|
||||
<select bind:value={receivedForm.received} class="w-full border p-2">
|
||||
<option value="" disabled>Select Status</option>
|
||||
<option value="received">Received</option>
|
||||
<option value="reject">Reject</option>
|
||||
</select>
|
||||
|
||||
<!-- Hidden -->
|
||||
<input type="hidden" value={receivedForm.received_by} />
|
||||
<input type="hidden" value={receivedForm.received_date} />
|
||||
|
||||
<!-- Actions -->
|
||||
<div class="flex justify-end space-x-2 pt-4">
|
||||
<button on:click={saveReceived} class="bg-blue-600 text-white px-4 py-2 rounded">Save</button>
|
||||
<button on:click={() => showReceivedModal = false} class="px-4 py-2 rounded border">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
Reference in New Issue
Block a user