feature: po pay downpayment

This commit is contained in:
2026-07-20 13:14:28 +07:00
parent dd5f0b6ab4
commit d92fb57751
64 changed files with 6166 additions and 1739 deletions

View File

@@ -0,0 +1,165 @@
import * as api from '../api/api.js';
export default {
namespaced: true,
state: {
/* common */
snackbar: {
color: 'success',
msg: '',
state: false
},
loading_process: false,
selected_orderaset: {},
viewonlymode: false,
/* main layout */
filterpo: {
startdate: moment(new Date()).format('YYYY-MM-DD'),
enddate: moment(new Date()).format('YYYY-MM-DD'),
status: 'All',
search: ''
},
list_status: ['All', 'Draft', 'Pending', 'Approved', 'Rejected', 'Completed'],
list_asetpo: {
records: [],
total: 0
},
currpage: 1,
/* delete order */
dialog_deleteorder: false,
/* attachment */
dialog_attachment: false,
assets_attachment: []
},
mutations: {
/* common */
update_snackbar(state, val) {
state.snackbar = val
},
update_loading_process(state, val) {
state.loading_process = val
},
update_selected_orderaset(state, val) {
state.selected_orderaset = val
},
update_viewonlymode(state, val) {
state.viewonlymode = val
},
/* main layout */
update_filterpo(state, val) {
state.filterpo = val
},
update_list_status(state, val) {
state.list_status = val
},
update_list_asetpo(state, val) {
state.list_asetpo = val
},
update_currpage(state, val) {
state.currpage = val
},
/* delete order */
update_dialog_deleteorder(state, val) {
state.dialog_deleteorder = val
},
/* attachment */
update_dialog_attachment(state, val) {
state.dialog_attachment = val
},
update_assets_attachment(state, val) {
state.assets_attachment = val
}
},
actions: {
async getListingPOAsset(context) {
try {
const params = {
token: one_token(),
currpage: context.state.currpage,
...context.state.filterpo
};
const resp = await api.getDaftarPoAset(params);
if (resp.status != 'OK') {
throw new Error(resp.message);
}
context.commit('update_list_asetpo', resp.data);
} catch (e) {
const snac = { color: 'error', msg: e.message, state: true };
context.commit("update_snackbar", snac);
}
},
async getAssetAttachment(context, param) {
try {
const params = {
token: one_token(),
contractID: param.contractID,
poID: param.poID
};
const resp = await api.getDaftarAttachment(params);
if (resp.status != 'OK') {
throw new Error(resp.message);
}
context.commit('update_assets_attachment', resp.data);
} catch (e) {
const snac = { color: 'error', msg: e.message, state: true };
context.commit("update_snackbar", snac);
}
},
async uploadAttachment(context, params) {
try {
context.state.loading_process = true;
const resp = await api.uploadAttachment(params);
if (resp.status != 'OK') {
throw new Error(resp.message);
}
const snac = { color: 'success', msg: resp.data, state: true };
context.commit("update_snackbar", snac);
context.dispatch('getListingPOAsset');
context.state.loading_process = false;
context.state.dialog_attachment = false;
} catch (e) {
context.state.loading_process = false;
const snac = { color: 'error', msg: e.message, state: true };
context.commit("update_snackbar", snac);
}
},
async deleteOrderAsset(context) {
try {
context.state.loading_process = true;
const order = context.state.selected_orderaset;
const params = {
token: one_token(),
poID: order.PurchaseOrderID,
contractID: order.contractID,
ponumber: order.PurchaseOrderNumber,
SupplierDownpaymentID: order.SupplierDownpaymentID
};
const resp = await api.deletePoAsset(params);
if (resp.status != 'OK') {
throw new Error(resp.message);
}
const snac = { color: 'success', msg: resp.data, state: true };
context.commit("update_snackbar", snac);
context.dispatch('getListingPOAsset');
context.state.loading_process = false;
context.state.dialog_deleteorder = false;
} catch (e) {
context.state.loading_process = false;
const snac = { color: 'error', msg: e.message, state: true };
context.commit("update_snackbar", snac);
}
}
}
}

View File

