// 1 => LOADING // 2 => DONE // 3 => ERROR import * as api from "../api/po.js"; import { validatePurchaseOrder, groupPurchaseRequestsByItemId, calculateSummaryTotal } from "../functions/functions.js"; export default { namespaced: true, state: { statusOptions: [ { value: 'All', title: "All" }, { value: 'Draft', title: "Draft" }, { value: 'Pending', title: "Pending" }, { value: 'Approved', title: "Approved" }, { value: 'Rejected', title: "Rejected" }, { value: 'Completed', title: "Completed" }, ], selectedStatus: { value: 'All', title: "All" }, selectedDate: moment(new Date()).format('YYYY-MM-DD'), search: '', totalPage: 0, selectedPage: 1, loading: false, poList: [ { "poNumber": "PO1234566", "poDate": "01-01-2025", "poVendor": "PT ABC 123", "poTotal": "1000000", "poStatus": "DRAFT", } ], dialogForm: false, detailData: [], selectedPr: {}, loadingDetail: false, snackbar: { state: false, type: 'success', message: '', }, //FORM selectedDateForm: moment(new Date()).format('YYYY-MM-DD'), selectedDateEnd: moment(new Date()).format('YYYY-MM-DD'), selectedSupplier: {}, refNumber: '', taxPpn: 0, taxPph: 0, paymentTerm: 0, discountType: 'Percentage', discountTypeList: ['Percentage', 'Absolute'], discountAmount: 0, note: '', warehouseTypeList: ['Single', 'Multiple'], warehouseType: 'Single', warehouseList: [], selectedWarehouse: {}, itemList: [], selectedItemTemp: [], selectedItem: [], searchItem: '', itemTotal: { total: 0, ppn: 0, pph: 0, tax: 0, discount: 0, finalTotal: 0, }, defaultWarehouse: {}, shippingCost: 0, shippingCostStatus: true,//Sudah di bayar atau belum //END FORM supplierList: [], loadingAutocomplete: false, searchSupplier: "", dialogConfirmation: false, dialogDelete: false, selectedPO: {}, dialogItem: false, currentPageItem: 1, totalPageItem: 0, dialogFormAct: 'ADD', summary: [], summaryTotal: { total: 0, ppn: 0, pph: 0, tax: 0, discount: 0, finalTotal: 0, }, deletedItem: [],//kalau edit item sebelumnya yang dihapus masuk sini agar bisa dipilih lagi , dialogView: false, itemCategoryList: [], selectedItemCategory: {}, open_print: false, // isValidMultipleWarehouse: false, // Flag untuk validasi multiple warehouse isValidMultipleWarehouse: { status: false, message: '', }, riwayatPoList: [], selected_riwayatPo: {}, riwayatPoPage: 0, dialogRiwayat: false, currPageRiwayatPo: 1, supplierPriceSave: null, itemDesc: '' }, mutations: { update_shippingCost(state, val) { state.shippingCost = val; }, update_shippingCostStatus(state, val) { state.shippingCostStatus = val; }, update_selectedItemCategory(state, val) { state.selectedItemCategory = val; }, update_itemCategoryList(state, val) { state.itemCategoryList = val; }, update_dialogView(state, val) { state.dialogView = val; }, update_deletedItem(state, val) { state.deletedItem = val; }, update_summaryTotal(state, val) { state.summaryTotal = val; }, update_summary(state, val) { state.summary = val; }, update_dialogFormAct(state, val) { state.dialogFormAct = val; }, update_totalPageItem(state, val) { state.totalPageItem = val; }, update_currentPageItem(state, val) { state.currentPageItem = val; }, update_dialogItem(state, val) { state.dialogItem = val; }, update_selectedPO(state, val) { state.selectedPO = val; }, update_dialogDelete(state, val) { state.dialogDelete = val; }, update_dialogConfirmation(state, val) { state.dialogConfirmation = val; }, update_defaultWarehouse(state, val) { state.defaultWarehouse = val; }, update_itemTotal(state, val) { state.itemTotal = val; }, update_searchItem(state, val) { state.searchItem = val; }, update_selectedItemTemp(state, val) { state.selectedItemTemp = val; }, update_selectedItem(state, val) { state.selectedItem = val; }, update_itemList(state, val) { state.itemList = val; }, update_warehouseList(state, val) { state.warehouseList = val; }, update_supplierList(state, val) { state.supplierList = val; }, update_searchSupplier(state, val) { state.searchSupplier = val; }, update_loadingAutocomplete(state, val) { state.loadingAutocomplete = val; }, update_selectedWarehouse(state, val) { state.selectedWarehouse = val; }, update_warehouseTypeList(state, val) { state.warehouseTypeList = val; }, update_warehouseType(state, val) { state.warehouseType = val; // Disable and clear selectedWarehouse when type is Multiple if (val === 'Multiple') { state.selectedWarehouse = {}; } }, update_note(state, val) { state.note = val; }, update_discountAmount(state, val) { // debugger; if (state.discountType === 'Percentage' && val > 100) { state.snackbar = { state: true, type: 'warning', message: 'Diskon tidak boleh lebih dari 100', }; state.discountAmount = 100; return; } if (state.discountType === 'Absolute' && val > state.itemTotal.total && state.itemTotal.total > 0) { state.snackbar = { state: true, type: 'warning', message: 'Diskon tidak boleh lebih dari total', }; state.discountAmount = state.itemTotal.total; return; } state.discountAmount = val; }, update_discountType(state, val) { state.discountType = val; }, update_paymentTerm(state, val) { state.paymentTerm = val; }, update_taxPpn(state, val) { if (val > 0) { state.taxPpn = val; } else { state.taxPpn = 0; } }, update_taxPph(state, val) { if (val > 0) { state.taxPph = val; } else { state.taxPph = 0; } }, update_refNumber(state, val) { state.refNumber = val; }, update_selectedSupplier(state, val) { state.selectedSupplier = val; state.currPageRiwayatPo = 1 }, update_selectedDateForm(state, val) { state.selectedDateForm = val; }, update_selectedDateEnd(state, val) { state.selectedDateEnd = val; }, update_snackbar(state, val) { state.snackbar = val; }, update_loadingDetail(state, val) { state.loadingDetail = val; }, update_selectedPr(state, val) { state.selectedPr = val; }, update_detailData(state, val) { state.detailData = val; }, update_dialogForm(state, val) { state.dialogForm = val; }, update_selectedStatus(state, val) { state.selectedStatus = val; }, update_selectedDate(state, val) { state.selectedDate = val; }, update_search(state, val) { state.search = val; }, update_loading(state, val) { state.loading = val; }, update_totalPage(state, val) { state.totalPage = val; }, update_selectedPage(state, val) { state.selectedPage = val; }, update_poList(state, val) { state.poList = val; }, update_open_print(state, value) { state.open_print = value }, update_isValidMultipleWarehouse(state, value) { state.isValidMultipleWarehouse = value; }, update_riwayatPoList(state, val) { state.riwayatPoList = val; }, update_selected_riwayatPo(state, val) { state.selected_riwayatPo = val; }, update_riwayatPoPage(state, val) { state.riwayatPoPage = val; }, update_dialogRiwayat(state, val) { state.dialogRiwayat = val; }, update_currPageRiwayatPo(state, val) { state.currPageRiwayatPo = val; }, update_supplierPriceSave(state, val) { state.supplierPriceSave = val; }, update_itemDesc(state, val) { state.itemDesc = val; }, }, actions: { async deleteItemFromSummary(context, { itemId = null, detailId = null }) { // Jika itemId ada, hapus seluruh item dan detailsnya if (itemId) { const newSummary = context.state.summary.filter(item => item.keyID !== itemId); const newSelectedItem = context.state.selectedItem.filter(item => item.keyID !== itemId); if (context.state.dialogFormAct === 'EDIT') { let deletedItemBefore = JSON.parse(JSON.stringify(context.state.deletedItem)) const deletedItem = context.state.selectedItem.filter(item => item.keyID === itemId && item.PurchaseOrderDetailID !== undefined && item.PurchaseOrderDetailID !== null && item.PurchaseOrderDetailID !== 0); let newDeletedItem = [] deletedItem.forEach(de => { let cek = deletedItemBefore.find((element) => element.M_ItemID === de.M_ItemID && element.PurchaseRequestFlagID === de.PurchaseRequestFlagID && element.PurchaseOrderDetailID === de.PurchaseOrderDetailID) if (!cek) { newDeletedItem.push(de) } }); context.commit('update_deletedItem', [...deletedItemBefore, ...newDeletedItem]); } // const newRef = newSelectedItem.map(obj => obj.PurchaseRequestNumber).join(", "); const newRef = [...new Set(newSelectedItem.map(obj => obj.PurchaseRequestNumber))].join(", "); context.commit("update_refNumber", newRef); context.commit('update_summary', newSummary); context.commit('update_selectedItem', newSelectedItem); } // Jika detailId ada, hapus detail spesifik if (detailId) { // Hapus dari selectedItem const newSelectedItem = context.state.selectedItem.filter( item => item.PurchaseRequestFlagID !== detailId ); if (context.state.dialogFormAct === 'EDIT') { let deletedItemBefore = JSON.parse(JSON.stringify(context.state.deletedItem)) const deletedItem = context.state.selectedItem.filter( item => item.PurchaseRequestFlagID === detailId && item.PurchaseOrderDetailID !== undefined && item.PurchaseOrderDetailID !== null && item.PurchaseOrderDetailID !== 0 ); let newDeletedItem = [] deletedItem.forEach(de => { let cek = deletedItemBefore.find((element) => element.M_ItemID === de.M_ItemID && element.PurchaseRequestFlagID === de.PurchaseRequestFlagID && element.PurchaseOrderDetailID === de.PurchaseOrderDetailID) if (!cek) { newDeletedItem.push(de) } }); context.commit('update_deletedItem', [...deletedItemBefore, ...newDeletedItem]); } // Regenerate summary dari selectedItem yang baru const newSummary = await groupPurchaseRequestsByItemId(newSelectedItem, context); // const newRef = newSelectedItem.map(obj => obj.PurchaseRequestNumber).join(", "); const newRef = [...new Set(newSelectedItem.map(obj => obj.PurchaseRequestNumber))].join(", "); context.commit("update_refNumber", newRef); context.commit('update_summary', newSummary); context.commit('update_selectedItem', newSelectedItem); } // Hitung ulang total context.dispatch('countItemTotal'); context.dispatch('generateSummary'); }, generateSummaryTotal(context) { const summaryTotal = calculateSummaryTotal( context.state.summary, context.state.taxPpn, context.state.taxPph, context.state.discountType, context.state.discountAmount ); context.commit('update_summaryTotal', summaryTotal); }, async generateSummary_131025(context) { let data = JSON.parse(JSON.stringify(context.state.selectedItem)); console.log("Data untuk param groupPurchaseRequestsByItemId:", JSON.parse(JSON.stringify(data))); /** * Tambah validasi: * > Apakah bisa multiple warehouse? */ context.dispatch('isValidMultipleWarehouse'); if (context.state.warehouseType === "Multiple") { data.forEach((element) => { element.warehouse = { WarehouseID: element.WarehouseID, WarehouseName: element.WarehouseName, }; }); } else if (context.state.warehouseType === "Single") { data.forEach((element) => { element.warehouse = context.state.selectedWarehouse; // Semua item pakai warehouse yang sama }); } let summary = await groupPurchaseRequestsByItemId(data, context); context.commit('update_summary', summary); console.log("Summary setelah grouping:", JSON.parse(JSON.stringify(summary))); // Hitung summary total menggunakan fungsi dari functions.js const summaryTotal = calculateSummaryTotal( summary, context.state.taxPpn, context.state.taxPph, context.state.discountType, context.state.discountAmount ); context.commit('update_summaryTotal', summaryTotal); }, async generateSummary(context) { let data = JSON.parse(JSON.stringify(context.state.selectedItem)); console.log("Data untuk param groupPurchaseRequestsByItemId:", JSON.parse(JSON.stringify(data))); // Validasi multiple warehouse context.dispatch('isValidMultipleWarehouse'); if (context.state.warehouseType === "Multiple") { data.forEach((element) => { element.warehouse = { WarehouseID: element.WarehouseID, WarehouseName: element.WarehouseName, }; }); } else if (context.state.warehouseType === "Single") { data.forEach((element) => { element.warehouse = context.state.selectedWarehouse; }); } // **Batch fetch supplier prices sekali saja** const supplierPriceMap = await context.dispatch('batchGetSupplierPrices', data); // Pass priceMap ke fungsi grouping let summary = await groupPurchaseRequestsByItemId(data, context, supplierPriceMap); context.commit('update_summary', summary); console.log("Summary setelah grouping:", JSON.parse(JSON.stringify(summary))); const summaryTotal = calculateSummaryTotal( summary, context.state.taxPpn, context.state.taxPph, context.state.discountType, context.state.discountAmount ); context.commit('update_summaryTotal', summaryTotal); }, // Di Vuex store actions async batchGetSupplierPrices(context, items) { // Group items by M_ItemID dan sum qty const itemQtyMap = items.reduce((acc, item) => { const itemId = item.M_ItemID; const qty = Number(item.PoQty || 0); if (!acc[itemId]) { acc[itemId] = qty; } else { acc[itemId] += qty; } return acc; }, {}); // Fetch all prices in parallel const pricePromises = Object.entries(itemQtyMap).map(async ([itemId, qty]) => { const supplierPrice = await context.dispatch('getDefaultSupplierPrice', { itemID: itemId, qty: qty }); return { itemId, qty, supplierPrice }; }); const results = await Promise.all(pricePromises); // Convert to Map for easy lookup const priceMap = new Map( results.map(r => [r.itemId, r.supplierPrice]) ); return priceMap; }, multipleWarehouseValidation(context, selectedItem) { let data; if (!selectedItem || selectedItem.length === 0) { data = JSON.parse(JSON.stringify(context.state.selectedItem)); } else { data = JSON.parse(JSON.stringify(selectedItem)); } // Pakai 'Set' JS Object yang hanya menyimpan nilai unik. const warehouseIds = new Set(); data.forEach(item => { if (item.WarehouseID) { // Kalau ada yang sama maka disimpan sekali. warehouseIds.add(item.WarehouseID); } }); if (warehouseIds.size > 1) { return true; // Ada lebih dari satu WarehouseID } else { return false; // Hanya ada satu WarehouseID } }, async isValidMultipleWarehouse(context) { /** * @param: array of PurchaseRequestDetailID dari selectedItem * @api: api.isValidMultipleWarehouse * @return: JSON -> {data.status (boolean), data.message (string)} * */ if (context.state.selectedItem.length === 0) { return false; // Tidak ada item yang dipilih } try { let payload = { "PurchaseRequestDetailIDs": context.state.selectedItem.map(item => item.PurchaseRequestDetailID), "token": one_token(), }; let response = await api.isValidMultipleWarehouse(payload) console.log("Payload untuk isValidMultipleWarehouse:", JSON.parse(JSON.stringify(payload.PurchaseRequestDetailIDs))); console.log("Response dari isValidMultipleWarehouse:", JSON.parse(JSON.stringify(response))); if (response.status !== "OK") { let snackbar = { state: true, type: "error", message: response.message, } context.commit("update_isValidMultipleWarehouse", { status: false, message: '', }); context.commit("update_snackbar", snackbar); } else {; context.commit("update_isValidMultipleWarehouse", { status: response.data.status, message: response.data.message, }); if(response.data.status == false) { context.commit("update_warehouseType", 'Single'); context.commit("update_selectedWarehouse", context.state.selectedWarehouse); } }; } catch (e) { let snackbar = { state: true, type: "error", message: e.message, } context.commit("update_snackbar", snackbar); } }, assignEdit(context) { let data = context.state.selectedPO context.commit("update_selectedDateForm", data.PurchaseOrderDate); context.commit("update_searchSupplier", data.SupplierName); context.commit("update_selectedSupplier", { "SupplierID": data.PurchaseOrderSupplierID, "SupplierCode": data.SupplierCode, "SupplierName": data.SupplierName }); context.commit("update_selectedItemCategory", { "itemCategoryID": data.itemCategoryID, "itemCategoryName": data.itemCategoryName }); context.commit("update_refNumber", data.PurchaseOrderRefNumber); context.commit("update_shippingCost", data.PurchaseOrderShippingCost); context.commit("update_shippingCostStatus", data.PurchaseOrderShippingCostStatus === 'Y' ? true : false); context.commit("update_taxPpn", data.PurchaseOrderTaxPercentPpn); context.commit("update_taxPph", data.PurchaseOrderTaxPercentPph); context.commit("update_paymentTerm", data.PurchaseOrderPaymentTerm); context.commit("update_discountType", data.PurchaseOrderDiscountPercent > 0 ? 'Percentage' : 'Absolute'); if (data.PurchaseOrderDiscountPercent > 0) { context.commit("update_discountAmount", parseFloat(data.PurchaseOrderDiscountPercent)); } else { context.commit("update_discountAmount", parseFloat(data.PurchaseOrderDiscountAmount)); } context.commit("update_note", data.PurchaseOrderNote); context.commit("update_warehouseType", data.PurchaseOrderWarehouseType); context.commit("update_selectedWarehouse", { "WarehouseID": data.PurchaseOrderWarehouseID, "WarehouseCode": data.WarehouseCode, "WarehouseName": data.WarehouseName, }); context.commit("update_dialogFormAct", 'EDIT'); context.dispatch("countItemTotal"); }, async resetForm(context) { context.commit("update_selectedDateForm", moment(new Date()).format('YYYY-MM-DD')); context.commit("update_selectedSupplier", {}); context.commit("update_selectedWarehouse", {}); context.commit("update_defaultWarehouse", {}); context.commit("update_warehouseType", 'Single'); context.commit("update_refNumber", ''); context.commit("update_taxPpn", 0); context.commit("update_taxPph", 0); context.commit("update_paymentTerm", 0); context.commit("update_discountType", 'Percentage'); context.commit("update_discountAmount", 0); context.commit("update_note", ''); context.commit("update_selectedItemTemp", []); context.commit("update_selectedItem", []); context.commit("update_deletedItem", []); context.commit("update_selectedItemCategory", {}); context.commit("update_summary", []); context.commit("update_shippingCost", 0); context.commit("update_shippingCostStatus", true); context.commit("update_itemList", []); context.commit("update_searchItem", ''); context.commit("update_warehouseList", []); context.commit("update_searchSupplier", 'null'); context.commit("update_supplierList", []); context.commit("update_dialogFormAct", 'ADD'); context.commit("update_summaryTotal", { total: 0, tax: 0, ppn: 0, pph: 0, discount: 0, finalTotal: 0, }); context.commit("update_itemTotal", { total: 0, tax: 0, ppn: 0, pph: 0, discount: 0, finalTotal: 0, }); }, countItemTotal(context) { let selectedItem = context.state.selectedItem; if (selectedItem.length === 0) { let hasil = { total: 0, tax: 0, ppn: 0, pph: 0, discount: 0, finalTotal: 0, } context.commit("update_itemTotal", hasil); return; } // Fix: Ensure we're working with numeric values let total = selectedItem.reduce((acc, item) => { // Convert string to number if needed const itemTotal = typeof item.Total === 'string' ? parseFloat(item.Total.replace(/\./g, '').replace(',', '.')) : item.Total; return acc + (isNaN(itemTotal) ? 0 : itemTotal); }, 0); total = Math.round(total * 100) / 100; let discount = parseFloat(context.state.discountAmount) || 0; if (context.state.discountType === 'Percentage') { discount = Math.round((discount / 100) * total * 100) / 100; } let newTotal = Math.round((total - discount) * 100) / 100; let ppn = Math.round((parseFloat(context.state.taxPpn) / 100) * newTotal * 100) / 100; let pph = Math.round((parseFloat(context.state.taxPph) / 100) * newTotal * 100) / 100; let pajak = Math.round((ppn + pph) * 100) / 100; let final = Math.round((newTotal + pajak) * 100) / 100; let hasil = { total: total, tax: pajak, ppn: ppn, pph: pph, discount: discount, finalTotal: final, } context.commit("update_itemTotal", hasil); }, updatePoQty(context, { itemId, newPoQty }) { let updatedSelectedItem = context.state.selectedItem.map(item => { if (item.PurchaseRequestFlagID === itemId) { // Convert string to number and ensure minimum value of 1 const numericPoQty = Number(newPoQty); item.PoQty = Math.max(1, Math.floor(isNaN(numericPoQty) ? 1 : numericPoQty)); // Recalculate item total let price = item.DefaultPurchase?.SupplierPricePrice || 0; // Apply discount if exists if (item.discount > 0) { if (item.discountType === 'P') { price = price - (item.discount * price / 100); } else if (item.discountType === 'R') { price = price - item.discount; } } item.Total = item.PoQty * price; } return item; }); context.commit('update_selectedItem', updatedSelectedItem); // Regenerate summary context.dispatch('generateSummary'); context.dispatch('countItemTotal'); context.dispatch('generateSummaryTotal'); }, async getSupplier(context) { if (context.state.searchSupplier.length < 2) return; context.commit("update_loadingAutocomplete", true); try { var payload = { token: one_token(), search: context.state.searchSupplier, }; let response = await api.getSupplier(payload); if (response.status != "OK") { let snackbar = { state: true, type: "error", message: response.message, } context.commit("update_snackbar", snackbar); context.commit("update_loadingAutocomplete", false); } else { let data = { records: response.data.records, total: response.data.total, }; context.commit("update_supplierList", data.records); context.commit("update_loadingAutocomplete", false); } } catch (e) { let snackbar = { state: true, type: "error", message: e.message, } context.commit("update_snackbar", snackbar); context.commit("update_loadingAutocomplete", false); } }, async getItemCategory(context) { context.commit("update_loadingAutocomplete", true); try { var payload = { token: one_token(), }; let response = await api.getItemCategory(payload); if (response.status != "OK") { let snackbar = { state: true, type: "error", message: response.message, } context.commit("update_snackbar", snackbar); context.commit("update_loadingAutocomplete", false); } else { let data = { records: response.data.records, total: response.data.total, }; context.commit("update_itemCategoryList", data.records); context.commit("update_loadingAutocomplete", false); } } catch (e) { let snackbar = { state: true, type: "error", message: e.message, } context.commit("update_snackbar", snackbar); context.commit("update_loadingAutocomplete", false); } }, async getWarehouse(context) { context.commit("update_loadingAutocomplete", true); try { var payload = { regionalId: one_user().S_RegionalID, categoryID: context.state.selectedItemCategory.itemCategoryID, token: one_token(), }; let response = await api.getWarehouse(payload); if (response.status != "OK") { let snackbar = { state: true, type: "error", message: response.message, } context.commit("update_snackbar", snackbar); context.commit("update_loadingAutocomplete", false); } else { let data = { records: response.data.records, total: response.data.total, }; response.data.records.forEach(element => { if (element.WarehouseIsDefault === 'Y') { context.commit("update_defaultWarehouse", element); context.commit("update_selectedWarehouse", element); } }); context.commit("update_warehouseList", response.data.records); context.commit("update_loadingAutocomplete", false); } } catch (e) { let snackbar = { state: true, type: "error", message: e.message, } context.commit("update_snackbar", snackbar); context.commit("update_loadingAutocomplete", false); } }, async getItem(context) { context.commit("update_loading", true); try { var payload = { "search": context.state.searchItem, "currentPage": context.state.currentPageItem, "supplierID": context.state.selectedSupplier.SupplierID, "itemCategoryID": context.state.selectedItemCategory.itemCategoryID, "regionalId": one_user().S_RegionalID, "token": one_token(), }; let response = await api.getItem(payload); if (response.status != "OK") { let snackbar = { state: true, type: "error", message: response.message, } context.commit("update_snackbar", snackbar); context.commit("update_loading", false); } else { let data = { records: response.data.records, total: response.data.totalPage, }; context.commit("update_itemList", data.records); context.commit("update_totalPageItem", data.total); context.commit("update_loading", false); } } catch (e) { let snackbar = { state: true, type: "error", message: e.message, } context.commit("update_snackbar", snackbar); context.commit("update_loading", false); } }, async getItemUpdate(context) { context.commit("update_loading", true); try { var payload = { "POID": context.state.selectedPO.PurchaseOrderID, "token": one_token(), }; let response = await api.getItemUpdate(payload); if (response.status != "OK") { let snackbar = { state: true, type: "error", message: response.message, } context.commit("update_snackbar", snackbar); context.commit("update_loading", false); } else { let data = { records: response.data.records, total: response.data.totalPage, }; context.commit("update_selectedItem", data.records); /** * Tambah validasi: * > Apakah bisa multiple warehouse? */ context.dispatch('isValidMultipleWarehouse'); context.commit("update_summary", response.data.summary) context.dispatch("countItemTotal"); // Hitung summary total menggunakan fungsi dari functions.js // TODO: Check ini akibat penyesuaian const summaryTotal = calculateSummaryTotal( response.data.summary, context.state.taxPpn, context.state.taxPph, context.state.discountType, context.state.discountAmount ); context.commit('update_summaryTotal', summaryTotal); context.commit("update_loading", false); } } catch (e) { let snackbar = { state: true, type: "error", message: e.message, } context.commit("update_snackbar", snackbar); context.commit("update_loading", false); } }, async saveOrder(context) { try { if (!validatePurchaseOrder(context)) { return; } const invalidQtyItems = context.state.selectedItem.filter(item => { // Convert string to number first const poQty = Number(item.PoQty); // Check if conversion failed (NaN), is less than 1, or not an integer return isNaN(poQty) || poQty < 1 || !Number.isInteger(poQty); }); if (invalidQtyItems.length > 0) { let snackbar = { state: true, type: "error", message: "Semua item harus memiliki quantity minimal 1", } context.commit("update_snackbar", snackbar); return; } // Validasi: Cek apakah ada item dengan harga supplier null if (context.state.supplierPriceSave === null) { let snackbar = { state: true, type: "error", message: `Jumlah Quantity tidak tersedia di rentang harga supplier pada item ${context.state.itemDesc}!`, } context.commit("update_snackbar", snackbar); return; } context.commit("update_loading", true); var payload = { "token": one_token(), "Date": context.state.selectedDateForm, "RefNumber": context.state.refNumber, "SupplierID": context.state.selectedSupplier.SupplierID, "ItemCategoryID": context.state.selectedItemCategory.itemCategoryID, "TaxPercent": context.state.taxPpn, "PaymentTerm": context.state.paymentTerm, "DiscountPercent": context.state.discountType === 'Percentage' ? context.state.discountAmount : 0, "DiscountAmount": context.state.discountType === 'Absolute' ? context.state.discountAmount : 0, "WarehouseType": context.state.warehouseType, "WarehouseID": context.state.selectedWarehouse.WarehouseID, "Note": context.state.note, "SubTotal": context.state.summaryTotal.total, "TaxPercentPph": context.state.taxPph, "TaxPercentPpn": context.state.taxPpn, "TaxAmount": context.state.summaryTotal.tax, "TaxAmountPph": context.state.summaryTotal.pph, "TaxAmountPpn": context.state.summaryTotal.ppn, "GrandTotal": context.state.summaryTotal.finalTotal, "ShippingCost": context.state.shippingCost, "ShippingCostStatus": context.state.shippingCostStatus, // "Details": detail, "Summary": context.state.summary }; // Validasi Total Tidak Boleh <0 const financialChecks = [ { value: payload.GrandTotal, name: "Total" }, { value: payload.SubTotal, name: "Sub Total" }, { value: payload.TaxAmount, name: "Pajak" }, { value: payload.TaxAmountPph, name: "Pajak PPH" }, { value: payload.TaxAmountPpn, name: "Pajak PPN" }, { value: payload.DiscountAmount, name: "Diskon" }, { value: payload.ShippingCost, name: "Biaya Ekspedisi" } ]; for (const check of financialChecks) { if (check.value < 0) { let snackbar = { state: true, type: "error", message: `${check.name} tidak boleh kurang dari 0`, } context.commit("update_snackbar", snackbar); context.commit("update_loading", false); return; } } let response = await api.saveOrder(payload); if (response.status != "OK") { let snackbar = { state: true, type: "error", message: response.message, } context.commit("update_snackbar", snackbar); context.commit("update_loading", false); } else { let data = { records: response.data.records, total: response.data.total, }; let snackbar = { state: true, type: "success", message: "Berhasil simpan data", } context.commit("update_snackbar", snackbar); context.commit("update_loading", false); context.commit("update_dialogForm", false); context.dispatch("resetForm"); context.dispatch("searchData"); } } catch (e) { let snackbar = { state: true, type: "error", message: e.message, } context.commit("update_snackbar", snackbar); context.commit("update_loading", false); } }, async searchData(context) { context.commit("update_loading", true); try { var url_string = window.location.href var url = new URL(url_string); var xdate = url.searchParams.get("date"); var xsearch = url.searchParams.get("search"); if (xsearch) { context.commit("update_search", xsearch); } if (xdate) { context.commit("update_selectedDate", xdate); context.commit("update_selectedDateEnd", xdate); } var payload = { "token": one_token(), "currentPage": context.state.selectedPage, "search": context.state.search, "startDate": context.state.selectedDate, "endDate": context.state.selectedDateEnd, "status": context.state.selectedStatus.value, }; let response = await api.search(payload); if (response.status != "OK") { let snackbar = { state: true, type: "error", message: response.message, } context.commit("update_snackbar", snackbar); context.commit("update_loading", false); } else { let data = { records: response.data.records, total: response.data.total, }; context.commit("update_totalPage", response.data.totalPage); context.commit("update_poList", data.records); context.commit("update_loading", false); context.dispatch("system/getlistnotif", null, { root: true }) } } catch (e) { let snackbar = { state: true, type: "error", message: e.message, } context.commit("update_snackbar", snackbar); context.commit("update_loading", false); } }, async requestOrder(context) { context.commit("update_loading", true); try { var payload = { "token": one_token(), "ID": context.state.selectedPO.PurchaseOrderID, }; let response = await api.requestOrder(payload); if (response.status != "OK") { let snackbar = { state: true, type: "error", message: response.message, } context.commit("update_snackbar", snackbar); context.commit("update_loading", false); } else { let data = { records: response.data.records, total: response.data.total, }; let snackbar = { state: true, type: "success", message: "Berhasil request order", } context.commit("update_snackbar", snackbar); context.commit("update_loading", false); context.commit("update_dialogConfirmation", false); } } catch (e) { let snackbar = { state: true, type: "error", message: e.message, } context.commit("update_snackbar", snackbar); context.commit("update_loading", false); } }, async deleteOrder(context) { context.commit("update_loading", true); try { var payload = { "token": one_token(), "PurchaseOrderId": context.state.selectedPO.PurchaseOrderID, }; let response = await api.deleteOrder(payload); if (response.status != "OK") { let snackbar = { state: true, type: "error", message: response.message, } context.commit("update_snackbar", snackbar); context.commit("update_loading", false); } else { let data = { records: response.data.records, total: response.data.total, }; let snackbar = { state: true, type: "success", message: "Berhasil hapus order", } context.commit("update_snackbar", snackbar); await context.dispatch("searchData"); context.commit("update_loading", false); context.commit("update_dialogDelete", false); } } catch (e) { let snackbar = { state: true, type: "error", message: e.message, } context.commit("update_snackbar", snackbar); context.commit("update_loading", false); } }, async updateOrder(context) { try { if (!validatePurchaseOrder(context)) { return; } const invalidQtyItems = context.state.selectedItem.filter(item => { // Convert string to number first const poQty = Number(item.PoQty); // Check if conversion failed (NaN), is less than 1, or not an integer return isNaN(poQty) || poQty < 1 || !Number.isInteger(poQty); }); console.log("InvalidQtyItem updateOrder", invalidQtyItems) if (invalidQtyItems.length > 0) { let snackbar = { state: true, type: "error", message: "Semua item harus memiliki quantity minimal 1", } context.commit("update_snackbar", snackbar); return; } // Validasi: Cek apakah ada item dengan harga supplier null if (context.state.supplierPriceSave === null) { let snackbar = { state: true, type: "error", message: `Jumlah Quantity tidak tersedia di rentang harga supplier pada item ${context.state.itemDesc}!`, } context.commit("update_snackbar", snackbar); return; } var payload = { "token": one_token(), "Date": context.state.selectedDateForm, "RefNumber": context.state.refNumber, "SupplierID": context.state.selectedSupplier.SupplierID, "TaxPercent": context.state.taxPpn, "PaymentTerm": context.state.paymentTerm, "ItemCategoryID": context.state.selectedItemCategory.itemCategoryID, "DiscountPercent": context.state.discountType === 'Percentage' ? context.state.discountAmount : 0, "DiscountAmount": context.state.discountType === 'Absolute' ? context.state.discountAmount : 0, "WarehouseType": context.state.warehouseType, "WarehouseID": context.state.selectedWarehouse.WarehouseID, "Note": context.state.note, "SubTotal": context.state.summaryTotal.total, "TaxPercentPph": context.state.taxPph, "TaxPercentPpn": context.state.taxPpn, "TaxAmount": context.state.summaryTotal.tax, "TaxAmountPph": context.state.summaryTotal.pph, "TaxAmountPpn": context.state.summaryTotal.ppn, "GrandTotal": context.state.summaryTotal.finalTotal, "ShippingCost": context.state.shippingCost, "ShippingCostStatus": context.state.shippingCostStatus, "PO": context.state.selectedPO, "Summary": context.state.summary, "deletedItem": context.state.deletedItem }; // Validasi Total Tidak Boleh <0 const financialChecks = [ { value: payload.GrandTotal, name: "Total" }, { value: payload.SubTotal, name: "Sub Total" }, { value: payload.TaxAmount, name: "Pajak" }, { value: payload.TaxAmountPph, name: "Pajak PPH" }, { value: payload.TaxAmountPpn, name: "Pajak PPN" }, { value: payload.DiscountAmount, name: "Diskon" }, { value: payload.ShippingCost, name: "Biaya Ekspedisi" } ]; for (const check of financialChecks) { if (check.value < 0) { let snackbar = { state: true, type: "error", message: `${check.name} tidak boleh kurang dari 0`, } context.commit("update_snackbar", snackbar); context.commit("update_loading", false); return; } } context.commit("update_loading", true); let response = await api.updateOrder(payload); if (response.status != "OK") { let snackbar = { state: true, type: "error", message: response.message, } context.commit("update_snackbar", snackbar); context.commit("update_loading", false); } else { let data = { records: response.data.records, total: response.data.total, }; let snackbar = { state: true, type: "success", message: "Berhasil simpan data", } context.commit("update_snackbar", snackbar); context.commit("update_loading", false); context.commit("update_dialogForm", false); context.dispatch("resetForm"); context.dispatch("searchData"); } } catch (e) { let snackbar = { state: true, type: "error", message: e.message, } context.commit("update_snackbar", snackbar); context.commit("update_loading", false); } }, async approveOrder(context, payload) { context.commit("update_loading", true); try { payload.token = one_token() let response = await api.approvePOrder(payload); if (response.status != 'OK') { let snackbar = { state: true, type: "error", message: response.message, } context.commit("update_snackbar", snackbar); context.commit("update_loading", false); } else { let params = { token: one_token(), id: payload.poID } let generateitempo = await api.generateItemPO(params) if (generateitempo.status != 'OK') { let snackbar = { state: true, type: "error", message: response.message, } context.commit("update_snackbar", snackbar); context.commit("update_loading", false); } else { let snackbar = { state: true, type: "success", message: "Berhasil approve order", } context.commit("update_snackbar", snackbar); await context.dispatch("searchData"); context.commit("update_loading", false); } } } catch (e) { let snackbar = { state: true, type: "error", message: e.message, } context.commit("update_snackbar", snackbar); context.commit("update_loading", false); } }, async getPoBySupplier(context) { context.commit("update_loading", true); try { var payload = { token: one_token(), supplierID: context.state.selectedSupplier.SupplierID, currentPage: context.state.currPageRiwayatPo, }; let response = await api.getPoBySupplier(payload); if (response.status != "OK") { let snackbar = { state: true, type: "error", message: response.message, } context.commit("update_snackbar", snackbar); context.commit("update_loading", false); } else { let data = { records: response.data.records, totalPage: response.data.totalPage, }; context.commit("update_riwayatPoList", data.records); context.commit("update_riwayatPoPage", data.totalPage); context.commit("update_loading", false); } } catch (e) { let snackbar = { state: true, type: "error", message: e.message, } context.commit("update_snackbar", snackbar); context.commit("update_loading", false); } }, async getDefaultSupplierPrice(context, payload) { context.commit("update_loading", true); try { payload.token = one_token() payload.supplierID = context.state.selectedSupplier.SupplierID let response = await api.getDefaultSupplierPrice(payload); if (response.status != "OK") { let snackbar = { state: true, type: "error", message: response.message, } context.commit("update_snackbar", snackbar); context.commit("update_loading", false); } else { let data = { records: response.data.records, }; context.commit("update_loading", false); return data.records; } } catch (e) { let snackbar = { state: true, type: "error", message: e.message, } context.commit("update_snackbar", snackbar); context.commit("update_loading", false); } }, }, };