penambahan menu approval per po per proses
This commit is contained in:
@@ -504,6 +504,21 @@
|
|||||||
};
|
};
|
||||||
currentEditingId = row.id;
|
currentEditingId = row.id;
|
||||||
await addToPo(project);
|
await addToPo(project);
|
||||||
|
} else {
|
||||||
|
// uncheck
|
||||||
|
const { data, error } =
|
||||||
|
await supabase
|
||||||
|
.from("projects")
|
||||||
|
.update({
|
||||||
|
add_to_po: false,
|
||||||
|
})
|
||||||
|
.eq("id", row.id);
|
||||||
|
if (error) {
|
||||||
|
console.error(
|
||||||
|
"Error updating project:",
|
||||||
|
error,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -8,12 +8,8 @@
|
|||||||
prepared_date: string;
|
prepared_date: string;
|
||||||
po_type: string;
|
po_type: string;
|
||||||
po_quantity: number;
|
po_quantity: number;
|
||||||
po_status: string;
|
po_price: number;
|
||||||
approved_vendor: string;
|
po_total_price: number;
|
||||||
acknowledge_by: string;
|
|
||||||
approved_by: string;
|
|
||||||
approved_price: number;
|
|
||||||
completed_status: string;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let purchaseOrderInsert: PurchaseOrderInsert = {
|
let purchaseOrderInsert: PurchaseOrderInsert = {
|
||||||
@@ -21,12 +17,8 @@
|
|||||||
prepared_date: "",
|
prepared_date: "",
|
||||||
po_type: "",
|
po_type: "",
|
||||||
po_quantity: 0,
|
po_quantity: 0,
|
||||||
po_status: "REQUESTED",
|
po_price: 0,
|
||||||
approved_vendor: "",
|
po_total_price: 0,
|
||||||
acknowledge_by: "",
|
|
||||||
approved_by: "",
|
|
||||||
approved_price: 0,
|
|
||||||
completed_status: "",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
type PurchaseOrders = {
|
type PurchaseOrders = {
|
||||||
@@ -37,6 +29,7 @@
|
|||||||
po_quantity: number;
|
po_quantity: number;
|
||||||
po_status: string;
|
po_status: string;
|
||||||
approved_vendor: string;
|
approved_vendor: string;
|
||||||
|
proses_to_approval: boolean;
|
||||||
acknowledged: boolean;
|
acknowledged: boolean;
|
||||||
approved_vendor_id: string;
|
approved_vendor_id: string;
|
||||||
acknowledge_by: string;
|
acknowledge_by: string;
|
||||||
@@ -62,6 +55,8 @@
|
|||||||
prepared_date: string;
|
prepared_date: string;
|
||||||
po_type: string;
|
po_type: string;
|
||||||
po_quantity: number;
|
po_quantity: number;
|
||||||
|
po_price: number;
|
||||||
|
po_total_price: number;
|
||||||
po_status: string;
|
po_status: string;
|
||||||
approved_vendor: string;
|
approved_vendor: string;
|
||||||
acknowledged: boolean;
|
acknowledged: boolean;
|
||||||
@@ -70,6 +65,7 @@
|
|||||||
approved_price: number;
|
approved_price: number;
|
||||||
approved_quantity: number;
|
approved_quantity: number;
|
||||||
total_approved_order_amount: number;
|
total_approved_order_amount: number;
|
||||||
|
proses_to_approval: boolean;
|
||||||
approval: string;
|
approval: string;
|
||||||
completed_status: string;
|
completed_status: string;
|
||||||
received: boolean;
|
received: boolean;
|
||||||
@@ -91,7 +87,10 @@
|
|||||||
{ key: "prepared_date", title: "Prepared Date" },
|
{ key: "prepared_date", title: "Prepared Date" },
|
||||||
{ key: "po_type", title: "PO Type" },
|
{ key: "po_type", title: "PO Type" },
|
||||||
{ key: "po_quantity", title: "PO Quantity" },
|
{ key: "po_quantity", title: "PO Quantity" },
|
||||||
|
{ key: "po_price", title: "PO Price" },
|
||||||
|
{ key: "po_total_price", title: "PO Total Price" },
|
||||||
{ key: "po_status", title: "PO Status" },
|
{ key: "po_status", title: "PO Status" },
|
||||||
|
{ key: "proses_to_approval", title: "PROSES TO APPROVAL" },
|
||||||
{ key: "approved_vendor", title: "Approved Vendor" },
|
{ key: "approved_vendor", title: "Approved Vendor" },
|
||||||
{ key: "acknowledged", title: "Acknowledged" },
|
{ key: "acknowledged", title: "Acknowledged" },
|
||||||
{ key: "acknowledge_by", title: "Acknowledged By" },
|
{ key: "acknowledge_by", title: "Acknowledged By" },
|
||||||
@@ -132,9 +131,7 @@
|
|||||||
) {
|
) {
|
||||||
let query = supabase
|
let query = supabase
|
||||||
.from("purchaseorder_data")
|
.from("purchaseorder_data")
|
||||||
.select(
|
.select("*")
|
||||||
"id, purchase_order_number, villa_data, issue_id, prepared_date, po_type, po_quantity, po_status, approved_vendor, acknowledged, acknowledge_by, approved_price, approved_quantity, total_approved_order_amount, approval, completed_status, received, received_by, input_by, approved_by, created_at",
|
|
||||||
)
|
|
||||||
.order(sort || "created_at", { ascending: order === "asc" })
|
.order(sort || "created_at", { ascending: order === "asc" })
|
||||||
.range(offset, offset + limit - 1);
|
.range(offset, offset + limit - 1);
|
||||||
if (filter) {
|
if (filter) {
|
||||||
@@ -172,7 +169,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// masukkan villa name dan issue name ke dalam data
|
// masukkan villa name dan issue name ke dalam data
|
||||||
allRows = data.map((row) => {
|
allRows = data.map((row: any) => {
|
||||||
const issue = issues.find((issue) => issue.id === row.issue_id);
|
const issue = issues.find((issue) => issue.id === row.issue_id);
|
||||||
const villa = villas.find((villa) => villa.id === issue.villa_id);
|
const villa = villas.find((villa) => villa.id === issue.villa_id);
|
||||||
const vendor = vendors.find(
|
const vendor = vendors.find(
|
||||||
@@ -189,6 +186,9 @@
|
|||||||
: "Unknown Approved Vendor",
|
: "Unknown Approved Vendor",
|
||||||
approval: row.approval || "",
|
approval: row.approval || "",
|
||||||
completed_status: row.completed_status || "",
|
completed_status: row.completed_status || "",
|
||||||
|
proses_to_approval: row.proses_to_approval || false,
|
||||||
|
po_price: row.po_price || 0,
|
||||||
|
po_total_price: row.po_total_price || 0,
|
||||||
} as PurchaseOrderDisplay;
|
} as PurchaseOrderDisplay;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -255,11 +255,14 @@
|
|||||||
"completed_status",
|
"completed_status",
|
||||||
"received",
|
"received",
|
||||||
"received_by",
|
"received_by",
|
||||||
"approved_quantity",
|
"proses_to_approval",
|
||||||
"total_approved_order_amount",
|
|
||||||
"approved_by",
|
"approved_by",
|
||||||
"name",
|
"name",
|
||||||
"po_status",
|
"po_status",
|
||||||
|
"approved_quantity",
|
||||||
|
"total_approved_order_amount",
|
||||||
|
"approved_vendor",
|
||||||
|
"approved_price",
|
||||||
];
|
];
|
||||||
const formColumns = columns.filter(
|
const formColumns = columns.filter(
|
||||||
(col) => !excludedKeys.includes(col.key),
|
(col) => !excludedKeys.includes(col.key),
|
||||||
@@ -280,17 +283,18 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function saveProject() {
|
async function saveProject() {
|
||||||
|
if (!validateInput()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
purchaseOrderInsert = {
|
purchaseOrderInsert = {
|
||||||
issue_id: newPurchaseOrders.issue_id || "",
|
issue_id: newPurchaseOrders.issue_id || "",
|
||||||
prepared_date: newPurchaseOrders.prepared_date || "",
|
prepared_date: newPurchaseOrders.prepared_date || "",
|
||||||
po_type: newPurchaseOrders.po_type || "",
|
po_type: newPurchaseOrders.po_type || "",
|
||||||
po_quantity: newPurchaseOrders.po_quantity || 0,
|
po_quantity: newPurchaseOrders.po_quantity || 0,
|
||||||
po_status: newPurchaseOrders.po_status || "REQUESTED",
|
po_price: newPurchaseOrders.po_price || 0,
|
||||||
approved_vendor: newPurchaseOrders.approved_vendor || "",
|
po_total_price:
|
||||||
acknowledge_by: newPurchaseOrders.acknowledge_by || "",
|
newPurchaseOrders.po_quantity * newPurchaseOrders.po_price || 0,
|
||||||
approved_price: newPurchaseOrders.approved_price || "",
|
|
||||||
approved_by: newPurchaseOrders.approved_by || "",
|
|
||||||
completed_status: newPurchaseOrders.completed_status || "",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (isEditing && currentEditingId) {
|
if (isEditing && currentEditingId) {
|
||||||
@@ -339,12 +343,12 @@
|
|||||||
{ label: "Acknowledged", value: "ACKNOWLEDGE", color: "#60a5fa" },
|
{ label: "Acknowledged", value: "ACKNOWLEDGE", color: "#60a5fa" },
|
||||||
{
|
{
|
||||||
label: "Received - Incomplete",
|
label: "Received - Incomplete",
|
||||||
value: "RECEIVE - INCOMPLETE",
|
value: "RECEIVED INCOMPLETE",
|
||||||
color: "#fb923c",
|
color: "#fb923c",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Received - Completed",
|
label: "Received - Completed",
|
||||||
value: "RECEIVE COMPLETED",
|
value: "RECEIVED COMPLETED",
|
||||||
color: "#10b981",
|
color: "#10b981",
|
||||||
},
|
},
|
||||||
{ label: "Canceled", value: "CANCELED", color: "#f87171" },
|
{ label: "Canceled", value: "CANCELED", color: "#f87171" },
|
||||||
@@ -360,7 +364,7 @@
|
|||||||
"prepared_date",
|
"prepared_date",
|
||||||
"po_type",
|
"po_type",
|
||||||
"po_quantity",
|
"po_quantity",
|
||||||
"approved_vendor",
|
"po_price",
|
||||||
];
|
];
|
||||||
for (const field of requiredFields) {
|
for (const field of requiredFields) {
|
||||||
if (!newPurchaseOrders[field]) {
|
if (!newPurchaseOrders[field]) {
|
||||||
@@ -382,6 +386,38 @@
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function validateInputProsesToAprroval() {
|
||||||
|
const requiredFields = ["po_type", "po_quantity", "po_price"];
|
||||||
|
for (const field of requiredFields) {
|
||||||
|
if (!newPurchaseOrders[field]) {
|
||||||
|
alert(`Please fill in the ${field} field.`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateProsesToApproval(id: string, status: boolean) {
|
||||||
|
if (!validateInputProsesToAprroval()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data, error } = await supabase
|
||||||
|
.from("purchase_orders")
|
||||||
|
.update({ proses_to_approval: status, po_status: "REQUESTED" })
|
||||||
|
.eq("id", id);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
console.error(
|
||||||
|
"Error updating purchase order proses to approval:",
|
||||||
|
error,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await fetchPurchaseOrder();
|
||||||
|
}
|
||||||
|
|
||||||
async function updatePurchaseOrderStatus(
|
async function updatePurchaseOrderStatus(
|
||||||
e: Event,
|
e: Event,
|
||||||
id: string,
|
id: string,
|
||||||
@@ -600,6 +636,42 @@
|
|||||||
>
|
>
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
|
{:else if col.key === "proses_to_approval"}
|
||||||
|
<td class="px-4 py-2">
|
||||||
|
<!-- checkbox -->
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={row.proses_to_approval}
|
||||||
|
on:change={(e) => {
|
||||||
|
const isChecked = (
|
||||||
|
e.target as HTMLInputElement
|
||||||
|
).checked;
|
||||||
|
|
||||||
|
if (isChecked) {
|
||||||
|
newPurchaseOrders = {
|
||||||
|
...row,
|
||||||
|
proses_to_approval: true,
|
||||||
|
};
|
||||||
|
// map to project
|
||||||
|
updateProsesToApproval(
|
||||||
|
row.id,
|
||||||
|
isChecked,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
newPurchaseOrders = {
|
||||||
|
...row,
|
||||||
|
proses_to_approval: false,
|
||||||
|
};
|
||||||
|
// uncheck
|
||||||
|
updateProsesToApproval(
|
||||||
|
row.id,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
disabled={row.proses_to_approval}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
{:else if col.key === "acknowledged"}
|
{:else if col.key === "acknowledged"}
|
||||||
<td class="px-4 py-2 text-center">
|
<td class="px-4 py-2 text-center">
|
||||||
<input
|
<input
|
||||||
@@ -671,10 +743,10 @@
|
|||||||
<option value="" disabled selected
|
<option value="" disabled selected
|
||||||
>ON PROSES</option
|
>ON PROSES</option
|
||||||
>
|
>
|
||||||
<option value="APPROVED"
|
<option value="RECEIVED COMPLETE"
|
||||||
>RECEIVED COMPLETE</option
|
>RECEIVED COMPLETE</option
|
||||||
>
|
>
|
||||||
<option value="REJECTED"
|
<option value="RECEIVED INCOMPLETE"
|
||||||
>COMPLETE INCOMPLETE</option
|
>COMPLETE INCOMPLETE</option
|
||||||
>
|
>
|
||||||
</select>
|
</select>
|
||||||
@@ -694,27 +766,6 @@
|
|||||||
🗑️ Delete
|
🗑️ Delete
|
||||||
</button>
|
</button>
|
||||||
</td>
|
</td>
|
||||||
{:else if col.key === "move_issue"}
|
|
||||||
<td class="px-4 py-2">
|
|
||||||
<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"
|
|
||||||
on:click={() =>
|
|
||||||
alert(
|
|
||||||
`Move issue ${row.id} to project`,
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
➡️ PROJECT
|
|
||||||
</button>
|
|
||||||
<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"
|
|
||||||
on:click={() =>
|
|
||||||
alert(
|
|
||||||
`Move issue ${row.id} to another area`,
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
➡️ PURCHASE ORDER
|
|
||||||
</button>
|
|
||||||
</td>
|
|
||||||
{:else}
|
{:else}
|
||||||
<td class="px-4 py-2 text-gray-700"
|
<td class="px-4 py-2 text-gray-700"
|
||||||
>{row[
|
>{row[
|
||||||
@@ -795,6 +846,7 @@
|
|||||||
(e.target as HTMLSelectElement)?.value ?? "";
|
(e.target as HTMLSelectElement)?.value ?? "";
|
||||||
newPurchaseOrders.issue_id = selectedIssue;
|
newPurchaseOrders.issue_id = selectedIssue;
|
||||||
}}
|
}}
|
||||||
|
disabled
|
||||||
>
|
>
|
||||||
<option value="">Select Issue</option>
|
<option value="">Select Issue</option>
|
||||||
{#each issues as issue}
|
{#each issues as issue}
|
||||||
@@ -873,6 +925,23 @@
|
|||||||
class="w-full px-3 py-2 border border-gray-300 rounded focus:outline-none focus:ring focus:ring-blue-500"
|
class="w-full px-3 py-2 border border-gray-300 rounded focus:outline-none focus:ring focus:ring-blue-500"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
{:else if col.key === "po_price"}
|
||||||
|
<div class="mb-4">
|
||||||
|
<label
|
||||||
|
for={col.key}
|
||||||
|
class="block text-sm font-medium text-gray-700 mb-1"
|
||||||
|
>
|
||||||
|
{col.title}
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
name="po_price"
|
||||||
|
placeholder="Enter PO Price"
|
||||||
|
type="number"
|
||||||
|
id={col.key}
|
||||||
|
bind:value={newPurchaseOrders[col.key]}
|
||||||
|
class="w-full px-3 py-2 border border-gray-300 rounded focus:outline-none focus:ring focus:ring-blue-500"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
{:else if col.key === "po_quantity"}
|
{:else if col.key === "po_quantity"}
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<label
|
<label
|
||||||
@@ -882,12 +951,33 @@
|
|||||||
{col.title}
|
{col.title}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
|
name="po_quantity"
|
||||||
|
placeholder="Enter PO Quantity"
|
||||||
type="number"
|
type="number"
|
||||||
id={col.key}
|
id={col.key}
|
||||||
bind:value={newPurchaseOrders[col.key]}
|
bind:value={newPurchaseOrders[col.key]}
|
||||||
class="w-full px-3 py-2 border border-gray-300 rounded focus:outline-none focus:ring focus:ring-blue-500"
|
class="w-full px-3 py-2 border border-gray-300 rounded focus:outline-none focus:ring focus:ring-blue-500"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
{:else if col.key === "po_total_price"}
|
||||||
|
<div class="mb-4">
|
||||||
|
<label
|
||||||
|
for={col.key}
|
||||||
|
class="block text-sm font-medium text-gray-700 mb-1"
|
||||||
|
>
|
||||||
|
{col.title}
|
||||||
|
</label>
|
||||||
|
<!-- calculate po quantity * price -->
|
||||||
|
<input
|
||||||
|
name="po_total_price"
|
||||||
|
type="number"
|
||||||
|
id={col.key}
|
||||||
|
class="w-full px-3 py-2 border border-gray-300 rounded focus:outline-none focus:ring focus:ring-blue-500"
|
||||||
|
readonly
|
||||||
|
value={newPurchaseOrders.po_quantity *
|
||||||
|
newPurchaseOrders.po_price}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
{:else if col.key === "approved_price"}
|
{:else if col.key === "approved_price"}
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<label
|
<label
|
||||||
|
|||||||
@@ -98,7 +98,6 @@
|
|||||||
{ key: "acknowledged", title: "Acknowledged" },
|
{ key: "acknowledged", title: "Acknowledged" },
|
||||||
{ key: "acknowledge_by", title: "Acknowledge By" },
|
{ key: "acknowledge_by", title: "Acknowledge By" },
|
||||||
{ key: "created_at", title: "Created At" },
|
{ key: "created_at", title: "Created At" },
|
||||||
{ key: "actions", title: "Actions" }, // For edit/delete buttons
|
|
||||||
];
|
];
|
||||||
|
|
||||||
let currentPage = 1;
|
let currentPage = 1;
|
||||||
@@ -123,9 +122,8 @@
|
|||||||
) {
|
) {
|
||||||
let query = supabase
|
let query = supabase
|
||||||
.from("purchaseorder_data")
|
.from("purchaseorder_data")
|
||||||
.select(
|
.select("*")
|
||||||
"id, purchase_order_number, villa_data, issue_id, prepared_date, po_type, po_quantity, po_status, approved_vendor, acknowledged, acknowledge_by, approved_price, approved_quantity, total_approved_order_amount, approval, completed_status, received, received_by, input_by, approved_by, created_at",
|
.eq("po_status", "APPROVED")
|
||||||
)
|
|
||||||
.order(sort || "created_at", { ascending: order === "asc" })
|
.order(sort || "created_at", { ascending: order === "asc" })
|
||||||
.range(offset, offset + limit - 1);
|
.range(offset, offset + limit - 1);
|
||||||
if (filter) {
|
if (filter) {
|
||||||
@@ -409,7 +407,7 @@
|
|||||||
async function acknowledgedOk(id: string, status: boolean) {
|
async function acknowledgedOk(id: string, status: boolean) {
|
||||||
const { data, error } = await supabase
|
const { data, error } = await supabase
|
||||||
.from("purchase_orders")
|
.from("purchase_orders")
|
||||||
.update({ acknowledged: status })
|
.update({ acknowledged: status, po_status: "ACKNOWLEDGED" })
|
||||||
.eq("id", id);
|
.eq("id", id);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
@@ -660,21 +658,6 @@
|
|||||||
>
|
>
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
{:else if col.key === "actions"}
|
|
||||||
<td class="px-4 py-2">
|
|
||||||
<button
|
|
||||||
class="inline-flex items-center gap-1 rounded bg-blue-600 px-3 py-1.5 text-white text-xs font-medium hover:bg-blue-700"
|
|
||||||
on:click={() => openModal(row)}
|
|
||||||
>
|
|
||||||
✏️ Edit
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
class="inline-flex items-center gap-1 rounded bg-red-600 px-3 py-1.5 text-white text-xs font-medium hover:bg-red-700"
|
|
||||||
on:click={() => deleteProject(row.id)}
|
|
||||||
>
|
|
||||||
🗑️ Delete
|
|
||||||
</button>
|
|
||||||
</td>
|
|
||||||
{:else if col.key === "move_issue"}
|
{:else if col.key === "move_issue"}
|
||||||
<td class="px-4 py-2">
|
<td class="px-4 py-2">
|
||||||
<button
|
<button
|
||||||
|
|||||||
@@ -5,28 +5,20 @@
|
|||||||
|
|
||||||
type PurchaseOrderInsert = {
|
type PurchaseOrderInsert = {
|
||||||
issue_id: string;
|
issue_id: string;
|
||||||
prepared_date: string;
|
|
||||||
po_type: string;
|
|
||||||
po_quantity: number;
|
|
||||||
po_status: string;
|
|
||||||
approved_vendor: string;
|
approved_vendor: string;
|
||||||
acknowledge_by: string;
|
|
||||||
approved_by: string;
|
approved_by: string;
|
||||||
approved_price: number;
|
approved_price: number;
|
||||||
completed_status: string;
|
approved_quantity: number;
|
||||||
|
total_approved_order_amount?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
let purchaseOrderInsert: PurchaseOrderInsert = {
|
let purchaseOrderInsert: PurchaseOrderInsert = {
|
||||||
issue_id: "",
|
issue_id: "",
|
||||||
prepared_date: "",
|
|
||||||
po_type: "",
|
|
||||||
po_quantity: 0,
|
|
||||||
po_status: "REQUESTED",
|
|
||||||
approved_vendor: "",
|
approved_vendor: "",
|
||||||
acknowledge_by: "",
|
|
||||||
approved_by: "",
|
approved_by: "",
|
||||||
approved_price: 0,
|
approved_price: 0,
|
||||||
completed_status: "",
|
approved_quantity: 0,
|
||||||
|
total_approved_order_amount: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
type PurchaseOrders = {
|
type PurchaseOrders = {
|
||||||
@@ -86,16 +78,19 @@
|
|||||||
const columns: columns[] = [
|
const columns: columns[] = [
|
||||||
{ key: "name", title: "Name" },
|
{ key: "name", title: "Name" },
|
||||||
{ key: "purchase_order_number", title: "Purchase Order Number" },
|
{ key: "purchase_order_number", title: "Purchase Order Number" },
|
||||||
|
{ key: "po_type", title: "PO Type" },
|
||||||
|
{ key: "approval", title: "Approval" },
|
||||||
{ key: "po_quantity", title: "PO Quantity" },
|
{ key: "po_quantity", title: "PO Quantity" },
|
||||||
|
{ key: "po_price", title: "PO Price" },
|
||||||
|
{ key: "po_total_price", title: "PO Total Price" },
|
||||||
{ key: "po_status", title: "PO Status" },
|
{ key: "po_status", title: "PO Status" },
|
||||||
{ key: "approved_vendor", title: "Approved Vendor" },
|
{ key: "approved_vendor", title: "Approved Vendor" },
|
||||||
{ key: "approved_price", title: "Approved Price" },
|
|
||||||
{ key: "approved_quantity", title: "Approved Quantity" },
|
{ key: "approved_quantity", title: "Approved Quantity" },
|
||||||
|
{ key: "approved_price", title: "Approved Price" },
|
||||||
{
|
{
|
||||||
key: "total_approved_order_amount",
|
key: "total_approved_order_amount",
|
||||||
title: "Total Approved Order Amount",
|
title: "Total Approved Order Amount",
|
||||||
},
|
},
|
||||||
{ key: "approval", title: "Approval" },
|
|
||||||
{ key: "approved_by", title: "Approved By" },
|
{ key: "approved_by", title: "Approved By" },
|
||||||
{ key: "created_at", title: "Created At" },
|
{ key: "created_at", title: "Created At" },
|
||||||
{ key: "actions", title: "Actions" }, // For edit/delete buttons
|
{ key: "actions", title: "Actions" }, // For edit/delete buttons
|
||||||
@@ -123,9 +118,8 @@
|
|||||||
) {
|
) {
|
||||||
let query = supabase
|
let query = supabase
|
||||||
.from("purchaseorder_data")
|
.from("purchaseorder_data")
|
||||||
.select(
|
.select("*")
|
||||||
"id, purchase_order_number, villa_data, issue_id, prepared_date, po_type, po_quantity, po_status, approved_vendor, acknowledged, acknowledge_by, approved_price, approved_quantity, total_approved_order_amount, approval, completed_status, received, received_by, input_by, approved_by, created_at",
|
.eq("po_status", "REQUESTED")
|
||||||
)
|
|
||||||
.order(sort || "created_at", { ascending: order === "asc" })
|
.order(sort || "created_at", { ascending: order === "asc" })
|
||||||
.range(offset, offset + limit - 1);
|
.range(offset, offset + limit - 1);
|
||||||
if (filter) {
|
if (filter) {
|
||||||
@@ -246,8 +240,6 @@
|
|||||||
"completed_status",
|
"completed_status",
|
||||||
"received",
|
"received",
|
||||||
"received_by",
|
"received_by",
|
||||||
"approved_quantity",
|
|
||||||
"total_approved_order_amount",
|
|
||||||
"approved_by",
|
"approved_by",
|
||||||
"name",
|
"name",
|
||||||
"po_status",
|
"po_status",
|
||||||
@@ -273,17 +265,19 @@
|
|||||||
async function saveProject() {
|
async function saveProject() {
|
||||||
purchaseOrderInsert = {
|
purchaseOrderInsert = {
|
||||||
issue_id: newPurchaseOrders.issue_id || "",
|
issue_id: newPurchaseOrders.issue_id || "",
|
||||||
prepared_date: newPurchaseOrders.prepared_date || "",
|
|
||||||
po_type: newPurchaseOrders.po_type || "",
|
|
||||||
po_quantity: newPurchaseOrders.po_quantity || 0,
|
|
||||||
po_status: newPurchaseOrders.po_status || "REQUESTED",
|
|
||||||
approved_vendor: newPurchaseOrders.approved_vendor || "",
|
approved_vendor: newPurchaseOrders.approved_vendor || "",
|
||||||
acknowledge_by: newPurchaseOrders.acknowledge_by || "",
|
|
||||||
approved_price: newPurchaseOrders.approved_price || "",
|
|
||||||
approved_by: newPurchaseOrders.approved_by || "",
|
approved_by: newPurchaseOrders.approved_by || "",
|
||||||
completed_status: newPurchaseOrders.completed_status || "",
|
approved_price: newPurchaseOrders.approved_price || 0,
|
||||||
|
approved_quantity: newPurchaseOrders.approved_quantity || 0,
|
||||||
|
total_approved_order_amount:
|
||||||
|
newPurchaseOrders.approved_quantity *
|
||||||
|
newPurchaseOrders.approved_price,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!validateInput()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (isEditing && currentEditingId) {
|
if (isEditing && currentEditingId) {
|
||||||
const { data, error } = await supabase
|
const { data, error } = await supabase
|
||||||
.from("purchase_orders")
|
.from("purchase_orders")
|
||||||
@@ -348,10 +342,10 @@
|
|||||||
//validate input fields purchase order
|
//validate input fields purchase order
|
||||||
function validateInput() {
|
function validateInput() {
|
||||||
const requiredFields = [
|
const requiredFields = [
|
||||||
"prepared_date",
|
"issue_id",
|
||||||
"po_type",
|
|
||||||
"po_quantity",
|
|
||||||
"approved_vendor",
|
"approved_vendor",
|
||||||
|
"approved_price",
|
||||||
|
"approved_quantity",
|
||||||
];
|
];
|
||||||
for (const field of requiredFields) {
|
for (const field of requiredFields) {
|
||||||
if (!newPurchaseOrders[field]) {
|
if (!newPurchaseOrders[field]) {
|
||||||
@@ -363,7 +357,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function validateInputApproval() {
|
function validateInputApproval() {
|
||||||
const requiredFields = ["approved_price"];
|
const requiredFields = [
|
||||||
|
"approved_price",
|
||||||
|
"approved_vendor",
|
||||||
|
"approved_quantity",
|
||||||
|
];
|
||||||
for (const field of requiredFields) {
|
for (const field of requiredFields) {
|
||||||
if (!newPurchaseOrders[field]) {
|
if (!newPurchaseOrders[field]) {
|
||||||
alert(`Please fill in the ${field} field.`);
|
alert(`Please fill in the ${field} field.`);
|
||||||
@@ -456,7 +454,10 @@
|
|||||||
|
|
||||||
const { data, error } = await supabase
|
const { data, error } = await supabase
|
||||||
.from("purchase_orders")
|
.from("purchase_orders")
|
||||||
.update({ approval: newPurchaseOrders.approval })
|
.update({
|
||||||
|
approval: newPurchaseOrders.approval,
|
||||||
|
po_status: "APPROVED",
|
||||||
|
})
|
||||||
.eq("id", id);
|
.eq("id", id);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
@@ -776,6 +777,7 @@
|
|||||||
(e.target as HTMLSelectElement)?.value ?? "";
|
(e.target as HTMLSelectElement)?.value ?? "";
|
||||||
newPurchaseOrders.issue_id = selectedIssue;
|
newPurchaseOrders.issue_id = selectedIssue;
|
||||||
}}
|
}}
|
||||||
|
disabled
|
||||||
>
|
>
|
||||||
<option value="">Select Issue</option>
|
<option value="">Select Issue</option>
|
||||||
{#each issues as issue}
|
{#each issues as issue}
|
||||||
@@ -810,6 +812,7 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
disabled
|
||||||
>
|
>
|
||||||
{#each statusOptions as option}
|
{#each statusOptions as option}
|
||||||
<option
|
<option
|
||||||
@@ -833,27 +836,13 @@
|
|||||||
id={col.key}
|
id={col.key}
|
||||||
bind:value={newPurchaseOrders[col.key]}
|
bind:value={newPurchaseOrders[col.key]}
|
||||||
class="w-full px-3 py-2 border border-gray-300 rounded focus:outline-none focus:ring focus:ring-blue-500"
|
class="w-full px-3 py-2 border border-gray-300 rounded focus:outline-none focus:ring focus:ring-blue-500"
|
||||||
|
disabled
|
||||||
>
|
>
|
||||||
<option value="">Select PO Type</option>
|
<option value="">Select PO Type</option>
|
||||||
<option value="Regular">Regular</option>
|
<option value="Regular">Regular</option>
|
||||||
<option value="Urgent">Urgent</option>
|
<option value="Urgent">Urgent</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
{:else if col.key === "prepared_date"}
|
|
||||||
<div class="mb-4">
|
|
||||||
<label
|
|
||||||
for={col.key}
|
|
||||||
class="block text-sm font-medium text-gray-700 mb-1"
|
|
||||||
>
|
|
||||||
{col.title}
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
type="date"
|
|
||||||
id={col.key}
|
|
||||||
bind:value={newPurchaseOrders[col.key]}
|
|
||||||
class="w-full px-3 py-2 border border-gray-300 rounded focus:outline-none focus:ring focus:ring-blue-500"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{:else if col.key === "po_quantity"}
|
{:else if col.key === "po_quantity"}
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<label
|
<label
|
||||||
@@ -867,6 +856,7 @@
|
|||||||
id={col.key}
|
id={col.key}
|
||||||
bind:value={newPurchaseOrders[col.key]}
|
bind:value={newPurchaseOrders[col.key]}
|
||||||
class="w-full px-3 py-2 border border-gray-300 rounded focus:outline-none focus:ring focus:ring-blue-500"
|
class="w-full px-3 py-2 border border-gray-300 rounded focus:outline-none focus:ring focus:ring-blue-500"
|
||||||
|
disabled
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{:else if col.key === "approved_price"}
|
{:else if col.key === "approved_price"}
|
||||||
@@ -878,12 +868,47 @@
|
|||||||
{col.title}
|
{col.title}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
|
name="approved_price"
|
||||||
|
placeholder="Enter Approved Price"
|
||||||
type="number"
|
type="number"
|
||||||
id={col.key}
|
id={col.key}
|
||||||
bind:value={newPurchaseOrders[col.key]}
|
bind:value={newPurchaseOrders[col.key]}
|
||||||
class="w-full px-3 py-2 border border-gray-300 rounded focus:outline-none focus:ring focus:ring-blue-500"
|
class="w-full px-3 py-2 border border-gray-300 rounded focus:outline-none focus:ring focus:ring-blue-500"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
{:else if col.key === "approved_quantity"}
|
||||||
|
<div class="mb-4">
|
||||||
|
<label
|
||||||
|
for={col.key}
|
||||||
|
class="block text-sm font-medium text-gray-700 mb-1"
|
||||||
|
>
|
||||||
|
{col.title}
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
name="approved_quantity"
|
||||||
|
type="number"
|
||||||
|
id={col.key}
|
||||||
|
bind:value={newPurchaseOrders[col.key]}
|
||||||
|
class="w-full px-3 py-2 border border-gray-300 rounded focus:outline-none focus:ring focus:ring-blue-500"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{:else if col.key === "total_approved_order_amount"}
|
||||||
|
<div class="mb-4">
|
||||||
|
<label
|
||||||
|
for={col.key}
|
||||||
|
class="block text-sm font-medium text-gray-700 mb-1"
|
||||||
|
>
|
||||||
|
{col.title}
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
id={col.key}
|
||||||
|
class="w-full px-3 py-2 border border-gray-300 rounded focus:outline-none focus:ring focus:ring-blue-500"
|
||||||
|
readonly
|
||||||
|
value={newPurchaseOrders.approved_quantity *
|
||||||
|
newPurchaseOrders.approved_price}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
{:else if col.key === "approved_vendor"}
|
{:else if col.key === "approved_vendor"}
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<label
|
<label
|
||||||
|
|||||||
@@ -123,9 +123,8 @@
|
|||||||
) {
|
) {
|
||||||
let query = supabase
|
let query = supabase
|
||||||
.from("purchaseorder_data")
|
.from("purchaseorder_data")
|
||||||
.select(
|
.select("*")
|
||||||
"id, purchase_order_number, villa_data, issue_id, prepared_date, po_type, po_quantity, po_status, approved_vendor, acknowledged, acknowledge_by, approved_price, approved_quantity, total_approved_order_amount, approval, completed_status, received, received_by, input_by, approved_by, created_at",
|
.eq("po_status", "ACKNOWLEDGED")
|
||||||
)
|
|
||||||
.order(sort || "created_at", { ascending: order === "asc" })
|
.order(sort || "created_at", { ascending: order === "asc" })
|
||||||
.range(offset, offset + limit - 1);
|
.range(offset, offset + limit - 1);
|
||||||
if (filter) {
|
if (filter) {
|
||||||
@@ -373,53 +372,6 @@
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function updatePurchaseOrderStatus(
|
|
||||||
e: Event,
|
|
||||||
id: string,
|
|
||||||
row: PurchaseOrderDisplay,
|
|
||||||
) {
|
|
||||||
const selectedOption = (e.target as HTMLSelectElement)?.value ?? "";
|
|
||||||
const option = getStatusOption(selectedOption);
|
|
||||||
|
|
||||||
newPurchaseOrders = {
|
|
||||||
...row,
|
|
||||||
po_status: option?.value || row.po_status,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (option?.value === "APPROVED") {
|
|
||||||
if (!validateInput()) {
|
|
||||||
e.preventDefault();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const { data, error } = await supabase
|
|
||||||
.from("purchase_orders")
|
|
||||||
.update({ po_status: newPurchaseOrders.po_status })
|
|
||||||
.eq("id", id);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
console.error("Error updating purchase order status:", error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await fetchPurchaseOrder();
|
|
||||||
}
|
|
||||||
|
|
||||||
async function acknowledgedOk(id: string, status: boolean) {
|
|
||||||
const { data, error } = await supabase
|
|
||||||
.from("purchase_orders")
|
|
||||||
.update({ acknowledged: status })
|
|
||||||
.eq("id", id);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
console.error("Error acknowledging purchase order:", error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await fetchPurchaseOrder();
|
|
||||||
}
|
|
||||||
|
|
||||||
async function receivedOk(id: string, status: boolean) {
|
async function receivedOk(id: string, status: boolean) {
|
||||||
const { data, error } = await supabase
|
const { data, error } = await supabase
|
||||||
.from("purchase_orders")
|
.from("purchase_orders")
|
||||||
@@ -470,7 +422,7 @@
|
|||||||
async function completedStatusOk(id: string, status: string) {
|
async function completedStatusOk(id: string, status: string) {
|
||||||
const { data, error } = await supabase
|
const { data, error } = await supabase
|
||||||
.from("purchase_orders")
|
.from("purchase_orders")
|
||||||
.update({ completed_status: status })
|
.update({ completed_status: status, po_status: status })
|
||||||
.eq("id", id);
|
.eq("id", id);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
@@ -584,27 +536,6 @@
|
|||||||
>
|
>
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
{:else if col.key === "acknowledged"}
|
|
||||||
<td class="px-4 py-2 text-center">
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
checked={row.acknowledged}
|
|
||||||
on:change={async (e) => {
|
|
||||||
const isChecked = (
|
|
||||||
e.target as HTMLInputElement
|
|
||||||
).checked;
|
|
||||||
row.acknowledged = isChecked;
|
|
||||||
|
|
||||||
if (isChecked) {
|
|
||||||
// map to project
|
|
||||||
await acknowledgedOk(
|
|
||||||
row.id,
|
|
||||||
isChecked,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</td>
|
|
||||||
{:else if col.key === "received"}
|
{:else if col.key === "received"}
|
||||||
<td class="px-4 py-2 text-center">
|
<td class="px-4 py-2 text-center">
|
||||||
<input
|
<input
|
||||||
@@ -652,10 +583,10 @@
|
|||||||
<option value="" disabled selected
|
<option value="" disabled selected
|
||||||
>SELECT COMPLETE</option
|
>SELECT COMPLETE</option
|
||||||
>
|
>
|
||||||
<option value="APPROVED"
|
<option value="RECEIVED COMPLETE"
|
||||||
>RECEIVED COMPLETE</option
|
>RECEIVED COMPLETE</option
|
||||||
>
|
>
|
||||||
<option value="REJECTED"
|
<option value="RECEIVED INCOMPLETE"
|
||||||
>COMPLETE INCOMPLETE</option
|
>COMPLETE INCOMPLETE</option
|
||||||
>
|
>
|
||||||
</select>
|
</select>
|
||||||
|
|||||||
@@ -123,9 +123,9 @@
|
|||||||
) {
|
) {
|
||||||
let query = supabase
|
let query = supabase
|
||||||
.from("purchaseorder_data")
|
.from("purchaseorder_data")
|
||||||
.select(
|
.select("*")
|
||||||
"id, purchase_order_number, villa_data, issue_id, prepared_date, po_type, po_quantity, po_status, approved_vendor, acknowledged, acknowledge_by, approved_price, approved_quantity, total_approved_order_amount, approval, completed_status, received, received_by, input_by, approved_by, created_at",
|
// RECEIVED COMPLETED or RECEIVE - INCOMPLETE
|
||||||
)
|
.in("po_status", ["RECEIVED COMPLETE", "RECEIVED INCOMPLETE"])
|
||||||
.order(sort || "created_at", { ascending: order === "asc" })
|
.order(sort || "created_at", { ascending: order === "asc" })
|
||||||
.range(offset, offset + limit - 1);
|
.range(offset, offset + limit - 1);
|
||||||
if (filter) {
|
if (filter) {
|
||||||
@@ -423,7 +423,7 @@
|
|||||||
async function receivedOk(id: string, status: boolean) {
|
async function receivedOk(id: string, status: boolean) {
|
||||||
const { data, error } = await supabase
|
const { data, error } = await supabase
|
||||||
.from("purchase_orders")
|
.from("purchase_orders")
|
||||||
.update({ receivedOk: status })
|
.update({ received: status })
|
||||||
.eq("id", id);
|
.eq("id", id);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
@@ -470,7 +470,7 @@
|
|||||||
async function completedStatusOk(id: string, status: string) {
|
async function completedStatusOk(id: string, status: string) {
|
||||||
const { data, error } = await supabase
|
const { data, error } = await supabase
|
||||||
.from("purchase_orders")
|
.from("purchase_orders")
|
||||||
.update({ completed_status: status })
|
.update({ completed_status: status, po_status: status })
|
||||||
.eq("id", id);
|
.eq("id", id);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
|
|||||||
Reference in New Issue
Block a user