@@ -1,7 +1,8 @@
import * as api from '../api/api.js';
export default {
namespaced: true,
state: {
dialog_create_contract: false,
form_kontrak: {
nama_kontrak: '',
tanggal_kontrak: moment(new Date()).format('YYYY-MM-DD'),
@@ -11,17 +12,136 @@ export default {
jumlah_cicilan: 1,
tanggalBayar_cicilan: 1,
besarNilai_cicilan: 0,
type_downpayment: 'persen',
type_downpayment: 'percent',
besarNilai_downpayment: 0
}
},
mutations: {
update_dialog_create_contract(state, val) {
state.dialog_create_contract = val
},
update_form_kontrak(state, val) {
state.form_kontrak = val
}
},
actions: {}
actions: {
async saveOrderAsset(context, params) {
try {
context.commit("common/update_loading_process", true, { root: true });
params.token = one_token();
const resp = await api.createPoAsset(params);
if (resp.status != 'OK') {
throw new Error(resp.message);
}
const snac = { color: 'success', msg: resp.data, state: true };
context.commit("common/update_snackbar", snac, { root: true });
context.commit("common/update_loading_process", false, { root: true });
context.commit("orderAsset/update_dialog_create_order", false, { root: true });
context.dispatch('common/getListingPOAsset', {}, { root: true });
} catch (error) {
context.commit("common/update_loading_process", false, { root: true });
const snac = { color: 'error', msg: error.message, state: true };
context.commit("common/update_snackbar", snac, { root: true });
}
},
async editOrderAsset(context, params) {
try {
context.commit("common/update_loading_process", true, { root: true });
params.token = one_token();
const resp = await api.editPoAsset(params);
if (resp.status != 'OK') {
throw new Error(resp.message);
}
const snac = { color: 'success', msg: resp.data, state: true };
context.commit("common/update_snackbar", snac, { root: true });
context.commit("common/update_loading_process", false, { root: true });
context.commit("orderAsset/update_dialog_create_order", false, { root: true });
context.dispatch('common/getListingPOAsset', {}, { root: true });
} catch (error) {
context.commit("common/update_loading_process", false, { root: true });
const snac = { color: 'error', msg: error.message, state: true };
context.commit("common/update_snackbar", snac, { root: true });
}
},
async sendRequestPO(context, poID) {
try {
context.commit("common/update_loading_process", true, { root: true });
let params = {
token: one_token(),
approvelevel: "0",
poID: poID,
}
const resp = await api.updateApprovalPO(params);
if (resp.status != 'OK') {
throw new Error(resp.message);
}
const snac = { color: 'success', msg: resp.data, state: true };
context.commit("common/update_snackbar", snac, { root: true });
context.commit("common/update_loading_process", false, { root: true });
context.commit("orderAsset/update_dialog_create_order", false, { root: true });
context.dispatch('common/getListingPOAsset', {}, { root: true });
} catch (error) {
context.commit("common/update_loading_process", false, { root: true });
const snac = { color: 'error', msg: error.message, state: true };
context.commit("common/update_snackbar", snac, { root: true });
}
},
async getDetailDataPO(context, poID) {
try {
let params = {
token: one_token(),
poID: poID,
}
const resp = await api.getDataKontrakPoAset(params);
if (resp.status != 'OK') {
throw new Error(resp.message);
}
let formOrder = {
podate: resp.data.podate,
supplierID: resp.data.supplierID,
reference: resp.data.reference,
branchID: resp.data.branchID,
gudangID: resp.data.gudangID,
typepajak: resp.data.typepajak,
valuepajak: parseFloat(resp.data.valuepajak),
typediskon: resp.data.typediskon,
valuediskon: parseFloat(resp.data.valuediskon),
catatan: resp.data.catatan
};
let formKontrak = {
nama_kontrak: resp.data.contractName,
tanggal_kontrak: resp.data.contractDate,
tanggalAwal_kontrak: resp.data.contractStart,
tanggalAkhir_kontrak: resp.data.contractEnd,
durasi_cicilan: resp.data.contractDuration,
jumlah_cicilan: resp.data.installmentNumber,
tanggalBayar_cicilan: resp.data.installmentDate,
besarNilai_cicilan: parseFloat(resp.data.installmentPayAmount),
type_downpayment: resp.data.installmentDownPaymentType,
besarNilai_downpayment: parseFloat(resp.data.installmentDownPayment),
};
let summary = resp.data.summary;
let selected_request = resp.data.detail;
selected_request.forEach(item => {
item.SupplierPrice = parseFloat(item.SupplierPrice)
item.DiskonAmount = parseFloat(item.DiskonAmount)
});
context.dispatch('orderAsset/listingGudang', resp.data.branchID, { root: true });
context.commit('update_form_kontrak', formKontrak);
context.commit('orderAsset/update_form_order_asset', formOrder, { root: true });
context.commit('orderAsset/update_selected_request_asset', selected_request, { root: true });
context.commit('orderAsset/update_summary_order', summary, { root: true });
context.commit('common/update_selected_orderaset', resp.data, { root: true });
context.dispatch('orderAsset/recalculateOrderSummary', {}, { root: true });
context.commit('orderAsset/update_dialog_create_order', true, { root: true });
} catch (error) {
const snac = { color: 'error', msg: error.message, state: true };
context.commit("common/update_snackbar", snac, { root: true });
}
}
}
}

View File

@@ -1,3 +1,5 @@
import * as api from '../api/api.js';
export default {
namespaced: true,
state: {
@@ -8,13 +10,32 @@ export default {
supplierID: "",
reference: "",
branchID: "",
typepajak: "persen",
gudangID: "",
typepajak: "percent",
valuepajak: 0,
typediskon: "persen",
valuediskon: 0
typediskon: "percent",
valuediskon: 0,
catatan: ""
},
list_supplier: [],
list_cabang: []
list_cabang: [],
list_gudang: [],
/* item request */
dialog_select_asset: false,
requested_asset: {
records: [],
total: 0,
},
selected_request_asset: [],
summary_order: {
subtotal: 0,
diskon: 0,
pajak: 0,
downpayment: 0,
total_before_downpayment: 0,
total: 0
}
},
mutations: {
update_dialog_create_order(state, val) {
@@ -28,9 +49,176 @@ export default {
},
update_list_cabang(state, val) {
state.list_cabang = val
},
update_list_gudang(state, val) {
state.list_gudang = val
},
update_dialog_select_asset(state, val) {
state.dialog_select_asset = val
},
update_requested_asset(state, val) {
state.requested_asset = val
},
update_selected_request_asset(state, val) {
state.selected_request_asset = val
},
update_summary_order(state, val) {
state.summary_order = val
}
},
actions: {
async listingCabang(context) {
try {
let param = { token: one_token() }
const resp = await api.getListCabang(param);
if (resp.status != "OK") {
throw new Error(resp.message);
}
context.commit('update_list_cabang', resp.data);
} catch (e) {
const snac = { color: 'error', msg: e.message, state: true };
context.commit("common/update_snackbar", snac, { root: true });
}
},
async listingGudang(context, branchID) {
try {
let param = {
token: one_token(),
M_BranchID: branchID
}
const resp = await api.getListGudang(param);
if (resp.status != "OK") {
throw new Error(resp.message);
}
context.commit('update_list_gudang', resp.data);
} catch (e) {
const snac = { color: 'error', msg: e.message, state: true };
context.commit("common/update_snackbar", snac, { root: true });
}
},
async listingSupplier(context) {
try {
const params = { token: one_token() };
const resp = await api.getListSupplier(params);
if (resp.status != 'OK') {
throw new Error(resp.message);
}
context.commit('update_list_supplier', resp.data);
} catch (e) {
const snac = { color: 'error', msg: e.message, state: true };
context.commit("update_snackbar", snac, { root: true });
}
},
async searchItemRequest(context, keyword) {
try {
const form = context.state.form_order_asset;
const params = {
token: one_token(),
search: keyword,
branchID: form.branchID,
supplierID: form.supplierID
};
const resp = await api.searchRequestAset(params);
if (resp.status != 'OK') {
throw new Error(resp.message);
}
context.commit('update_requested_asset', resp.data)
} catch (e) {
const snac = { color: 'error', msg: e.message, state: true };
context.commit("update_snackbar", snac, { root: true });
}
},
async recalculateOrderSummary(context) {
const formOrder = context.state.form_order_asset;
const formKontrak = context.rootState.kontrakAsset.form_kontrak;
const items = JSON.parse(JSON.stringify(context.state.selected_request_asset));
const calculatedItems = items.map(item => {
const supplierPrice = parseCurrency(item.SupplierPrice);
const requestQty = item.detail.reduce((sum, detail) => {
return sum + parseCurrency(detail.RequestQty);
}, 0);
let itemDiscount = 0;
if (item.DiskonType == 'P') {
itemDiscount = supplierPrice * parseCurrency(item.DiskonAmount) / 100;
} else {
itemDiscount = parseCurrency(item.DiskonAmount);
}
const endPrice = Math.max(supplierPrice - itemDiscount, 0);
const tempTotal = requestQty * endPrice;
return {
...item,
RequestQty: requestQty,
EndPrice: endPrice,
TempTotal: tempTotal,
detail: item.detail.map(detail => ({
...detail,
SupplierPrice: supplierPrice
}))
};
});
const subtotal = calculatedItems.reduce((sum, item) => {
return sum + parseCurrency(item.TempTotal);
}, 0);
const diskon = calculateByType(
formOrder.typediskon,
formOrder.valuediskon,
subtotal
);
const subtotalAfterDiskon = Math.max(subtotal - diskon, 0);
const pajak = calculateByType(
formOrder.typepajak,
formOrder.valuepajak,
subtotalAfterDiskon
);
const totalBeforeDownpayment = subtotalAfterDiskon + pajak;
const downpayment = calculateByType(
formKontrak.type_downpayment,
formKontrak.besarNilai_downpayment,
totalBeforeDownpayment
);
const total = Math.max(totalBeforeDownpayment - downpayment, 0);
context.commit('update_selected_request_asset', calculatedItems);
context.commit('update_summary_order', {
subtotal: subtotal,
diskon: diskon,
pajak: pajak,
downpayment: downpayment,
total_before_downpayment: totalBeforeDownpayment,
total: total
});
}
}
}
function parseCurrency(value) {
let cleanValue = String(value || 0).replace(/\./g, '');
cleanValue = cleanValue.replace(',', '.');
return parseFloat(cleanValue) || 0;
}
function calculateByType(type, value, base) {
const amount = parseCurrency(value);
if (type == 'percent') {
return base * amount / 100;
}
return amount;
}

View File

@@ -1,179 +0,0 @@
import * as api from '../api/api.js';
export default {
namespaced: true,
state: {
/* common */
snackbar: {
color: 'success',
msg: '',
state: false
},
loading_process: false,
selected_orderaset: {},
/* main layout */
filterpo: {
startdate: moment(new Date()).format('YYYY-MM-DD'),
enddate: moment(new Date()).format('YYYY-MM-DD'),
status: 'All',
search: ''
},
list_status: ['All', 'Draft', 'Pending', 'Approved', 'Rejected', 'Completed'],
list_asetpo: {
records: [],
total: 0
},
currpage: 1,
/* form order aset */
dialog_form_orderaset: false,
list_supplier: [],
list_branch: [],
form_orderaset: {
podate: moment(new Date()).format('YYYY-MM-DD'),
supplierID: "",
reference: "",
branchcode: "",
typepajak: "persen",
valuepajak: 0,
typediskon: "persen",
valuediskon: 0
},
item_orderaset: [],
summary_orderaset: {
subtotal: 0,
diskon: 0,
pajak: 0,
total: 0
},
dialog_add_itemaset: false,
list_requestaset: {
records: [],
total: 0
},
/* delete order */
dialog_deleteorder: false,
/* attachment */
dialog_attachment: false,
prview_attachment: [],
},
mutations: {
/* common */
update_snackbar(state, val) {
state.snackbar = val
},
update_loading_process(state, val) {
state.loading_process = val
},
update_selected_orderaset(state, val) {
state.selected_orderaset = val
},
/* main layout */
update_filterpo(state, val) {
state.filterpo = val
},
update_list_status(state, val) {
state.list_status = val
},
update_list_asetpo(state, val) {
state.list_asetpo = val
},
update_currpage(state, val) {
state.currpage = val
},
/* form order aset */
update_dialog_form_orderaset(state, val) {
state.dialog_form_orderaset = val
},
update_list_supplier(state, val) {
state.list_supplier = val
},
update_list_branch(state, val) {
state.list_branch = val
},
update_form_orderaset(state, val) {
state.form_orderaset = val
},
update_item_orderaset(state, val) {
state.item_orderaset = val
},
update_summary_orderaset(state, val) {
state.summary_orderaset = val
},
update_dialog_add_itemaset(state, val) {
state.dialog_add_itemaset = val
},
update_list_requestaset(state, val) {
state.list_requestaset = val
},
/* delete order */
update_dialog_deleteorder(state, val) {
state.dialog_deleteorder = val
},
/* attachment */
update_dialog_attachment(state, val) {
state.dialog_attachment = val
},
update_prview_attachment(state, val) {
state.prview_attachment = val
}
},
actions: {
async lookupVendor(context) {
try {
const resp = await api.getListSupplier({token: one_token()});
if (resp.status != 'OK') {
throw new Error(resp.message);
} else {
context.commit('update_list_supplier', resp.data)
}
} catch (error) {
let snac = {color: 'error', msg: error.message, state: true}
context.commit('update_snackbar', snac)
}
},
async lookupCabang(context) {
try {
const resp = await api.getListCabang({token: one_token()});
if (resp.status != 'OK') {
throw new Error(resp.message);
}
context.commit('update_list_branch', resp.data)
} catch (error) {
let snac = {color: 'error', msg: error.message, state: true}
context.commit('update_snackbar', snac)
}
},
async lookupOrderRequest(context, keyword) {
try {
const form = context.state.form_orderaset
let param = {
token: one_token(),
branchcode: form.branchcode,
search: keyword,
currpage: 1,
supplierID: form.supplierID
}
const resp = await api.searchRequestAset(param)
if (resp.status != 'OK') {
throw new Error(resp.message);
}
context.commit('update_list_requestaset', resp.data)
} catch (error) {
let snac = {color: 'error', msg: error.message, state: true}
context.commit('update_snackbar', snac)
}
}
}
}