add modules folder based on s_menu

This commit is contained in:
2026-06-30 10:16:11 +07:00
parent 315b657ee3
commit a1aab09ac9
625 changed files with 192283 additions and 794 deletions

View File

@@ -0,0 +1,164 @@
const URL = "/one-api/mockup/masterdata/accounting/Beginingbalance";
export async function getPeriode(prm) {
try {
var resp = await axios.post(URL + '/getPeriode', prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function save(prm) {
try {
var resp = await axios.post(URL + '/save', prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function addData(prm) {
try {
var resp = await axios.post(URL + '/addData', prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function search(prm) {
try {
var resp = await axios.post(URL + '/search', prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function cek(prm) {
try {
var resp = await axios.post(URL + '/cek', prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function updateData(prm) {
try {
var resp = await axios.post(URL + '/updateData', prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function deleteData(prm) {
try {
var resp = await axios.post(URL + '/delete', prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function searchCoa(prm) {
try {
var resp = await axios.post(URL + '/searchCoa', prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function postData(prm) {
try {
var resp = await axios.post(URL + '/postData', prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}

View File

@@ -0,0 +1,347 @@
const URL = "/one-api/mockup/mcuoffline/";
export async function search(prm) {
try {
var resp = await axios.post(URL + 'preregister/search', prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function generatesetup(prm) {
try {
var resp = await axios.post(URL + 'preregister/generatesetup', prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function getsexreg(token) {
try {
var resp = await axios.post(URL + 'preregister/getsexreg',{token:token});
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function save(prm) {
try {
var resp = await axios.post(URL + 'preregister/save',prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function newpatient(prm) {
try {
var resp = await axios.post(URL + 'preregister/newpatient',prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function xdelete(prm) {
try {
var resp = await axios.post(URL + 'preregister/deletepatient',prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function getaddress(prm) {
try {
var resp = await axios.post(URL + 'preregister/getaddress',prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function searchcity(token,prm) {
try {
var resp = await axios.post(URL + 'preregister/searchcity',{token:token,search:prm});
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch(e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function getdistrict(token,prm) {
try {
var resp = await axios.post(URL + 'preregister/getdistrict',{id:prm.M_CityID,token:token});
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch(e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function getkelurahan(token,prm) {
try {
var resp = await axios.post(URL + 'preregister/getkelurahan',{token:token,id:prm.M_DistrictID});
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch(e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function savenewaddress(prm) {
try {
var resp = await axios.post(URL + 'preregister/savenewaddress',prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function saveeditaddress(prm) {
try {
var resp = await axios.post(URL + 'preregister/saveeditaddress',prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function deleteaddress(prm) {
try {
var resp = await axios.post(URL + 'preregister/deleteaddress',prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function searchdoctor(prm) {
try {
console.log('aye')
console.log(prm)
var resp = await axios.post(URL + 'preregister/searchdoctor',prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch(e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function searchcompany(prm) {
try {
var resp = await axios.post(URL + 'preregister/searchcompany',prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch(e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function getmou(prm) {
try {
var resp = await axios.post(URL + 'preregister/getmou',prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch(e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function savepreregister(prm) {
try {
var resp = await axios.post(URL + 'preregister/savepreregister',prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch(e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function gotoreg(prm) {
try {
var resp = await axios.post(URL + 'preregister/gotoreg',prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch(e) {
return {
status: "ERR",
message: e.message
};
}
}

View File

@@ -0,0 +1,293 @@
<template>
<div class="vue-csv-uploader">
<div class="form">
<div class="vue-csv-uploader-part-one">
<div class="form-check form-group csv-import-checkbox" v-if="headers === null">
<slot name="hasHeaders" :headers="hasHeaders" :toggle="toggleHasHeaders">
<input :class="checkboxClass" type="checkbox" :id="makeId('hasHeaders')" :value="hasHeaders" @change="toggleHasHeaders">
<label class="form-check-label" :for="makeId('hasHeaders')">
File Has Headers
</label>
</slot>
</div>
<div class="form-group csv-import-file">
<input ref="csv" type="file" @change.prevent="validFileMimeType" :class="inputClass" name="csv">
<slot name="error" v-if="showErrorMessage">
<div class="invalid-feedback d-block">
File type is invalid
</div>
</slot>
</div>
<div class="form-group">
<slot name="next" :load="load">
<button type="submit" :disabled="disabledNextButton" :class="buttonClass" @click.prevent="load">
{{ loadBtnText }}
</button>
</slot>
</div>
</div>
<div class="vue-csv-uploader-part-two">
<div class="vue-csv-mapping" v-if="sample">
<table :class="tableClass">
<slot name="thead">
<thead>
<tr>
<th>Field</th>
<th>CSV Column</th>
</tr>
</thead>
</slot>
<tbody>
<tr v-for="(field, key) in fieldsToMap" :key="key">
<td>{{ field.label }}</td>
<td>
<select :class="tableSelectClass" :name="`csv_uploader_map_${key}`" v-model="map[field.key]">
<option :value="null" v-if="canIgnore">Ignore</option>
<option v-for="(column, key) in firstRow" :key="key" :value="key">{{ column }}</option>
</select>
</td>
</tr>
</tbody>
</table>
<div class="form-group" v-if="url">
<slot name="submit" :submit="submit">
<input type="submit" :class="buttonClass" @click.prevent="submit" :value="submitBtnText">
</slot>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { drop, every, forEach, get, isArray, map, set } from 'lodash';
import axios from 'axios';
import Papa from 'papaparse';
import mimeTypes from "mime-types";
export default {
props: {
value: Array,
url: {
type: String
},
mapFields: {
required: true
},
callback: {
type: Function,
default: () => ({})
},
catch: {
type: Function,
default: () => ({})
},
finally: {
type: Function,
default: () => ({})
},
parseConfig: {
type: Object,
default() {
return {};
}
},
headers: {
default: null
},
loadBtnText: {
type: String,
default: "Next"
},
submitBtnText: {
type: String,
default: "Submit"
},
tableClass: {
type: String,
default: "table"
},
checkboxClass: {
type: String,
default: "form-check-input"
},
buttonClass: {
type: String,
default: "btn btn-primary"
},
inputClass: {
type: String,
default: "form-control-file"
},
validation: {
type: Boolean,
default: true,
},
fileMimeTypes: {
type: Array,
default: () => {
return ["text/csv", "text/x-csv", "application/vnd.ms-excel", "text/plain"];
}
},
tableSelectClass: {
type: String,
default: 'form-control'
},
canIgnore: {
type: Boolean,
default: false,
}
},
data: () => ({
form: {
csv: null,
},
fieldsToMap: [],
map: {},
hasHeaders: true,
csv: null,
sample: null,
isValidFileMimeType: false,
fileSelected: false
}),
created() {
this.hasHeaders = this.headers;
if (isArray(this.mapFields)) {
this.fieldsToMap = map(this.mapFields, (item) => {
return {
key: item,
label: item
};
});
} else {
this.fieldsToMap = map(this.mapFields, (label, key) => {
return {
key: key,
label: label
};
});
}
},
methods: {
submit() {
const _this = this;
this.form.csv = this.buildMappedCsv();
this.$emit('input', this.form.csv);
if (this.url) {
axios.post(this.url, this.form).then(response => {
_this.callback(response);
}).catch(response => {
_this.catch(response);
}).finally(response => {
_this.finally(response);
});
} else {
_this.callback(this.form.csv);
}
},
buildMappedCsv() {
const _this = this;
let csv = this.hasHeaders ? drop(this.csv) : this.csv;
return map(csv, (row) => {
let newRow = {};
forEach(_this.map, (column, field) => {
set(newRow, field, get(row, column));
});
return newRow;
});
},
validFileMimeType() {
let file = this.$refs.csv.files[0];
const mimeType = file.type === "" ? mimeTypes.lookup(file.name) : file.type;
if (file) {
this.fileSelected = true;
this.isValidFileMimeType = this.validation ? this.validateMimeType(mimeType) : true;
} else {
this.isValidFileMimeType = !this.validation;
this.fileSelected = false;
}
},
validateMimeType(type) {
return this.fileMimeTypes.indexOf(type) > -1;
},
load() {
const _this = this;
this.readFile((output) => {
_this.sample = get(Papa.parse(output, { preview: 2, skipEmptyLines: true }), "data");
_this.csv = get(Papa.parse(output, { skipEmptyLines: true }), "data");
});
},
readFile(callback) {
let file = this.$refs.csv.files[0];
if (file) {
let reader = new FileReader();
reader.readAsText(file, "UTF-8");
reader.onload = function (evt) {
callback(evt.target.result);
};
reader.onerror = function () {
};
}
},
toggleHasHeaders() {
this.hasHeaders = !this.hasHeaders;
},
makeId(id) {
return `${id}${this._uid}`;
}
},
watch: {
map: {
deep: true,
handler: function (newVal) {
if (!this.url) {
let hasAllKeys = Array.isArray(this.mapFields) ? every(this.mapFields, function (item) {
return newVal.hasOwnProperty(item);
}) : every(this.mapFields, function (item, key) {
return newVal.hasOwnProperty(key);
});
if (hasAllKeys) {
this.submit();
}
}
}
},
sample(newVal, oldVal) {
if(newVal !== null){
this.fieldsToMap.forEach(field => {
newVal[0].forEach((columnName, index) => {
if(field.key === columnName){
this.map[field.key] = index;
}
});
});
}
}
},
computed: {
firstRow() {
return get(this, "sample.0");
},
showErrorMessage() {
return this.fileSelected && !this.isValidFileMimeType;
},
disabledNextButton() {
return !this.isValidFileMimeType;
}
},
};
</script>

View File

@@ -0,0 +1,856 @@
<template>
<div style="width: 100%;" class="">
<v-snackbar
:color="snackbar.color"
v-model="snackbar.state"
:timeout="5000"
top
>
{{ snackbar.msg }}
<v-btn flat @click="snackbar.state = false">
Close
</v-btn>
</v-snackbar>
<v-dialog v-model="dialogAdd" persistent width="500">
<v-card>
<v-card-title class="headline grey lighten-2" primary-title>
ADD BEGINNING BALANCE
</v-card-title>
<v-card-text>
<v-autocomplete
:search-input.sync="searchCoa"
v-model="selectedCoa"
:items="coaList"
:loading="loadingAutocomplete"
hide-no-data
hide-selected
item-text="display"
label="COA"
placeholder="Start typing desc /number"
outline
return-object
></v-autocomplete>
<v-text-field
type="number"
v-model="debit"
label="Debit"
placeholder="Debit"
outline
></v-text-field>
<v-text-field
type="number"
v-model="credit"
label="Credit"
placeholder="Credit"
outline
></v-text-field>
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn
color="error"
:loading="loading"
:disabled="loading"
flat
@click="dialogAdd = false"
>
Cancel
</v-btn>
<v-btn
color="primary"
:loading="loading"
:disabled="loading"
flat
@click="addBegginingBalance()"
>
Simpan
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
<v-dialog v-model="dialogImport" persistent width="500">
<v-card>
<v-card-title class="headline grey lighten-2" primary-title>
UPLOAD FILE BEGINNING BALANCE
</v-card-title>
<v-card-text>
<input
accept=".xlsx"
type="file"
id="csv_file"
name="csv_file"
class="form-control"
:disabled="loadingCsv || loading"
@input="loadCSV($event)"
/>
<div v-if="loadingCsv">
<v-progress-circular
indeterminate
v-if="loadingCsv"
color="primary"
></v-progress-circular>
load file
</div>
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn
color="error"
:loading="loading || loadingCsv"
:disabled="loading || loadingCsv"
flat
@click="resetInputFile()"
>
Cancel
</v-btn>
<v-btn
color="primary"
:loading="loading || loadingCsv"
:disabled="loading || loadingCsv"
flat
@click="upload()"
>
Upload
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
<v-dialog v-model="dialogEdit" persistent width="500">
<v-card>
<v-card-title class="headline grey lighten-2" primary-title>
{{ selectedData.keterangan }}
</v-card-title>
<v-card-text>
<v-text-field
readonly
v-model="selectedData.number"
label="No. Account"
placeholder="No. Account"
outline
></v-text-field>
<v-text-field
type="number"
v-model="debit"
label="Debit"
placeholder="Debit"
outline
></v-text-field>
<v-text-field
type="number"
v-model="credit"
label="Credit"
placeholder="Credit"
outline
></v-text-field>
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn
color="error"
:loading="loading"
:disabled="loading"
flat
@click="dialogEdit = false"
>
Tutup
</v-btn>
<v-btn
color="primary"
:loading="loading"
:disabled="loading"
flat
@click="editData()"
>
Simpan
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
<v-toolbar dark color="primary">
<v-toolbar-title class="white--text">BEGINNING BALANCE</v-toolbar-title>
<v-spacer></v-spacer>
<v-btn
v-if="btnUpload && status==='N'"
@click="dialogImport = true"
flat
icon
color="white"
>
<v-icon v-if="btnUpload">
file_upload
</v-icon>
</v-btn>
<v-btn
v-if="btnUpload && status==='N'"
@click="openDialogAdd()"
flat
icon
color="white"
>
<v-icon>add_box</v-icon>
</v-btn>
<v-btn
@click="postData()"
v-if="btnUpload && status==='N' && data.length >0"
color="orange"
>POST DATA</v-btn
>
</v-toolbar>
<v-card class="pa-2">
<v-autocomplete
v-model="selectedPeriode"
:items="periodeList"
outline
hide-details
color="blue"
label="Periode"
item-text="name"
return-object
>
<template v-slot:item="data">
<template>
<v-list-tile-content>
<v-list-tile-title v-html="data.item.name"></v-list-tile-title>
<v-list-tile-sub-title
v-html="data.item.periode"
></v-list-tile-sub-title>
</v-list-tile-content>
</template>
</template>
</v-autocomplete>
</v-card>
<v-card class="pa-2 mt-2">
<v-layout align-center justify-space-between row fill-height class="mb-2">
<div style="width: 300px;">
<v-text-field
v-model="searchTable"
prepend-icon="search"
label="cari"
single-line
hide-details
></v-text-field>
</div>
<div class="pa-1">
Download template
<v-btn @click="download()" flat icon color="primary">
<v-icon class="">
file_download
</v-icon>
</v-btn>
<!-- <v-spacer></v-spacer> -->
</div>
</v-layout>
<div style="height: 54vh; overflow-y: scroll;">
<v-data-table
:headers="headers"
hide-actions
:loading="loading"
:items="data"
class="elevation-1"
:search="searchTable"
:custom-filter="filterItemsObj"
>
<!-- :filter="filterItems" -->
<template v-slot:items="props">
<tr>
<td>{{ props.item.number }}</td>
<td>{{ props.item.keterangan }}</td>
<td>
<div v-if="props.item.type ==='DB'">
{{ formatCurrency(props.item.value) }}
</div>
<div v-else>
Rp. 0,00
</div>
</td>
<td>
<div v-if="props.item.type ==='CR'">
{{ formatCurrency(props.item.value) }}
</div>
<div v-else>
Rp. 0,00
</div>
</td>
<td class="justify-center layout px-0">
<v-icon
v-if="status==='N'"
small
class="mr-2"
@click="openDialogEdit(props.item)"
>
edit
</v-icon>
<v-icon
v-if="status==='N'"
small
@click="deleteData(props.item)"
>
delete
</v-icon>
</td>
</tr>
</template>
<!-- <template v-slot:footer>
<tr>
<td colspan="2" class="font-weight-bold">Total</td>
<td class="font-weight-bold">
{{ formatCurrency(summary.debit) }}
</td>
<td class="font-weight-bold">
{{ formatCurrency(summary.credit) }}
</td>
</tr>
<tr>
<td colspan="3" class="font-weight-bold">Balance</td>
<td>
<div class="d-flex text-right font-weight-bold">
<v-spacer></v-spacer> {{ formatCurrency(summary.balance) }}
</div>
</td>
</tr>
</template> -->
</v-data-table>
</div>
<v-divider></v-divider>
<v-data-table
:headers="headers"
hide-actions
:loading="loading"
hide-headers
:items="data"
class="elevation-1"
>
<template v-slot:items="props">
<tr></tr>
</template>
<template v-slot:footer>
<tr>
<td width="50%" class="font-weight-bold">Total</td>
<td width="20%" class="font-weight-bold">
{{ formatCurrency(summary.debit) }}
</td>
<td width="20%" class="font-weight-bold">
{{ formatCurrency(summary.credit) }}
</td>
<td width="10%" class="font-weight-bold"></td>
</tr>
<tr>
<td width="70%" colspan="2" class="font-weight-bold">Balance</td>
<td width="20%">
<div class="d-flex text-right font-weight-bold">
<v-spacer></v-spacer> {{ formatCurrency(summary.balance) }}
</div>
</td>
<td width="10%" class="font-weight-bold"></td>
</tr>
</template>
</v-data-table>
</v-card>
</div>
</template>
<style scoped></style>
<script>
module.exports = {
mounted() {
// this.formatCurrency(10000);
this.$store.dispatch("balance/getPeriode");
this.$store.dispatch("balance/search");
},
data: () => ({
loadingCsv: false,
search_city: "",
oldlabel: "",
selectedData: {},
debit: 0,
credit: 0,
btnUpload: false,
searchTable: "",
headers: [
{
text: "NO. ACCOUNT",
align: "left",
sortable: false,
value: "action",
width: "10%",
class: "pa-2 pl-2 blue lighten-3 white--text",
},
{
text: "KETERANGAN",
align: "left",
sortable: false,
value: "mr",
width: "40%",
class: "pa-2 blue lighten-3 white--text",
},
{
text: "DEBIT",
align: "left",
sortable: false,
value: "lab",
width: "20%",
class: "pa-2 blue lighten-3 white--text",
},
{
text: "KREDIT",
align: "left",
sortable: false,
value: "lab",
width: "20%",
class: "pa-2 blue lighten-3 white--text",
},
{
text: "ACTION",
align: "left",
sortable: false,
value: "lab",
width: "10%",
class: "pa-2 blue lighten-3 white--text",
},
],
}),
computed: {
selectedPeriode: {
get() {
return this.$store.state.balance.selectedPeriode;
},
set(val) {
this.$store.commit("balance/update_selectedPeriode", val);
},
},
snackbar: {
get() {
return this.$store.state.balance.snackbar;
},
set(val) {
this.$store.commit("balance/update_snackbar", val);
},
},
status: {
get() {
return this.$store.state.balance.status;
},
set(val) {
this.$store.commit("balance/update_status", val);
},
},
data: {
get() {
return this.$store.state.balance.data;
},
set(val) {
this.$store.commit("balance/update_data", val);
},
},
dialogEdit: {
get() {
return this.$store.state.balance.dialogEdit;
},
set(val) {
this.$store.commit("balance/update_dialogEdit", val);
},
},
dialogImport: {
get() {
return this.$store.state.balance.dialogImport;
},
set(val) {
this.$store.commit("balance/update_dialogImport", val);
},
},
dataUpload: {
get() {
return this.$store.state.balance.dataUpload;
},
set(val) {
this.$store.commit("balance/update_dataUpload", val);
},
},
loading: {
get() {
return this.$store.state.balance.loading;
},
set(val) {
this.$store.commit("balance/update_loading", val);
},
},
loadingAutocomplete: {
get() {
return this.$store.state.balance.loadingAutocomplete;
},
set(val) {
this.$store.commit("balance/update_loadingAutocomplete", val);
},
},
selectedCoa: {
get() {
return this.$store.state.balance.selectedCoa;
},
set(val) {
this.$store.commit("balance/update_selectedCoa", val);
},
},
searchCoa: {
get() {
return this.$store.state.balance.searchCoa;
},
set(val) {
this.$store.commit("balance/update_searchCoa", val);
},
},
dialogAdd: {
get() {
return this.$store.state.balance.dialogAdd;
},
set(val) {
this.$store.commit("balance/update_dialogAdd", val);
},
},
periodeList() {
return this.$store.state.balance.periodeList;
},
summary() {
return this.$store.state.balance.summary;
},
coaList() {
return this.$store.state.balance.coaList;
},
},
methods: {
postData() {
if (parseInt(this.summary.balance) !== 0) {
alert("Balance tidak sama dengan 0, tidak bisa post data !!");
return;
}
let cek = confirm(
"Apakah anda yakin konfirmasi data beginning balance yang sudah ada ? \n\n *setelah post/konfirmasi data tidak bisa diedit lagi"
);
if (cek) {
this.$store.dispatch("balance/postData");
}
},
filterItems(val, search) {
return (
val.keterangan.includes(search.toLowerCase()) ||
val.number.includes(search.toLowerCase())
);
},
filterItemsObj(items, search, filterBawaan) {
const result = items.filter(
(e) =>
e.keterangan.toLowerCase().includes(search.toLowerCase()) ||
e.number.toLowerCase().includes(search.toLowerCase())
);
return result;
},
download() {
// window.open("/one-api/mockup/cpone-nonlab-upload-document/patient/downloadfile/" + name, '_self')
// window.location = "/one-api/mockup/cpone-nonlab-upload-document/patient/downloadfile/" + name;
// `/one-api/mockup/cpone-nonlab-upload-document/patient/downloadfile/${name}`
fetch(
"/birt/run?__report=report/one/acc/sp_rpt_acc_002.rptdesign&__format=xlsx&username=admin"
)
.then((response) => {
if (!response.ok) throw new Error("Network response was not ok");
return response.blob();
})
.then((blob) => {
const url = window.URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.setAttribute("download", "Template_beginning_balance");
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
})
.catch((error) => {
console.error("Error downloading file:", error);
});
},
addBegginingBalance() {
this.loading = true;
let prm = {
data: [
{
Number: this.selectedCoa.number,
Keterangan: this.selectedCoa.keterangan,
Debit: this.debit,
Kredit: this.credit,
},
],
};
this.$store.dispatch("balance/addData", prm);
},
openDialogAdd() {
this.selectedCoa = {};
this.debit = 0;
this.credit = 0;
this.searchCoa = "";
this.dialogAdd = true;
},
isObjectEmpty(val) {
let obj = val;
return Object.keys(obj).length === 0 && obj.constructor === Object;
},
isPeriodeEmpty() {
return Object.keys(this.selectedPeriode).length === 0;
},
openDialogEdit(val) {
if (this.loading) {
return;
}
if (this.status == "P") {
return;
}
this.selectedData = val;
if (val.type == "DB") {
this.debit = val.value;
this.credit = 0;
}
if (val.type == "CR") {
this.credit = val.value;
this.debit = 0;
}
this.dialogEdit = true;
},
editData() {
// debugger;
if (this.loading) {
return;
}
if (this.status == "P") {
return;
}
let type = "DB";
let value = 0;
if (
this.debit.toString().trim() === "" &&
this.credit.toString().trim() === ""
) {
alert("Debit dan kredit tidak boleh kosong");
return;
}
if (parseFloat(this.debit) > 0 && parseFloat(this.credit) > 0) {
alert("Debit dan kredit tidak boleh lebih besar dari 0");
return;
}
if (parseFloat(this.debit) < 0 && parseFloat(this.credit) < 0) {
alert("Debit dan kredit tidak boleh kurang dari 0");
return;
}
if (parseFloat(this.debit) > 0 && parseFloat(this.credit) === 0) {
type = "DB";
}
if (parseFloat(this.debit) === 0 && parseFloat(this.credit) > 0) {
type = "CR";
}
if (type == "DB") {
value = this.debit;
}
if (type == "CR") {
value = this.credit;
}
let prm = {
data: {
id: this.selectedData.id,
type: type,
value: value,
},
};
this.$store.dispatch("balance/updateData", prm);
console.log(prm);
},
formatCurrency(val) {
// Format the price above to USD using the locale, style, and currency.
let price = parseFloat(val);
let USDollar = new Intl.NumberFormat("id-ID", {
style: "currency",
currency: "IDR",
});
// console.log(
// `The formated version of ${price} is ${USDollar.format(price)}`
// );
return `${USDollar.format(price)}`;
},
loadCSV(e) {
this.loadingCsv = true;
// debugger;
var vm = this;
var files = e.target.files,
f = files[0];
var reader = new FileReader();
let error = [];
reader.onload = function (e) {
var data = new Uint8Array(e.target.result);
var workbook = XLSX.read(data, {
type: "array",
cellText: true,
cellDates: true,
});
let sheetName = workbook.SheetNames[0];
/* DO SOMETHING WITH workbook HERE */
console.log(workbook);
let worksheet = workbook.Sheets[sheetName];
// console.log(XLSX.utils.sheet_to_json(worksheet));
//var xdata = XLSX.utils.sheet_to_json(worksheet,{ raw:false, dateNF: 'FMT 22'})
var data_json = [];
// console.log(xdata)
var date_data = XLSX.utils.sheet_to_json(worksheet, {
raw: false,
dateNF: "22",
});
var ktp_data = XLSX.utils.sheet_to_json(worksheet, {
cellText: true,
});
//console.log(zdata)
date_data.forEach(function (entry, iidx) {
if (entry.Number === undefined) {
error.push("Kolom Number tidak ditemukan ");
}
if (entry.Keterangan === undefined) {
error.push("Kolom Keterangan tidak ditemukan ");
}
if (entry.Debit === undefined) {
error.push("Debit tidak ditemukan / kosong");
}
if (entry.Kredit === undefined) {
error.push("Kredit tidak ditemukan /kosong");
}
if (entry.Number === "" || entry.Number === undefined) {
error.push("No. Account/Number tidak boleh kosong ");
}
if (entry.Keterangan === "" || entry.Keterangan === undefined) {
error.push("Keterangan tidak boleh kosong ");
}
if (entry.Debit === "") {
error.push("Debit tidak boleh kosong ");
}
if (entry.Kredit === "") {
error.push("Kredit tidak boleh kosong ");
}
if (parseFloat(entry.Debit) > 0 && parseFloat(entry.Kredit) > 0) {
error.push(
entry.Number + " Kredit dan debit jumlahnya lebih besar dari 0 "
);
}
data_json.push(entry);
});
// var prm = {
// xid: vm.$store.state.patient.data_setup.McuOfflinePrepareID,
// data: data_json,
// };
console.log(data_json);
console.log(error);
if (error.length > 0) {
let msg = error.join(",\n");
alert(msg);
vm.loadingCsv = false;
document.getElementById("csv_file").value = null;
return;
}
console.log(data_json);
let prm = {
data: data_json,
};
vm.dataUpload = data_json;
// setTimeout(() => {
// console.log("Bam! 5 seconds have passed.");
// }, 5000);
vm.loadingCsv = false;
// vm.$store.dispatch("balance/save", prm);
// console.log(data_json);
//XLSX.utils.sheet_to_json(ws, {dateNF:"YYYY-MM-DD"})
// vm.$store.dispatch("patient/savecsv", prm);
};
reader.readAsArrayBuffer(f);
},
resetInputFile() {
document.getElementById("csv_file").value = null;
this.dialogImport = false;
},
upload() {
// this.loading = true;
let prm = {
data: this.dataUpload,
};
if (this.data.length > 0) {
if (
confirm(
"Apakah anda yakin import document ? \n *import document akan menghapus data yang sudah ada"
)
) {
this.$store.dispatch("balance/save", prm);
}
} else {
this.$store.dispatch("balance/save", prm);
}
},
deleteData(val) {
console.log(val);
let cek = confirm(
"Apakah anda yakin untuk menghapus data berikut " +
val.number +
" " +
val.keterangan
);
if (cek) {
let prm = {
id: val.id,
};
this.$store.dispatch("balance/deleteData", prm);
}
},
},
watch: {
selectedPeriode(val, old) {
if (Object.keys(val).length === 0) {
this.btnUpload = false;
} else {
this.btnUpload = true;
}
},
searchCoa(val, old) {
if (val == old) return;
if (!val) return;
if (val.length < 1) return;
this.$store.dispatch("balance/searchCoa");
},
search_city(val, old) {
if (val == old) return;
if (!val) return;
if (val.length < 1) return;
if (this.$store.state.patient.update_autocomplete_status == 1) return;
this.thr_search_city();
},
},
};
</script>

View File

@@ -0,0 +1,397 @@
<template>
<v-layout v-if="xact !== 'new'" column >
<v-dialog v-model="dialogconfirmationdeleteaddr" persistent max-width="290">
<v-card>
<v-card-title
dark
class="headline error pt-2 pb-2"
primary-title
style="color:white"
>
<h4 dark>Konfirmasi</h4>
</v-card-title>
<v-card-text>
{{msgconfirmationdeleteaddr}}
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn small v-if="!checkError('deleteutama')" color="error darken-1 text-sm-left" flat @click="doDeleteAddr()">Hapus</v-btn>
<v-btn small color="primary darken-1 text-sm-right" flat @click="dialogconfirmationdeleteaddr = false">Batal</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
<v-dialog v-model="dialogformaddress" persistent max-width="650">
<v-card>
<v-card-title>
<span class="headline">Form Alamat Pasien</span>
</v-card-title>
<v-card-text class="pt-0 pb-0">
<v-layout wrap>
<v-flex xs12>
<v-text-field v-model="labeladdress" label="Label"></v-text-field>
<p v-if="checkError('requiredlabel')" class="error pl-2 pr-2" style="color:#fff">Jangan kosong dong</p>
<p v-if="checkError('readonlyutama')" class="error pl-2 pr-2" style="color:#fff">Biarkan jadi yang utama</p>
</v-flex>
<v-flex xs12>
<v-layout row>
<v-flex xs4 pa-1>
<v-autocomplete
label="Kota"
v-model="cityaddress"
:items="xcities"
:search-input.sync="search_city"
auto-select-first
no-filter
item-text="M_CityName"
return-object
:loading="isLoading"
no-data-text="Pilih Kota"
>
<template
slot="item"
slot-scope="{ item }"
>
<v-list-tile-content>
<v-list-tile-title v-text="item.M_CityName"></v-list-tile-title>
</v-list-tile-content>
</template>
</v-autocomplete>
<p v-if="checkError('requiredcity')" class="error pl-2 pr-2" style="color:#fff">Jangan kosong dong</p>
</v-flex>
<v-flex xs4 pa-1>
<v-select
item-text="M_DistrictName"
return-object
:items="xdistricts"
v-model="districtaddress"
label="Kecamatan*"
></v-select>
<p v-if="checkError('requireddistrict')" class="error pl-2 pr-2" style="color:#fff">Jangan kosong dong</p>
</v-flex>
<v-flex xs4 pa-1>
<v-select
item-text="M_KelurahanName"
return-object
:items="xkelurahans"
v-model="kelurahanaddress"
label="Kelurahan / Desa*"
></v-select>
<p v-if="checkError('requiredkelurahan')" class="error pl-2 pr-2" style="color:#fff">Jangan kosong dong</p>
</v-flex>
</v-layout>
</v-flex>
<v-flex xs12>
<v-textarea
box
label="Alamat Lengkap"
v-model="descriptionaddress"
></v-textarea>
<p v-if="checkError('requireddescription')" class="error pl-2 pr-2" style="color:#fff">Jangan kosong dong</p>
</v-flex>
</v-layout>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="blue darken-1" flat @click="dialogformaddress = false">Tutup</v-btn>
<v-btn v-if="xactaddr === 'new'" color="blue darken-1" flat @click="saveNewAddress()">Simpan</v-btn>
<v-btn v-if="xactaddr === 'edit'" color="blue darken-1" flat @click="saveEditAddress()">Simpan</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
<v-card>
<v-layout row>
<v-flex xs12>
<v-subheader red--text text--lighten-1> ALAMAT PASIEN
<v-flex text-md-right>
<v-btn @click="createNewAddress()" small color="info">Baru</v-btn>
</v-flex>
</v-subheader>
<v-divider></v-divider>
<v-layout row wrap>
<v-flex xs12 pa-2>
<v-data-table
:headers="headers"
:items="xaddresses"
:loading="isLoading"
hide-actions class="elevation-1">
<template slot="items" slot-scope="props">
<td class="text-xs-center pa-2">
<v-icon color="error" @click="deleteAddress(props.item)">delete</v-icon>
<v-icon class="ml-3" color="primary" @click="editAddress(props.item)">edit</v-icon>
</td>
<td class="text-xs-left pa-2">{{ props.item.M_PatientAddressNote}}</td>
<td class="text-xs-left pa-2">{{ props.item.M_PatientAddressDescription}}</td>
</template>
</v-data-table>
</v-flex>
</v-layout>
</v-flex>
</v-flex>
</v-card>
</v-layout>
</template>
<style scoped>
</style>
<script>
module.exports = {
data: () => ({
search_city:'',
oldlabel:'',
headers: [
{
text: "AKSI",
align: "center",
sortable: false,
value: "action",
width: "10%",
class: "pa-1 blue lighten-3 white--text"
},
{
text: "LABEL",
align: "left",
sortable: false,
value: "mr",
width: "20%",
class: "pa-1 blue lighten-3 white--text"
},
{
text: "ALAMAT",
align: "left",
sortable: false,
value: "lab",
width: "40%",
class: "pa-1 blue lighten-3 white--text"
}
]
}),
computed: {
dialogconfirmationdeleteaddr:{
get() {
return this.$store.state.patient.dialog_confirmation_delete_addr
},
set(val) {
this.$store.commit("patient/update_dialog_confirmation_delete_addr",val)
}
},
msgconfirmationdeleteaddr(){
return this.$store.state.patient.msg_confirmation_delete_addr
},
xact() {
return this.$store.state.patient.act
},
xactaddr() {
return this.$store.state.patient.act_addr
},
dialogformaddress:{
get() {
return this.$store.state.patient.dialog_form_address
},
set(val) {
this.$store.commit("patient/update_dialog_form_address",val)
}
},
isLoading() {
return this.$store.state.patient.search_status == 1
},
xaddresses(p) {
return this.$store.state.patient.addresses
},
xcities(){
return this.$store.state.patient.cities
},
labeladdress:{
get() {
return this.$store.state.patient.label_address
},
set(val) {
this.$store.commit("patient/update_label_address",val)
}
},
cityaddress:{
get() {
return this.$store.state.patient.city_address
},
set(val) {
this.$store.commit("patient/update_city_address",val)
this.$store.dispatch("patient/getdistrict",this.$store.state.patient.city_address)
}
},
xdistricts(){
return this.$store.state.patient.districts
},
districtaddress:{
get() {
return this.$store.state.patient.district_address
},
set(val) {
this.$store.commit("patient/update_district_address",val)
this.$store.dispatch("patient/getkelurahan",this.$store.state.patient.district_address)
}
},
xkelurahans(){
return this.$store.state.patient.kelurahans
},
kelurahanaddress:{
get() {
return this.$store.state.patient.kelurahan_address
},
set(val) {
this.$store.commit("patient/update_kelurahan_address",val)
}
},
descriptionaddress:{
get() {
return this.$store.state.patient.description_address
},
set(val) {
this.$store.commit("patient/update_description_address",val)
}
},
},
methods : {
createNewAddress(){
this.$store.commit("patient/update_act_addr",'new')
this.search_city = ''
this.labeladdress = ''
this.$store.commit("patient/update_cities",[])
this.cityaddress = {}
this.$store.commit("patient/update_districts",[])
this.districtaddress = {}
this.$store.commit("patient/update_kelurahans",[])
this.kelurahanaddress = {}
this.descriptionaddress = ''
this.$store.commit("patient/update_dialog_form_address",true)
},
thr_search_city: _.debounce( function () {
this.$store.dispatch("patient/searchcity",this.search_city)
},2000),
checkError(value){
var errors = this.$store.state.patient.errors
if(errors.includes(value)){
return true
}
else{
return false
}
},
saveNewAddress(){
this.$store.commit("patient/update_errors",[])
var errors = this.$store.state.patient.errors
if(this.labeladdress === ''){
errors.push("requiredlabel")
}
if(_.isEmpty(this.cityaddress)){
errors.push("requiredcity")
}
if(_.isEmpty(this.districtaddress)){
errors.push("requireddistrict")
}
if(_.isEmpty(this.kelurahanaddress)){
errors.push("requiredkelurahan")
}
if(_.isEmpty(this.descriptionaddress)){
errors.push("requireddescription")
}
if(errors.length === 0){
var prm = {}
prm.M_PatientAddressM_PatientID = this.$store.state.patient.selected_patient.M_PatientID
prm.M_PatientName = this.$store.state.patient.selected_patient.M_PatientName
prm.M_PatientAddressNote = this.labeladdress
prm.M_PatientAddressDescription = this.descriptionaddress
prm.M_PatientAddressM_KelurahanID = this.kelurahanaddress.M_KelurahanID
this.$store.dispatch("patient/savenewaddress",prm)
}
},
editAddress(value){
this.$store.commit("patient/update_act_addr",'edit')
this.$store.commit("patient/update_x_addr_id",value.M_PatientAddressID)
this.labeladdress = value.M_PatientAddressNote
this.oldlabel = value.M_PatientAddressNote
this.$store.commit("patient/update_cities",[{M_CityID:value.M_CityID,M_CityName:value.M_CityName}])
this.cityaddress = {M_CityID:value.M_CityID,M_CityName:value.M_CityName}
this.$store.commit("patient/update_districts",[{M_DistrictID:value.M_DistrictID,M_DistrictName:value.M_DistrictName}])
this.districtaddress = {M_DistrictID:value.M_DistrictID,M_DistrictName:value.M_DistrictName}
this.$store.commit("patient/update_kelurahans",[{M_KelurahanID:value.M_PatientAddressM_KelurahanID,M_KelurahanName:value.M_KelurahanName}])
this.kelurahanaddress = {M_KelurahanID:value.M_PatientAddressM_KelurahanID,M_KelurahanName:value.M_KelurahanName}
this.descriptionaddress = value.M_PatientAddressDescription
this.$store.commit("patient/update_dialog_form_address",true)
},
saveEditAddress(){
this.$store.commit("patient/update_errors",[])
var errors = this.$store.state.patient.errors
if(this.labeladdress === ''){
errors.push("requiredlabel")
}
if(this.oldlabel.toLowerCase() === 'utama' && this.labeladdress.toLowerCase() !== 'utama'){
errors.push("readonlyutama")
}
if(_.isEmpty(this.cityaddress)){
errors.push("requiredcity")
}
if(_.isEmpty(this.districtaddress)){
errors.push("requireddistrict")
}
if(_.isEmpty(this.kelurahanaddress)){
errors.push("requiredkelurahan")
}
if(_.isEmpty(this.descriptionaddress)){
errors.push("requireddescription")
}
if(errors.length === 0){
var prm = {}
prm.M_PatientAddressID = this.$store.state.patient.x_addr_id
prm.M_PatientAddressM_PatientID = this.$store.state.patient.selected_patient.M_PatientID
prm.M_PatientName = this.$store.state.patient.selected_patient.M_PatientName
prm.M_PatientAddressNote = this.labeladdress
prm.M_PatientAddressDescription = this.descriptionaddress
prm.M_PatientAddressM_KelurahanID = this.kelurahanaddress.M_KelurahanID
this.$store.dispatch("patient/saveeditaddress",prm)
}
},
deleteAddress(value){
this.$store.commit("patient/update_act_addr",'delete')
this.$store.commit("patient/update_x_addr_id",value.M_PatientAddressID)
this.$store.commit("patient/update_errors",[])
this.oldlabel = value.M_PatientAddressNote
var errors = this.$store.state.patient.errors
if(value.M_PatientAddressNote.toLowerCase() === 'utama'){
errors.push("deleteutama")
}
var msg = ''
if(errors.includes("deleteutama")){
msg = "Biarkan yang utama tetap ada"
}
else{
msg = "Yakin, akan menghapus data alamat pasien "+value.M_PatientAddressNote+" ?"
}
this.$store.commit("patient/update_msg_confirmation_delete_addr",msg)
this.$store.commit("patient/update_dialog_confirmation_delete_addr",true)
},
doDeleteAddr(){
var prm = {}
prm.M_PatientAddressID = this.$store.state.patient.x_addr_id
prm.M_PatientAddressM_PatientID = this.$store.state.patient.selected_patient.M_PatientID
prm.M_PatientName = this.$store.state.patient.selected_patient.M_PatientName
prm.M_PatientAddressNote = this.oldlabel
this.$store.dispatch("patient/deleteaddress",prm)
}
},
watch: {
search_city(val,old) {
if (val == old ) return
if (! val) return
if (val.length < 1 ) return
if (this.$store.state.patient.update_autocomplete_status == 1 ) return
this.thr_search_city()
}
}
}
</script>

View File

@@ -0,0 +1,183 @@
<template>
<v-layout class="mb-2" column>
<v-card >
<v-card-title style="background:#57c492">
<v-layout row>
<v-flex xs12>
<v-text-field
color="teal"
label="Cari pasien"
v-model="xsearch"
@keyup.enter="searchPatientTable()"
outline
hide-details
></v-text-field>
</v-flex>
</v-layout>
</v-card-title>
<v-card-text>
<v-data-table
:headers="headers"
:items="patients"
hide-actions
class="elevation-1"
>
<template v-slot:items="props">
<td class="text-xs-left">{{ props.item.Mcu_PreregisterDetailsPatientName }}</td>
<td class="text-xs-center">{{ props.item.dob }}</td>
<td class="text-xs-center">{{ props.item.Mcu_PreregisterDetailsM_SexCode }}</td>
<td class="text-xs-center">{{ props.item.Mcu_PreregisterDetailsNIK }}</td>
<td class="text-xs-left">{{ props.item.Mcu_PreregisterDetailsJabatan }}</td>
<td class="text-xs-center">
<v-btn small dark v-if="props.item.Mcu_PreregisterDetailsFlagAction === 'N'" @click="goToRegister(props.item)" color="#03989e">DAFTARKAN</v-btn>
<v-btn small dark v-if="props.item.Mcu_PreregisterDetailsFlagAction === 'R'" color="#57c492">SEDANG DIPROSES</v-btn>
<v-btn small disabled v-if="props.item.Mcu_PreregisterDetailsFlagAction === 'S'" color="grey">TELAH SELESAI</v-btn>
</td>
</template>
</v-data-table>
</v-card-text>
<v-card-actions>
<v-pagination style="margin-top:10px;margin-bottom:10px"
color="#57c492"
:total-visible="15"
v-model="curr_page"
:length="xtotal_page">
</v-pagination>
</v-card-actions>
</v-card>
</v-layout>
</template>
<style scoped>
table,
td,
th {
border: 0px solid #ddd;
text-align: left;
}
table {
border-collapse: collapse;
width: 100%;
}
th,
td {
padding-top: 5px;
padding-bottom: 5px;
padding-left: 8px;
padding-right: 5px;
}
.mini-input .v-input {
margin-top: 0px;
}
.mini-input .v-input,
.mini-input .v-input--selection-controls,
.mini-input .v-input__slot {
margin-top: 0px;
margin-bottom: 0px;
margin-left: 3px;
}
.mini-input .v-messages {
min-height: 0px;
}
input.fhm-input {
border: 1px solid black;
border-radius: 2px;
-webkit-box-shadow: inset 0 0 2px rgba(0, 0, 0, 0.1),
0 0 4px rgba(0, 0, 0, 0.1);
-moz-box-shadow: inset 0 0 2px rgba(0, 0, 0, 0.1),
0 0 4px rgba(0, 0, 0, 0.1);
box-shadow: inset 0 0 2px rgba(0, 0, 0, 0.1),
0 0 4px rgba(0, 0, 0, 0.1);
padding: 2px 4px;
background: rgba(255, 255, 255, 0.5);
margin: 0 0 1px 0;
width: 30px;
text-align: center;
}
</style>
<script>
module.exports = {
data () {
return {
search: '',
pagination: {},
selected: [],
headers: [
{ text: 'NAMA',width:'20%',align:'center',sortable: false},
{ text: 'TANGGAL LAHIR',width:'10%',align:'center',sortable: false},
{ text: 'JENIS KEL.',width:'10%',align:'center',sortable: false},
{ text: 'NIK',width:'10%',align:'center',sortable: false},
{ text: 'JABATAN',width:'18%',align:'center',sortable: false},
{ text: 'STATUS',width:'10%',align:'center',sortable: false}
]
}
},
computed: {
patients() {
return this.$store.state.patient.patients
},
totalpatient() {
return this.$store.state.patient.total_patient
},
curr_page: {
get() {
return this.$store.state.patient.current_page
},
set(val) {
this.$store.commit("patient/update_current_page", val)
this.$store.dispatch("patient/search", {
search:this.$store.state.patient.search,
xid:this.$store.state.patient.data_setup.McuOfflinePrepareID,
current_page: val,
lastid: -1
})
}
},
xtotal_page: {
get() {
return this.$store.state.patient.total_patient
},
set(val) {
this.$store.commit("patient/update_total_patient", val)
}
},
xsearch: {
get() {
return this.$store.state.patient.search
},
set(val) {
this.$store.commit("patient/update_search", val)
}
},
},
methods: {
gotoReg(row) {
this.$store.dispatch("patient/gotoreg", row)
},
goToRegister(row){
var prm = this.$store.state.patient.selected_patient_listing
var setup = this.$store.state.patient.data_setup
var pre_id = row.Mcu_PreregisterDetailsID
var code = setup.McuOfflinePrepareCode
location.replace("/one-ui/test/vuex/one-fo-registration-v8/" + "?pre_id=" +pre_id+"&code="+code)
},
searchPatientTable(){
this.curr_page = 1
this.$store.dispatch("patient/search", {
search: this.xsearch,
current_page: this.curr_page,
xid:this.$store.state.patient.data_setup.McuOfflinePrepareID,
lastid: -1
})
},
}
}
</script>

View File

@@ -0,0 +1,543 @@
<template>
<v-layout class="fill-height" column>
<v-dialog v-model="dialogsuccess" persistent max-width="290">
<v-card>
<v-card-title color="success" class="headline">Berhasil !</v-card-title>
<v-card-text>
{{ msgsuccess }}
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="green darken-1" flat @click="closeDialogSuccess"
>OK</v-btn
>
</v-card-actions>
</v-card>
</v-dialog>
<v-card color="orange accent-1" class="mb-2 pa-2 searchbox">
<v-layout row>
<v-flex xs12>
<v-card>
<v-layout pa-1 row>
<v-flex class="text-xs-center pa-2" xs9>
<v-text-field
color="orange"
label="KODE SETUP"
placeholder="Masukkan kode setup"
v-model="setupcode"
outline
hide-details
></v-text-field>
</v-flex>
<v-flex class="text-xs-left pa-2" xs3>
<v-btn
@click="generateSetup()"
title="generate"
style="min-width: 30px; min-height: 25px;"
color="orange"
dark
>
<v-icon>system_update_alt</v-icon>
</v-btn>
</v-flex>
</v-layout>
<v-divider></v-divider>
<v-layout row>
<v-flex xs12 pa-2>
<v-card color="orange" dark>
<v-card-text>
<v-layout align-center row>
<v-flex pb-2 xs12>
SETUP : {{ xsetup.McuOfflinePrepareCode }}
</v-flex>
</v-layout>
<v-divider dark></v-divider>
<v-layout pt-2 align-center row>
<v-flex xs12>
{{ xsetup.M_CompanyName }}
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs12>
<p class="mb-0 caption">
Periode : {{ xsetup.start_date }} -
{{ xsetup.end_date }}
</p>
</v-flex>
</v-layout>
</v-card-text>
</v-card>
</v-flex>
</v-layout>
<v-divider></v-divider>
<v-layout row>
<v-flex xs12 pa-2>
<v-card>
<v-layout row>
<v-flex xs12>
<v-subheader
class="pl-3 white--text"
style="background: #ff9800;"
>AGREEMENT</v-subheader
>
</v-flex>
</v-layout>
<v-card-text>
<v-layout align-center wrap>
<v-flex pb-2 xs12>
<v-card
dark
class="mb-1"
v-if="xsetup && xsetup.agreements.length > 0"
v-for="agreement in xsetup.agreements"
color="orange"
>
<v-layout wrap>
<v-flex pa-2 xs12 text-xs-center
><p style="font-size: 12px;" class="mb-0">
{{ agreement.name }}
</p></v-flex
>
</v-layout>
</v-card>
</v-flex>
</v-layout>
</v-card-text>
</v-card>
</v-flex>
</v-layout>
<v-divider></v-divider>
<v-layout row>
<v-flex xs12 pa-2>
<v-card color="orange" dark>
<v-card-text>
<v-layout align-center row>
<v-flex xs5>
JANJI HASIL
</v-flex>
<v-flex text-xs-right xs7>
<p class="mb-0">
{{ xsetup.promise_date }} {{ xsetup.promise_time }}
</p>
</v-flex>
</v-layout>
</v-card-text>
</v-card>
</v-flex>
</v-layout>
<v-layout row>
<v-flex pa-2 xs12>
<v-btn block @click="downloadxapp()" class="" color="info"
>download</v-btn
>
</v-flex>
</v-layout>
</v-card>
</v-flex>
</v-layout>
</v-card>
<v-card color="orange accent-1" class="mb-2 pa-2 searchbox">
<v-layout pa-1 row>
<v-flex class="text-xs-center" xs12>
<p class="mb-0 caption">
silahkan download template di
<span
@click="downloadcsv()"
style="cursor: pointer;"
class="info--text lighten-3--text"
>sini</span
>
</p>
</v-flex>
</v-layout>
<v-divider></v-divider>
<v-layout pt-2 pb-1 row>
<v-flex class="text-xs-left" xs12>
<input
accept=".xlsx"
type="file"
id="csv_file"
name="csv_file"
class="form-control"
@change="loadCSV($event)"
/>
</v-flex>
</v-layout>
</v-card>
<one-dialog-alert
:status="openalertconfirmation"
:msg="msgalertconfirmation"
@forget-dialog-alert="forgetAlertConfirmation()"
@close-dialog-alert="closeAlertConfirmation()"
></one-dialog-alert>
</v-layout>
</template>
<style scoped>
table.v-table tbody td,
table.v-table tbody th {
height: 35px;
}
table.v-table thead tr {
height: 35px;
}
</style>
<script>
module.exports = {
components: {
"one-dialog-info": httpVueLoader("../../common/oneDialogInfo.vue"),
"one-dialog-alert": httpVueLoader("../../common/oneDialogAlert.vue"),
},
mounted() {
//this.setNewSetup()
},
methods: {
downloadxapp() {
var start = Date.now();
location.replace("/install-mcu.zip?tm=" + start);
},
generateSetup() {
this.$store.commit("patient/update_patients", []);
this.$store.commit("patient/update_total_patients", 0);
this.$store.dispatch("patient/generatesetup", {
setupcode: this.setupcode,
});
},
downloadcsv() {
window.open("./csv-mcu.xlsx");
},
editRow(row) {
console.log(row);
this.$store.commit("patient/update_act", "edit");
this.$store.commit("patient/update_xid", row.McuOfflinePrepareID);
this.$store.commit("patient/update_companies", [
{ id: row.McuOfflinePrepareM_CompanyID, name: row.M_CompanyName },
]);
this.$store.commit("patient/update_company", {
id: row.McuOfflinePrepareM_CompanyID,
name: row.M_CompanyName,
});
this.$store.commit("patient/update_mous", row.allmous);
this.$store.commit("patient/update_mou", {});
this.$store.commit("patient/update_selected_mous", row.mous);
this.$store.commit("patient/update_selected_doctors", row.doctors);
this.$store.commit(
"patient/update_start_date",
moment(row.McuOfflinePrepareStartDate).format("YYYY-MM-DD")
);
this.$store.commit(
"patient/update_end_date",
moment(row.McuOfflinePrepareEndDate).format("YYYY-MM-DD")
);
},
isSelected(p) {
return (
p.M_PatientID ==
this.$store.state.patient.selected_patient.M_PatientID
);
},
searchPatient() {
this.$store.dispatch("patient/search", {
status: this.status,
current_page: 1,
lastid: -1,
});
this.$store.commit("patient/update_current_page", 1);
},
selectMe(pat) {
if (this.$store.state.patient.no_save == 0) {
this.$store.commit("patient/update_selected_patient", pat);
} else {
this.$store.commit("patient/update_open_alert_confirmation", true);
}
},
closeAlertConfirmation() {
this.$store.commit("patient/update_open_alert_confirmation", false);
},
forgetAlertConfirmation() {
this.$store.commit("patient/update_no_save", 0);
this.$store.commit("patient/update_open_alert_confirmation", false);
},
updateAlert_success(val) {
this.$store.commit("patient/update_alert_success", val);
},
closeDialogSuccess() {
let arrpatient = this.$store.state.patient.patients;
var idx = _.findIndex(
arrpatient,
(item) => item.M_PatientID === this.$store.state.patient.last_id
);
console.log(idx);
this.$store.dispatch("patient/search", {
status: this.status,
current_page: this.curr_page,
lastid: idx,
});
this.$store.commit("patient/update_dialog_success", false);
},
setNewSetup() {
this.$store.commit("patient/update_act", "new");
this.$store.commit("patient/update_xid", -1);
this.$store.commit("patient/update_company", {});
this.$store.commit("patient/update_mous", []);
this.$store.commit("patient/update_mou", {});
this.$store.commit("patient/update_default_mou", {});
this.$store.commit("patient/update_default_doctor", {});
this.$store.commit("patient/update_selected_mous", []);
this.$store.commit("patient/update_selected_doctors", []);
this.$store.commit(
"patient/update_start_date",
moment(new Date()).format("YYYY-MM-DD")
);
this.$store.commit(
"patient/update_end_date",
moment(new Date()).format("YYYY-MM-DD")
);
},
deleteData(row) {
this.$store.commit("patient/update_selected_patient", row);
console.log(this.$store.state.patient.selected_patient);
let msg =
"Yakin, akan menghapus data setup " +
this.$store.state.patient.selected_patient.McuOfflinePrepareCode +
" ?";
this.$store.commit("patient/update_msg_confirmation_delete", msg);
this.$store.commit("patient/update_dialog_confirmation_delete", true);
},
doDeleteData() {
var prm = {};
prm.id = this.$store.state.patient.selected_patient.McuOfflinePrepareID;
prm.code = this.$store.state.patient.selected_patient.McuOfflinePrepareCode;
console.log(prm);
this.$store.dispatch("patient/delete", prm);
},
csvJSON(csv) {
var vm = this;
var lines = csv.split("\n");
var result = [];
var headers = lines[0].split(",");
vm.parse_header = lines[0].split(",");
lines[0].split(",").forEach(function (key) {
vm.sortOrders[key] = 1;
});
lines.map(function (line, indexLine) {
if (indexLine < 1) return; // Jump header line
var obj = {};
var currentline = line.split(",");
headers.map(function (header, indexHeader) {
var header = header.trim();
obj[header] = currentline[indexHeader];
});
result.push(obj);
});
result.pop(); // remove the last item because undefined values
return result; // JavaScript object
},
loadCSV_old(e) {
var vm = this;
if (window.FileReader) {
var reader = new FileReader();
reader.readAsText(e.target.files[0]);
// Handle errors load
reader.onload = function (event) {
var csv = event.target.result;
vm.parse_csv = vm.csvJSON(csv);
var prm = {
xid: vm.$store.state.patient.data_setup.McuOfflinePrepareID,
data: vm.parse_csv,
};
console.log(prm);
vm.$store.dispatch("patient/savecsv", prm);
};
reader.onerror = function (evt) {
if (evt.target.error.name == "NotReadableError") {
alert("Canno't read file !");
}
};
} else {
alert("FileReader are not supported in this browser.");
}
},
loadCSV(e) {
var vm = this;
var files = e.target.files,
f = files[0];
var reader = new FileReader();
reader.onload = function (e) {
var data = new Uint8Array(e.target.result);
var workbook = XLSX.read(data, {
type: "array",
cellText: true,
cellDates: true,
});
let sheetName = workbook.SheetNames[0];
/* DO SOMETHING WITH workbook HERE */
console.log(workbook);
let worksheet = workbook.Sheets[sheetName];
// console.log(XLSX.utils.sheet_to_json(worksheet));
//var xdata = XLSX.utils.sheet_to_json(worksheet,{ raw:false, dateNF: 'FMT 22'})
var data_json = [];
// console.log(xdata)
var date_data = XLSX.utils.sheet_to_json(worksheet, {
raw: false,
dateNF: "22",
});
var ktp_data = XLSX.utils.sheet_to_json(worksheet, {
cellText: true,
});
//console.log(zdata)
date_data.forEach(function (entry, iidx) {
if (iidx > 0) {
//entry.TANGGAL_LAHIR = moment(entry.TANGGAL_LAHIR).format('DD-MM-YYYY')
entry.KTP = ktp_data[iidx].KTP;
data_json.push(entry);
}
});
var prm = {
xid: vm.$store.state.patient.data_setup.McuOfflinePrepareID,
data: data_json,
};
console.log(data_json);
//XLSX.utils.sheet_to_json(ws, {dateNF:"YYYY-MM-DD"})
// vm.$store.dispatch("patient/savecsv", prm);
};
reader.readAsArrayBuffer(f);
},
},
computed: {
setupcode: {
get() {
return this.$store.state.patient.setupcode;
},
set(val) {
this.$store.commit("patient/update_setupcode", val);
},
},
xsetup() {
return this.$store.state.patient.data_setup;
},
dialogconfirmationdelete: {
get() {
return this.$store.state.patient.dialog_confirmation_delete;
},
set(val) {
this.$store.commit("patient/update_dialog_confirmation_delete", val);
},
},
msgconfirmationdelete() {
return this.$store.state.patient.msg_confirmation_delete;
},
status: {
get() {
return this.$store.state.patient.status;
},
set(val) {
this.$store.commit("patient/update_status", val);
this.$store.dispatch("patient/search", {
status: val,
current_page: this.curr_page,
lastid: -1,
});
},
},
dialogsuccess: {
get() {
return this.$store.state.patient.dialog_success;
},
set(val) {
this.$store.commit("patient/update_dialog_success", val);
},
},
msgsuccess() {
return this.$store.state.patient.msg_success;
},
snackbar: {
get() {
return this.$store.state.patient.alert_success;
},
set(val) {
this.$store.commit("patient/update_alert_success", val);
},
},
isLoading() {
return this.$store.state.patient.search_status == 1;
},
openalertconfirmation: {
get() {
return this.$store.state.patient.open_alert_confirmation;
},
set(val) {
this.$store.commit("patient/update_open_alert_confirmation", val);
},
},
},
filters: {
capitalize: function (str) {
return str.charAt(0).toUpperCase() + str.slice(1);
},
},
data() {
return {
channel_name: "",
channel_fields: [],
channel_entries: [],
parse_header: [],
parse_csv: [],
sortOrders: {},
sortKey: "",
statuses: [
{ id: "N", name: "Belum di download" },
{ id: "Y", name: "Sudah di download" },
],
msgalertconfirmation:
"Perubahan yang telah dilakukan belum disimpan dong !",
items: [],
name: "",
snorm: "",
page: 1,
headers: [
{
text: "KODE",
align: "left",
sortable: false,
value: "mr",
width: "20%",
class: "pa-2 deep-orange accent-1 white--text",
},
{
text: "KEL. PELANGGAN",
align: "left",
sortable: false,
value: "lab",
width: "55%",
class: "pa-2 deep-orange accent-1 white--text",
},
{
text: "AKSI",
align: "left",
sortable: false,
value: "lab",
width: "15%",
class: "pa-2 deep-orange accent-1 white--text",
},
],
pagination: {
descending: false,
page: 1,
rowsPerPage: 5,
sortBy: "M_PatientName",
totalItems: this.$store.state.patient.total_patients,
},
};
},
};
</script>

View File

@@ -0,0 +1,3 @@
PID,NAMA,TANGGAL_LAHIR,JENIS_KELAMIN,NIK,JABATAN,EMAIL,HP,LOKASI,JOB,KEDUDUKAN
,AA,12-09-2001,P,,GURU,,,,,
,BB,14-01-1994,L,12.14.44.55,DIRKEU,,,,,
1 PID NAMA TANGGAL_LAHIR JENIS_KELAMIN NIK JABATAN EMAIL HP LOKASI JOB KEDUDUKAN
2 AA 12-09-2001 P GURU
3 BB 14-01-1994 L 12.14.44.55 DIRKEU

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,119 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>One</title>
<link rel="stylesheet" href="../../../libs/vendor/css/google-fonts.css">
<link rel="stylesheet" href="../../../libs/vendor/css/icomoon-fonts.css">
<link rel="stylesheet" href="../../../libs/vendor/css/vuetify.min.css">
</head>
<body>
<div v-cloak id="app">
<v-app id="smartApp">
<one-navbar></one-navbar>
<v-content style="background:#F5E8DF!important">
<v-container fluid fill-height class="pl-1 pr-1 pt-2 pb-2">
<v-layout row wrap>
<!-- <v-flex xs3 class="left" fill-height pa-1>
<one-md-patient-list></one-md-patient-list>
</v-flex>
<v-flex xs9 class="right" fill-height pa-1>
<one-md-patient-detail></one-md-patient-detail>
</v-flex> -->
<one-balance></one-balance>
</v-layout>
</v-container>
</v-content>
<one-footer> </one-footer>
</v-app>
</div>
<!-- Vendor -->
<script src="../../../libs/vendor/moment.min.js"></script>
<script src="../../../libs/vendor/numeral.min.js"></script>
<script src="../../../libs/vendor/moment-locale-id.js"></script>
<script src="../../../libs/vendor/lodash.js"></script>
<script src="../../../libs/vendor/axios.min.js"></script>
<script src="../../../libs/vendor/vue.js"></script>
<script src="../../../libs/vendor/vuex.js"></script>
<script src="../../../libs/vendor/vuetify.js"></script>
<script src="../../../libs/vendor/httpVueLoader.js"></script>
<script src="../../../libs/one_global.js"></script>
<script src="../../../libs/vendor/sheetjs-master/xlsx.full.min.js"></script>
<!-- App Script -->
<?php
$ts = "?ts=" . Date("ymdhis");
?>
<script type="module">
window.calculate_age = function(inp_dob) {
var now = moment(new Date())
var dob = moment(new Date(inp_dob))
var year = now.diff(dob, 'years')
dob.add(year, 'years')
var month = now.diff(dob, 'months')
dob.add(month, 'months')
var day = now.diff(dob, 'days')
if (isNaN(year)) return ''
return `${year} tahun ${month} bulan ${day} hari`
}
import {
store
} from './store.js<?php echo $ts ?>';
//for testing
window.store = store;
var ts = "?ts=" + Date.now();
new Vue({
store,
el: '#app',
methods: {
tab_selected: function(tab) {
return this.$store.state.tab_selected == tab
}
},
mounted: function() {
var url_string = window.location.href
var url = new URL(url_string);
var code = url.searchParams.get("code");
if (code != null) {
this.$store.commit('order/update_setupcode', code)
this.$store.commit("patient/update_patients", [])
this.$store.commit("patient/update_total_patients", 0)
this.$store.commit("patient/update_current_page", 1)
this.$store.dispatch("patient/generatesetup", {
setupcode: code
})
}
if (!one_token())
location.replace('/one-ui/test/vuex/one-login')
},
components: {
'one-navbar': httpVueLoader('../../../apps/components/oneNavbarComponent.vue'),
'one-footer': httpVueLoader('../../../apps/components/oneFooter.vue'),
'one-balance': httpVueLoader('./components/oneBalance.vue')
}
})
</script>
<style>
[v-cloak] {
display: none
}
.left {}
.right {}
</style>
</body>
</html>

View File

@@ -0,0 +1,411 @@
// 1 => LOADING
// 2 => DONE
// 3 => ERROR
import * as api from "../api/balance.js"
export default {
namespaced: true,
state: {
last_id: -1,
loading: false,
cek: false,
dataUpload: [],
status: 'N',
snackbar: {
state: false,
color: 'success',
msg: ''
},
periodeList: [
{
"id": '1', "name": "periode Januari", "periode": '01-01-2024 - 31-01-2024'
},
{
"id": '2', "name": "periode Februari", "periode": '01-02-2024 - 31-02-2024'
}
],
selectedPeriode: {},
data: [
{
"number": '101101001',
"keterangan": 'Bank BCA 742-599-268899',
"value": '1500000',
"type": 'DB',
"input": 1
},
{
"number": '101101002',
"keterangan": 'Bank',
"value": '1500000',
"type": 'CR',
"input": 1
},
],
summary: { debit: "1500000", credit: "1500000", balance: "1500000" },
dialogEdit: false,
dialogImport: false,
dialogAdd: false,
loadingAutocomplete: false,
coaList: [],
selectedCoa: {},
searchCoa: ''
},
mutations: {
update_periodeList(state, val) {
state.periodeList = val
},
update_selectedPeriode(state, val) {
state.selectedPeriode = val
},
update_data(state, val) {
state.data = val
},
update_dialogEdit(state, val) {
state.dialogEdit = val
},
update_dialogImport(state, val) {
state.dialogImport = val
},
update_summary(state, val) {
state.summary = val
},
update_loading(state, val) {
state.loading = val
},
update_cek(state, val) {
state.cek = val
},
update_dataUpload(state, val) {
state.dataUpload = val
},
update_loadingAutocomplete(state, val) {
state.loadingAutocomplete = val
},
update_coaList(state, val) {
state.coaList = val
},
update_selectedCoa(state, val) {
state.selectedCoa = val
},
update_searchCoa(state, val) {
state.searchCoa = val
},
update_dialogAdd(state, val) {
state.dialogAdd = val
},
update_status(state, val) {
state.status = val
},
update_snackbar(state, val) {
state.snackbar = val
},
},
actions: {
async getPeriode(context) {
context.commit("update_loading", true)
try {
let prm = {}
prm.token = one_token()
let resp = await api.getPeriode(prm)
if (resp.status != "OK") {
context.commit("update_loading", false)
} else {
context.commit("update_loading", false)
context.commit("update_periodeList", resp.data)
console.log(resp.data);
}
} catch (e) {
context.commit("update_loading", false)
console.log(e)
}
},
async addData(context, prm) {
context.commit("update_loading", true)
try {
prm.periode = context.state.selectedPeriode;
prm.token = one_token()
let resp = await api.addData(prm)
if (resp.status != "OK") {
context.commit("update_loading", false)
let snackbar = {
state: true,
color: 'error',
msg: resp.message
}
context.commit("update_snackbar", snackbar)
console.log(resp)
} else {
context.commit("update_loading", false)
context.dispatch("search");
context.commit("update_dialogAdd", false)
let snackbar = {
state: true,
color: 'success',
msg: 'Berhasil tambah data'
}
context.commit("update_snackbar", snackbar)
console.log(resp.data);
}
} catch (e) {
context.commit("update_loading", false)
let snackbar = {
state: true,
color: 'error',
msg: 'Error add data'
}
context.commit("update_snackbar", snackbar)
console.log('error add data')
}
},
async save(context, prm) {
context.commit("update_loading", true)
try {
prm.periode = context.state.selectedPeriode;
prm.token = one_token()
let resp = await api.save(prm)
if (resp.status != "OK") {
context.commit("update_loading", false)
let snackbar = {
state: true,
color: 'error',
msg: resp.message
}
context.commit("update_snackbar", snackbar)
console.log(resp)
} else {
context.commit("update_loading", false)
context.dispatch("search");
context.commit("update_dialogImport", false)
let snackbar = {
state: true,
color: 'success',
msg: 'Berhasil simpan data'
}
context.commit("update_snackbar", snackbar)
console.log(resp.data);
}
} catch (e) {
context.commit("update_loading", false)
let snackbar = {
state: true,
color: 'error',
msg: "Error save"
}
context.commit("update_snackbar", snackbar)
console.log(e)
}
},
async postData(context) {
context.commit("update_loading", true)
try {
let prm = {}
prm.token = one_token()
let resp = await api.postData(prm)
if (resp.status != "OK") {
context.commit("update_loading", false)
console.log(resp)
let snackbar = {
state: true,
color: 'error',
msg: resp.message
}
context.commit("update_snackbar", snackbar)
} else {
context.commit("update_loading", false)
context.dispatch("search");
let snackbar = {
state: true,
color: 'success',
msg: 'Berhasil post data'
}
context.commit("update_snackbar", snackbar)
console.log(resp.data);
}
} catch (e) {
context.commit("update_loading", false)
let snackbar = {
state: true,
color: 'error',
msg: "Error post data"
}
context.commit("update_snackbar", snackbar)
console.log(e)
}
},
async search(context) {
context.commit("update_loading", true)
try {
let prm = {}
prm.token = one_token()
let resp = await api.search(prm)
if (resp.status != "OK") {
context.commit("update_loading", false)
console.log(resp)
let snackbar = {
state: true,
color: 'error',
msg: resp.message
}
context.commit("update_snackbar", snackbar)
} else {
console.log(resp);
context.commit("update_loading", false)
context.commit("update_data", resp.data.data)
context.commit("update_summary", resp.data.total)
context.commit("update_selectedPeriode", resp.data.periode)
context.commit("update_status", resp.data.status)
}
} catch (e) {
context.commit("update_loading", false)
let snackbar = {
state: true,
color: 'error',
msg: "Error Search"
}
context.commit("update_snackbar", snackbar)
console.log(e)
}
},
async cek(context) {
context.commit("update_loading", true)
try {
let prm = {}
prm.token = one_token()
let resp = await api.cek(prm)
if (resp.status != "OK") {
context.commit("update_loading", false)
console.log(resp)
} else {
console.log(resp);
context.commit("update_loading", false)
let cek = 0;
if (parseInt(resp.data) > 0) {
cek = true
}
context.commit("update_cek", cek)
}
} catch (e) {
context.commit("update_loading", false)
console.log(e)
}
},
async updateData(context, prm) {
context.commit("update_loading", true)
try {
prm.token = one_token()
let resp = await api.updateData(prm)
if (resp.status != "OK") {
context.commit("update_loading", false)
console.log(resp)
let snackbar = {
state: true,
color: 'error',
msg: resp.message
}
context.commit("update_snackbar", snackbar)
} else {
console.log(resp);
// context.commit("update_loading", false)
// let cek = 0;
// if (parseInt(resp.data) > 0) {
// cek = true
// }
context.dispatch("search")
context.commit("update_dialogEdit", false)
let snackbar = {
state: true,
color: 'success',
msg: 'Berhasil update data'
}
context.commit("update_snackbar", snackbar)
}
} catch (e) {
context.commit("update_loading", false)
let snackbar = {
state: true,
color: 'error',
msg: "Error update data"
}
context.commit("update_snackbar", snackbar)
console.log(e)
}
},
async deleteData(context, prm) {
context.commit("update_loading", true)
try {
prm.token = one_token()
let resp = await api.deleteData(prm)
if (resp.status != "OK") {
context.commit("update_loading", false)
console.log(resp)
let snackbar = {
state: true,
color: 'error',
msg: resp.message
}
context.commit("update_snackbar", snackbar)
} else {
console.log(resp);
// context.commit("update_loading", false)
// let cek = 0;
// if (parseInt(resp.data) > 0) {
// cek = true
// }
let snackbar = {
state: true,
color: 'success',
msg: 'Berhasil hapus data'
}
context.commit("update_snackbar", snackbar)
context.dispatch("search")
// context.commit("update_dialogEdit", false)
}
} catch (e) {
context.commit("update_loading", false)
let snackbar = {
state: true,
color: 'error',
msg: "Error delete data"
}
context.commit("update_snackbar", snackbar)
console.log(e)
}
},
async searchCoa(context) {
context.commit("update_loadingAutocomplete", true)
try {
let prm = {};
prm.search = context.state.searchCoa;
prm.token = one_token()
let resp = await api.searchCoa(prm)
if (resp.status != "OK") {
context.commit("update_loadingAutocomplete", false)
console.log(resp);
} else {
console.log(resp);
context.commit("update_loadingAutocomplete", false)
// let cek = 0;
// if (parseInt(resp.data) > 0) {
// cek = true
// }
context.commit("update_coaList", resp.data)
}
} catch (e) {
context.commit("update_loadingAutocomplete", false)
console.log(e)
}
},
}
}

View File

@@ -0,0 +1,740 @@
// 1 => LOADING
// 2 => DONE
// 3 => ERROR
import * as api from "../api/patient.js"
export default {
namespaced: true,
state: {
last_id: -1,
last_saved_id: -1,
x_addr_id: 0,
act: 'edit',
act_addr: 'new',
get_data_status: 0,
search_patient: 0,
search_status: 0,
search_error_message: '',
norm: '',
patient_prefix: '',
patient_name: '',
patient_suffix: '',
titles: [],
selected_title: {},
dob: '',
patients: [],
total_patients: 0,
patient_address: [],
sexes: [],
selected_sex: {},
religions: [],
selected_religion: {},
phone: '',
hp: '',
email: '',
pob: '',
kartuidentitass: [],
selected_kartuidentitas: {},
noidentitas: '',
note: '',
nik: '',
jabatan: '',
kedudukan: '',
pj: '',
location: '',
job: '',
total_patient: 0,
selected_patient: {},
save_status: 0,
btn_save_seen: true,
pgrs_save: false,
save_error_message: '',
no_save: 0,
open_alert_confirmation: false,
alert_success: false,
msg_success: "",
dialog_success: false,
dialog_confirmation_delete: false,
msg_confirmation_delete: "",
dialog_confirmation_delete_addr: false,
msg_confirmation_delete_addr: "",
autocomplete_status: 0,
dialog_form_address: false,
label_address: '',
addresses: [],
cities: [],
city_address: {},
companies:[],
company:{},
mous:[],
mou:{},
doctors:[],
doctor:{},
districts: [],
district_address: {},
kelurahans: [],
kelurahan_address: {},
description_address: '',
errors: [],
current_page:1,
autocomplete_status:0,
status:{id:"N",name:"Belum di download"},
start_date:moment(new Date()).format('YYYY-MM-DD'),
end_date:moment(new Date()).format('YYYY-MM-DD'),
selected_mous:[],
selected_doctors:[],
xid:-1,
csv_json:[],
data_setup:{},
default_mu :{},
default_doctor:{},
setupcode:'',
search:''
},
mutations: {
update_search(state,val){
state.search = val
},
update_setupcode(state,val){
state.setupcode = val
},
update_default_mu(state,val){
state.default_mu = val
},
update_default_doctor(state,val){
state.default_doctor = val
},
update_data_setup(state,val){
state.data_setup = val
},
update_csv_json(state,val){
state.csv_json = val
},
update_xid(state,val){
state.xid = val
},
update_selected_doctors(state,val){
state.selected_doctors = val
},
update_selected_mous(state,val){
state.selected_mous = val
},
update_companies(state,val){
state.companies = val
},
update_company(state,val){
state.company = val
},
update_mous(state,val){
state.mous = val
},
update_mou(state,val){
state.mou = val
},
update_doctors(state,val){
state.doctors = val
},
update_doctor(state,val){
state.doctor = val
},
update_autocomplete_status(state,val){
state.autocomplete_status = val
},
update_start_date(state, val) {
state.start_date = val
},
update_end_date(state, val) {
state.end_date = val
},
update_status(state, val) {
state.status = val
},
update_current_page(state, val) {
state.current_page = val
},
update_x_addr_id(state, val) {
state.x_addr_id = val
},
update_last_id(state, val) {
state.last_id = val
},
update_last_saved_id(state, val) {
state.last_saved_id = val
},
update_act(state, val) {
state.act = val
},
update_act_addr(state, val) {
state.act_addr = val
},
update_get_data_status(state, val) {
state.get_data_status = val
},
update_search_error_message(state, patient) {
state.search_error_message = patient
},
update_search_patient(state, patient) {
state.search_patient = patient
},
update_dob(state, val) {
state.dob = val
},
update_patient_prefix(state, val) {
state.patient_prefix= val
},
update_patient_name(state, val) {
state.patient_name = val
},
update_patient_suffix(state, val) {
state.patient_suffix = val
},
update_norm(state, val) {
state.norm = val
},
update_titles(state, val) {
state.titles = val
},
update_selected_title(state, val) {
state.selected_title = val
},
update_patients(state, data) {
state.patients = data
},
update_selected_patient(state, val) {
state.selected_patient = val
},
update_sexes(state, val) {
state.sexes = val
},
update_selected_sex(state, val) {
state.selected_sex = val
},
update_religions(state, val) {
state.religions = val
},
update_selected_religion(state, val) {
state.selected_religion = val
},
update_phone(state, val) {
state.phone = val
},
update_email(state, val) {
state.email = val
},
update_pob(state, val) {
state.pob = val
},
update_hp(state, val) {
state.hp = val
},
update_kartuidentitass(state, val) {
state.kartuidentitass = val
},
update_selected_kartuidentitas(state, val) {
state.selected_kartuidentitas = val
},
update_noidentitas(state, val) {
state.noidentitas = val
},
update_note(state, val) {
state.note = val
},
update_nik(state, val) {
state.nik = val
},
update_jabatan(state, val) {
state.jabatan = val
},
update_kedudukan(state, val) {
state.kedudukan = val
},
update_pj(state, val) {
state.pj = val
},
update_location(state, val) {
state.location = val
},
update_job(state, val) {
state.job = val
},
update_save_status(state, val) {
state.save_status = val
},
update_btn_save_seen(state, val) {
state.btn_save_seen = val
},
update_pgrs_save(state, val) {
state.pgrs_save = val
},
update_save_error_message(state, msg) {
state.save_error_message = ''
},
update_no_save(state, val) {
state.no_save = val
},
update_open_alert_confirmation(state, val) {
state.open_alert_confirmation = val
},
update_alert_success(state, val) {
state.alert_success = val
},
update_msg_success(state, val) {
state.msg_success = val
},
update_dialog_success(state, val) {
state.dialog_success = val
},
update_dialog_confirmation_delete(state, val) {
state.dialog_confirmation_delete = val
},
update_msg_confirmation_delete(state, val) {
state.msg_confirmation_delete = val
},
update_dialog_confirmation_delete_addr(state, val) {
state.dialog_confirmation_delete_addr = val
},
update_msg_confirmation_delete_addr(state, val) {
state.msg_confirmation_delete_addr = val
},
update_addresses(state, val) {
state.addresses = val
},
update_autocomplete_status(state, val) {
state.autocomplete_status = val
},
update_dialog_form_address(state, val) {
state.dialog_form_address = val
},
update_label_address(state, val) {
state.label_address = val
},
update_cities(state, val) {
state.cities = val
},
update_city_address(state, val) {
state.city_address = val
},
update_districts(state, val) {
state.districts = val
},
update_district_address(state, val) {
state.district_address = val
},
update_kelurahans(state, val) {
state.kelurahans = val
},
update_kelurahan_address(state, val) {
state.kelurahan_address = val
},
update_description_address(state, val) {
state.description_address = val
},
update_search_status(state, val) {
state.search_status = val
},
update_errors(state, val) {
state.errors = val
},
update_total_patients(state, val) {
state.total_patients = val
},
update_total_patient(state, val) {
state.total_patient = val
}
},
actions: {
async generatesetup(context,prm) {
context.commit("update_get_data_status", 1)
try {
prm.token = one_token()
let resp = await api.generatesetup(prm)
if (resp.status != "OK") {
context.commit("update_get_data_status", 3)
} else {
context.commit("update_get_data_status", 2)
let data = {
records: resp.data.records,
total: resp.data.total
}
console.log(resp.data.records)
context.commit("update_data_setup", resp.data.records)
context.commit("update_setupcode", '')
context.commit("update_current_page", 1)
//context.commit("update_patients", data.records['patients'])
context.dispatch("search", {
search:'',
xid:context.state.data_setup.McuOfflinePrepareID,
current_page: 1,
lastid: -1
})
}
} catch (e) {
context.commit("update_get_data_status", 3)
}
},
async search(context, prm) {
context.commit("update_search_patient", 1)
try {
prm.token = one_token()
let resp = await api.search(prm)
if (resp.status != "OK") {
context.commit("update_search_patient", 3)
context.commit("update_search_error_message", resp.message)
} else {
context.commit("update_search_patient", 2)
context.commit("update_search_error_message", "")
let data = {
records: resp.data.records,
total: resp.data.total
}
context.commit("update_patients", data.records)
context.commit("update_total_patient", data.total)
context.commit("update_no_save", 0)
//context.commit("update_data_setup", resp.data.setup)
}
} catch (e) {
context.commit("update_search_patient", 3)
context.commit("update_search_error_message", e.message)
console.log(e)
}
},
async getsexreg(context) {
context.commit("update_get_data_status", 1)
try {
let resp = await api.getsexreg(one_token())
if (resp.status != "OK") {
context.commit("update_get_data_status", 3)
} else {
context.commit("update_get_data_status", 2)
let data = {
records: resp.data.records,
total: resp.data.total
}
context.commit("update_sexes", data.records.sexes)
context.commit("update_religions", data.records.religions)
context.commit("update_titles", data.records.titles)
context.commit("update_kartuidentitass", data.records.kartuidentitass)
}
} catch (e) {
context.commit("update_get_data_status", 3)
}
},
async savecsv(context, prm) {
context.commit("update_save_status", 1)
try {
prm.token = one_token()
let resp = await api.save(prm)
if (resp.status != "OK") {
context.commit("update_save_status", 3)
} else {
context.commit("update_save_status", 2)
//location.reload()
context.dispatch("search", {
search:'',
xid:context.state.data_setup.McuOfflinePrepareID,
current_page: 1,
lastid: -1
})
}
} catch (e) {
context.commit("update_save_status", 3)
}
},
async gotoreg(context, prm) {
context.commit("update_save_status", 1)
try {
prm.token = one_token()
let resp = await api.gotoreg(prm)
if (resp.status != "OK") {
context.commit("update_save_status", 3)
} else {
context.commit("update_save_status", 2)
var pre_id = prm.Mcu_PreregisterDetailsID
location.replace("/one-ui/test/vuex/one-fo-registration-v8/" + "?pre_id=" +pre_id)
}
} catch (e) {
context.commit("update_save_status", 3)
}
},
async newpatient(context, prm) {
context.commit("update_save_status", 1)
try {
prm.token = one_token()
let resp = await api.newpatient(prm)
if (resp.status != "OK") {
context.commit("update_save_status", 3)
} else {
context.commit("update_save_status", 2)
console.log(resp.data.id)
context.commit("update_last_id", resp.data.id)
context.commit("update_dialog_success", true)
var msg = "Data pasien " + prm.M_PatientName + " sudah tersimpan dong ..."
context.commit("update_msg_success", msg)
}
} catch (e) {
context.commit("update_save_status", 3)
}
},
async delete(context, prm) {
context.commit("update_save_status", 1)
try {
prm.token = one_token()
let resp = await api.xdelete(prm)
if (resp.status != "OK") {
context.commit("update_save_status", 3)
} else {
context.commit("update_save_status", 2)
context.commit("update_last_id", 0)
context.commit("update_dialog_confirmation_delete", false)
context.commit("update_dialog_success", true)
var msg = "Data setup " + prm.code + " sudah dihapus dong ..."
context.commit("update_msg_success", msg)
context.commit("update_company", {})
context.commit("update_selected_mous", [])
context.commit("update_mou", {})
context.commit("update_selected_doctors", [])
context.commit("update_start_date", moment(new Date()).format('YYYY-MM-DD'))
context.commit("update_end_date", moment(new Date()).format('YYYY-MM-DD'))
context.commit("update_default_mou", {})
context.commit("update_default_doctor", {})
}
} catch (e) {
context.commit("update_save_status", 3)
}
},
async getaddress(context, prm) {
context.commit("update_save_status", 1)
try {
prm.token = one_token()
let resp = await api.getaddress(prm)
if (resp.status != "OK") {
context.commit("update_save_status", 3)
} else {
context.commit("update_save_status", 2)
let data = {
records: resp.data.records,
total: resp.data.total
}
context.commit("update_addresses", data.records)
}
} catch (e) {
context.commit("update_save_status", 3)
}
},
async savesetup(context, prm) {
context.commit("update_save_status", 1)
try {
prm.token = one_token()
let resp = await api.savesetup(prm)
if (resp.status != "OK") {
context.commit("update_save_status", 3)
} else {
context.commit("update_save_status", 2)
let data = {
records: resp.data.records,
total: resp.data.total
}
context.commit("update_company", {})
context.commit("update_selected_mous", [])
context.commit("update_mou", {})
context.commit("update_selected_doctors", [])
context.commit("update_start_date", moment(new Date()).format('YYYY-MM-DD'))
context.commit("update_end_date", moment(new Date()).format('YYYY-MM-DD'))
context.commit("update_default_mou", {})
context.commit("update_default_doctor", {})
context.commit("update_dialog_success", true)
if(context.state.act === 'new')
var msg = "Pembuatan setup nomor " + resp.data.records.xnumber + " sudah berhasil dong ..."
else
var msg = "Perubahan setup nomor " + resp.data.records.xnumber + " sudah berhasil dong ..."
context.commit("update_msg_success", msg)
}
} catch (e) {
context.commit("update_save_status", 3)
}
},
async searchcity(context, prm) {
context.commit("update_autocomplete_status", 1)
try {
let resp = await api.searchcity(one_token(), prm)
if (resp.status != "OK") {
context.commit("update_autocomplete_status", 3)
} else {
context.commit("update_autocomplete_status", 2)
let data = {
records: resp.data.records,
total: resp.data.total
}
context.commit("update_cities", resp.data.records)
}
} catch (e) {
context.commit("update_autocomplete_status", 3)
}
},
async searchdoctor(context,prm) {
context.commit("update_autocomplete_status",1)
try {
var xpar = {}
xpar.search = prm
xpar.token = one_token()
let resp= await api.searchdoctor(xpar)
if (resp.status != "OK") {
context.commit("update_autocomplete_status",3)
} else {
context.commit("update_autocomplete_status",2)
let data = {
records : resp.data.records,
total: resp.data.total
}
var arr = resp.data.records
var xsel = context.state.selected_doctors
var filtered = arr.filter(o1 => xsel.filter(o2 => o2.id === o1.id).length === 0)
context.commit("update_doctors",filtered)
}
} catch(e) {
context.commit("update_autocomplete_status",3)
}
},
async searchcompany(context,prm) {
context.commit("update_autocomplete_status",1)
try {
prm.token = one_token()
let resp= await api.searchcompany(prm)
if (resp.status != "OK") {
context.commit("update_autocomplete_status",3)
} else {
context.commit("update_autocomplete_status",2)
let data = {
records : resp.data.records,
total: resp.data.total
}
context.commit("update_companies",resp.data.records)
}
} catch(e) {
context.commit("update_autocomplete_status",3)
}
},
async getdistrict(context, prm) {
context.commit("update_get_data_status", 1)
try {
let resp = await api.getdistrict(one_token(), prm)
if (resp.status != "OK") {
context.commit("update_get_data_status", 3)
} else {
context.commit("update_get_data_status", 2)
let data = {
records: resp.data.records,
total: resp.data.total
}
context.commit("update_districts", resp.data.records)
}
} catch (e) {
context.commit("update_get_data_status", 3)
}
},
async getkelurahan(context, prm) {
context.commit("update_get_data_status", 1)
try {
let resp = await api.getkelurahan(one_token(), prm)
if (resp.status != "OK") {
context.commit("update_get_data_status", 3)
} else {
context.commit("update_get_data_status", 2)
let data = {
records: resp.data.records,
total: resp.data.total
}
context.commit("update_kelurahans", resp.data.records)
}
} catch (e) {
context.commit("update_get_data_status", 3)
}
},
async savenewaddress(context, prm) {
context.commit("update_save_status", 1)
try {
prm.token = one_token()
let resp = await api.savenewaddress(prm)
if (resp.status != "OK") {
context.commit("update_save_status", 3)
} else {
context.commit("update_save_status", 2)
context.commit("update_dialog_form_address", false)
context.commit("update_last_id", prm.M_PatientAddressM_PatientID)
context.commit("update_dialog_success", true)
var msg = "Penambahan data alamat pasien " + prm.M_PatientName + " sudah berhasil dong ..."
context.commit("update_msg_success", msg)
}
} catch (e) {
context.commit("update_save_status", 3)
}
},
async saveeditaddress(context, prm) {
context.commit("update_save_status", 1)
try {
prm.token = one_token()
let resp = await api.saveeditaddress(prm)
if (resp.status != "OK") {
context.commit("update_save_status", 3)
} else {
context.commit("update_save_status", 2)
context.commit("update_dialog_form_address", false)
context.commit("update_last_id", prm.M_PatientAddressM_PatientID)
context.commit("update_dialog_success", true)
var msg = "Perubahan data alamat pasien " + prm.M_PatientName + " sudah berhasil dong ..."
context.commit("update_msg_success", msg)
}
} catch (e) {
context.commit("update_save_status", 3)
}
},
async deleteaddress(context, prm) {
context.commit("update_save_status", 1)
try {
prm.token = one_token()
let resp = await api.deleteaddress(prm)
if (resp.status != "OK") {
context.commit("update_save_status", 3)
} else {
context.commit("update_save_status", 2)
context.commit("update_dialog_confirmation_delete_addr", false)
context.commit("update_last_id", prm.M_PatientAddressM_PatientID)
context.commit("update_dialog_success", true)
var msg = "Penghapusan data alamat " + prm.M_PatientAddressNote + " dari pasien " + prm.M_PatientName + " sudah berhasil dong ..."
context.commit("update_msg_success", msg)
}
} catch (e) {
context.commit("update_save_status", 3)
}
},
async getmou(context,prm) {
context.commit("update_lookup_order",1)
try {
prm.token = one_token()
let resp= await api.getmou(prm)
if (resp.status != "OK") {
context.commit("update_lookup_order",3)
} else {
context.commit("update_lookup_order",2)
let data = {
records : resp.data.records,
total: resp.data.total
}
context.commit("update_mous",resp.data.records)
context.commit("update_mou",{})
context.commit("update_selected_mous",[])
}
} catch(e) {
context.commit("update_lookup_order",3)
}
},
}
}

View File

@@ -0,0 +1,29 @@
// State
// data ...
// Mutations
//
//
// Actions
import patient from "./modules/patient.js";
import system from "../../../apps/modules/system/system.js";
import balance from "./modules/balance.js";
export const store = new Vuex.Store({
modules: {
// patient: patient,
balance: balance,
system: system
},
state: {
tab_selected: 'pasien-dokter'
},
mutations: {
change_tab(state, ntab) {
state.tab_selected = ntab
}
},
actions: {
change_tab(context, ntab) {
context.commit('change_tab', ntab)
}
}
});

View File

@@ -0,0 +1,293 @@
const URL = "/one-api/mockup/purchase/order/PurchaseOrderInventaris/";
const URLRO = "/one-api/mockup/receive-item-po/receiveitempo/";
export async function getSupplier(payload) {
try {
var response = await axios.post(URL + "getSupplier", payload);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function getItemCategory(payload) {
try {
var response = await axios.post(URL + "getItemCategory", payload);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function getWarehouse(payload) {
try {
var response = await axios.post(URL + "getWarehouse", payload);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function getItem(payload) {
try {
var response = await axios.post(URL + "getItem", payload);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function getItemUpdate(payload) {
try {
var response = await axios.post(URL + "getItemUpdate", payload);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function saveOrder(payload) {
try {
var response = await axios.post(URL + "saveOrder", payload);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function search(payload) {
try {
var response = await axios.post(URL + "search", payload);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function requestOrder(payload) {
try {
var response = await axios.post(URL + "requestOrder", payload);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function deleteOrder(payload) {
try {
var response = await axios.post(URL + "deleteOrder", payload);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function updateOrder(payload) {
try {
var response = await axios.post(URL + "updateOrder", payload);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function approvePOrder(payload) {
try {
var response = await axios.post(URL + "approvePOrder", payload);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function isValidMultipleWarehouse(payload) {
try {
var response = await axios.post(URL + "isValidMultipleWarehouse", payload);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function generateItemPO(params) {
try {
var response = await axios.post(URLRO + "generateItemPo", params);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function getApprovalLevel(params) {
try {
var response = await axios.post(URL + 'getApproveLevel', params);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function getDefaultSupplierPrice(payload) {
try {
var response = await axios.post(URL + "getDefaultSupplierPrice", payload);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}

View File

@@ -0,0 +1,595 @@
<template>
<div>
<!-- Dialog View -->
<v-dialog v-model="dialogView" persistent width="85vw">
<v-card>
<v-card-title class="headline grey lighten-2" primary-title>
DETAIL PURCHASE ORDER {{ selectedPO.PurchaseOrderNumber ?? "" }}
</v-card-title>
<v-card-text>
<v-layout row wrap class="px-2 py-2">
<!-- HEADER PO VIEW -->
<v-layout row wrap class="pa-0 ma-0">
<!-- Tanggal -->
<v-flex xs3>
<div class="label-value subheading mb-2">
<span class="label">Nomor PO</span>
</div>
</v-flex>
<v-flex xs9>
<div class="label-value subheading mb-2">
<span class="value">: {{ selectedPO.PurchaseOrderNumber }}</span>
</div>
</v-flex>
<!-- Tanggal -->
<v-flex xs3>
<div class="label-value subheading mb-2">
<span class="label">Tanggal</span>
</div>
</v-flex>
<v-flex xs9>
<div class="label-value subheading mb-2">
<span class="value">: {{ selectedPO.DisplayDate }}</span>
</div>
</v-flex>
<!-- Nomor Referensi -->
<v-flex xs3>
<div class="label-value subheading mb-2">
<span class="label">Nomor Referensi</span>
</div>
</v-flex>
<v-flex xs9>
<div class="label-value subheading mb-2">
<span class="value">: {{ selectedPO.PurchaseOrderRefNumber }}</span>
</div>
</v-flex>
<!-- Pajak Pendapatan (PPN) -->
<v-flex xs3>
<div class="label-value subheading mb-2">
<span class="label">Pajak Pendapatan (PPN):</span>
</div>
</v-flex>
<v-flex xs9>
<div class="label-value subheading mb-2">
<span v-if="selectedPO.PurchaseOrderTaxPpnType == 'P'" class="value">: {{ selectedPO.PurchaseOrderTaxPercentPpn }}%</span>
<span v-else-if="selectedPO.PurchaseOrderTaxPpnType == 'R'" class="value">: Rp {{ selectedPO.PurchaseOrderTaxAmountPpn }}</span>
<span v-else class="value">: -</span>
</div>
</v-flex>
<!-- Pajak Penghasilan (PPH) -->
<v-flex xs3>
<div class="label-value subheading mb-2">
<span class="label">Pajak Penghasilan (PPH)</span>
</div>
</v-flex>
<v-flex xs9>
<div class="label-value subheading mb-2">
<span class="value">: {{ selectedPO.PurchaseOrderTaxPercentPph }}%</span>
</div>
</v-flex>
<!-- Vendor -->
<v-flex xs3>
<div class="label-value subheading mb-2">
<span class="label">Vendor</span>
</div>
</v-flex>
<v-flex xs9>
<div class="label-value subheading mb-2">
<span class="label">: {{ selectedPO.SupplierCode }}
{{ selectedPO.SupplierName }}
</span>
</div>
</v-flex>
<!-- Diskon Vendor -->
<v-flex xs3>
<div class="label-value subheading mb-2">
<span class="label">Diskon Vendor(Tipe Diskon)</span>
</div>
</v-flex>
<v-flex xs9>
<div class="label-value subheading mb-2">
<span v-if="selectedPO.DiscountType == 'Percentage'" class="label">: {{ selectedPO.PurchaseOrderDiscountPercent }}% (Percentage)</span>
<span v-if="selectedPO.DiscountType == 'Absolute'" class="label">: Rp {{ selectedPO.PurchaseOrderDiscountAmount }} (Absolut)</span>
<span v-if="selectedPO.DiscountType == ''" class="label">: - (-)</span>
</div>
</v-flex>
<!-- Jangka Waktu Pembayaran -->
<v-flex xs3>
<div class="label-value subheading mb-2">
<span class="label">Jangka Waktu Pembayaran</span>
</div>
</v-flex>
<v-flex xs9>
<div class="label-value subheading mb-2">
<span class="value">: {{ selectedPO.PurchaseOrderPaymentTerm }} hari</span>
</div>
</v-flex>
<!-- Tipe Gudang -->
<v-flex xs3>
<div class="label-value subheading mb-2">
<span class="label">Tipe Gudang</span>
</div>
</v-flex>
<!-- Tipe Gudang -->
<v-flex xs9>
<div class="label-value subheading mb-2">
<span class="value">: {{ selectedPO.PurchaseOrderWarehouseType }}</span>
</div>
</v-flex>
<!-- Gudang -->
<v-flex xs3 v-if="selectedPO.PurchaseOrderWarehouseType === 'Single'">
<div class="label-value subheading mb-2">
<span class="label">Gudang</span>
</div>
</v-flex>
<v-flex xs9 v-if="selectedPO.PurchaseOrderWarehouseType === 'Single'">
<div class="label-value subheading mb-2">
<span class="value">: {{ selectedPO.WarehouseName }}</span>
</div>
</v-flex>
<!-- Keterangan -->
<v-flex xs3>
<div class="label-value subheading mb-2">
<span class="label">Biaya Ekspedisi</span>
</div>
</v-flex>
<v-flex xs9>
<div class="label-value subheading mb-2">
<span class="value">: {{ selectedPO && selectedPO.PurchaseOrderShippingCost != null
? oneMoney(selectedPO.PurchaseOrderShippingCost) : '0' }}
<span v-if="selectedPO.PurchaseOrderShippingCostStatus === 'Y'">Sudah dibayar
</span>
<span v-if="selectedPO.PurchaseOrderShippingCostStatus === 'N'">Belum dibayar
</span>
</span>
</div>
</v-flex>
<!-- Keterangan -->
<v-flex xs3>
<div class="label-value subheading mb-2">
<span class="label">Keterangan</span>
</div>
</v-flex>
<v-flex xs9>
<div class="label-value subheading mb-2">
<span class="value">: {{ selectedPO.PurchaseOrderNote }}</span>
</div>
</v-flex>
</v-layout>
<!-- TABEL ITEM VIEW -->
<v-flex xs12>
<v-data-table v-if="summary.length > 0" :headers="summaryHeaders" :items="summary" :loading="loading"
hide-actions class="elevation-1 mt-4" expand item-key="M_ItemID">
<!-- Tabel Item -->
<template slot="items" slot-scope="props">
<tr @click="props.expanded = !props.expanded">
<td class="text-xs-center">
<v-icon>{{
props.expanded
? "keyboard_arrow_down"
: "keyboard_arrow_right"
}}</v-icon>
</td>
<td class="">
<kbd>{{ props.item.M_ItemCode }}</kbd>
{{ props.item.M_ItemDesc }}
</td>
<td class="text-xs-center">
{{ props.item.TotalPoQty }} {{ props.item.PoItemUnitName }}
</td>
<td class="text-xs-center">
{{ oneMoney(props.item.RealPrice) }}
</td>
<td class="text-xs-right">
<div v-if="props.item.discountType === 'R'">
{{ oneMoney(props.item.discount) }}
</div>
<div v-if="props.item.discountType === 'P'">
<kbd>{{ props.item.discount }}%</kbd>
{{ oneMoney(props.item.summaryDiscountAmount) }}
</div>
</td>
<td class="text-xs-right">
{{ oneMoney(props.item.Price) }}
</td>
<td class="text-xs-right">
{{ oneMoney(props.item.Total) }}
</td>
</tr>
</template>
<!-- Detail per Baris Item -->
<template slot="expand" slot-scope="props">
<v-card flat>
<v-card-text class="pl-3">
<div class="ml-3 mb-3">
<v-data-table :headers="detailHeaders" :items="props.item.Details" hide-actions
class="elevation-0">
<template slot="items" slot-scope="detailProps">
<td class="">
<kbd>{{ detailProps.item.M_ItemCode }}</kbd>
{{ detailProps.item.M_ItemDesc }}
</td>
<td class="">
{{
detailProps.item.PurchaseRequestNumber
}}
</td>
<td class="">
{{
detailProps.item.M_BranchName ??
detailProps.item.S_RegionalName
}}
</td>
<td class="py-1">
{{ detailProps.item.warehouse.WarehouseName }}
</td>
<td class="text-xs-center">
{{ detailProps.item.PoQty }}
{{ detailProps.item.PoItemUnitName }}
</td>
</template>
</v-data-table>
</div>
</v-card-text>
</v-card>
</template>
<!-- Tabel di bawah Item -->
<template v-slot:footer>
<tr>
<td :colspan="4">
<strong class="ml-2">TOTAL HARGA TANPA DISKON</strong>
</td>
<td :colspan="3" class="text-xs-right">
<strong>{{
selectedPO && selectedPO.TotalRealPrice != null
? oneMoney(selectedPO.TotalRealPrice) : '0'
}}</strong>
</td>
</tr>
<tr>
<td :colspan="4">
<strong class="ml-2">TOTAL DISKON PER ITEM</strong>
</td>
<td :colspan="3" class="text-xs-right">
<strong>{{
selectedPO && selectedPO.TotalDiskonPerItem != null
? oneMoney(selectedPO.TotalDiskonPerItem) : '0'
}}</strong>
</td>
</tr>
<tr>
<td :colspan="4">
<strong class="ml-2">DISKON VENDOR</strong>
</td>
<td :colspan="3" class="text-xs-right">
<strong>{{
selectedPO && selectedPO.DiscountAmount != null
? oneMoney(selectedPO.DiscountAmount) : '0'
}}</strong>
</td>
</tr>
<tr>
<td :colspan="4">
<strong class="ml-5">PAJAK PENDAPATAN(PPN)</strong>
</td>
<td :colspan="3" class="text-xs-right">
<strong>{{
selectedPO && selectedPO.PurchaseOrderTaxAmountPpn != null
? oneMoney(selectedPO.PurchaseOrderTaxAmountPpn) : '0'
}}</strong>
</td>
</tr>
<tr>
<td :colspan="4">
<strong class="ml-5">PAJAK PENGHASILAN(PPH)</strong>
</td>
<td :colspan="3" class="text-xs-right">
<strong>{{
selectedPO && selectedPO.PurchaseOrderTaxAmountPph != null
? oneMoney(selectedPO.PurchaseOrderTaxAmountPph) : '0'
}}</strong>
</td>
</tr>
<tr>
<td :colspan="4">
<strong class="ml-2">PAJAK</strong>
</td>
<td :colspan="3" class="text-xs-right">
<strong>{{ selectedPO && selectedPO.TaxAmount != null
? oneMoney(selectedPO.TaxAmount) : '0' }}</strong>
</td>
</tr>
<tr>
<td :colspan="4">
<strong>TOTAL</strong>
</td>
<td :colspan="3" class="text-xs-right">
<strong>{{
selectedPO && selectedPO.PurchaseOrderGrandTotal != null
? oneMoney(selectedPO.PurchaseOrderGrandTotal) : '0'
}}</strong>
</td>
</tr>
</template>
</v-data-table>
</v-flex>
</v-layout>
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="green" flat @click="dialogView = false">
TUTUP
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</div>
</template>
<script>
module.exports = {
data() {
return {
selectedDateForm: null,
refNumber: "",
taxPpn: 0,
taxPph: 0,
selectedSupplier: {},
paymentTerm: 0,
warehouseType: "",
selectedWarehouse: {},
note: "",
selectedItem: [],
detailHeaders: [
// {
// text: "KODE ITEM",
// align: "center",
// sortable: false,
// value: "M_ItemCode",
// width: "15%",
// class: "blue lighten-4 black--text",
// },
{
text: "NAMA PRODUK",
align: "center",
sortable: false,
value: "M_ItemDesc",
width: "20%",
class: "blue lighten-4 black--text",
},
{
text: "PR NUMBER",
align: "center",
sortable: false,
value: "M_ItemDesc",
width: "10%",
class: "blue lighten-4 black--text",
},
{
text: "CABANG",
align: "center",
sortable: false,
value: "M_BranchName",
width: "20%",
class: "blue lighten-4 black--text",
},
{
text: "GUDANG",
align: "center",
sortable: false,
value: "M_BranchName",
width: "30%",
class: "blue lighten-4 black--text",
},
// {
// text: "UNIT",
// align: "center",
// sortable: false,
// value: "ItemUnitName",
// width: "10%",
// class: "blue lighten-4 black--text",
// },
{
text: "QTY",
align: "center",
sortable: false,
value: "PoQty",
width: "15%",
class: "blue lighten-4 black--text",
},
],
summaryHeaders: [
{
text: "",
align: "center",
sortable: false,
value: "expand",
width: "5%",
class: "blue lighten-3 white--text",
},
{
text: "ITEM",
align: "center",
sortable: false,
value: "M_ItemCode",
width: "10%",
class: "blue lighten-3 white--text",
},
{
text: "QTY",
align: "center",
sortable: false,
value: "PoQty",
width: "10%",
class: "blue lighten-3 white--text",
},
{
text: "HARGA",
align: "center",
sortable: false,
value: "price",
width: "15%",
class: "blue lighten-3 white--text",
},
{
text: "DISKON",
align: "center",
sortable: false,
value: "price",
width: "20%",
class: "blue lighten-3 white--text",
},
{
text: "HARGA SETELAH DISKON",
align: "center",
sortable: false,
value: "price",
width: "15%",
class: "blue lighten-3 white--text",
},
{
text: "TOTAL",
align: "center",
sortable: false,
value: "Total",
width: "20%",
class: "blue lighten-3 white--text",
},
],
};
},
computed: {
statusOptions() {
return this.$store.state.po.statusOptions;
},
dialogView: {
get() {
return this.$store.state.po.dialogView;
},
set(val) {
this.$store.commit("po/update_dialogView", val);
},
},
selectedPO: {
get() {
return this.$store.state.po.selectedPO;
},
set(val) {
this.$store.commit("po/update_selectedPO", val);
},
},
summary: {
get() {
return this.$store.state.po.summary;
},
set(val) {
this.$store.commit("po/update_summary", val);
},
},
loading: {
get() {
return this.$store.state.po.loading;
},
set(val) {
this.$store.commit("po/update_loading", val);
},
},
},
methods: {
roundToThreeSignificantDigits(num) {
if (num === 0) return 0;
// Hitung jumlah digit
const absNum = Math.abs(num);
const magnitude = Math.floor(Math.log10(absNum)) + 1;
// Jika kurang dari 3 digit, tidak perlu dibulatkan
if (magnitude <= 3) return num;
// Hitung faktor pembulatan
const factor = Math.pow(10, magnitude - 3);
// Bulatkan
return Math.round(num / factor) * factor;
},
oneMoney(value) {
//return one_money(value);
// let splitValue = value.toString().split(".");
// if(splitValue.length > 1) {
// let val = splitValue[0]
// return val.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".") + "," + this.roundToThreeSignificantDigits(splitValue[1]);
// } else {
// return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".");
// }
// Ubah ke float jika belum angka
if (typeof value !== 'number') {
value = parseFloat(value);
}
if (isNaN(value)) return '0,00';
// Bulatkan dulu ke 2 desimal
const fixed = value.toFixed(2); // hasil string, misal "16200000.00" atau "123456.70"
const splitValue = fixed.split(".");
const val = splitValue[0]; // bagian ribuan
const decimal = splitValue[1]; // bagian desimal
const formatted = val.replace(/\B(?=(\d{3})+(?!\d))/g, ".");
return `${formatted},${decimal}`;
},
formatDate(date) {
if (!date) return null;
const [year, month, day] = date.split("-");
return `${day}-${month}-${year}`;
},
formatRupiah(angka) {
const format = new Intl.NumberFormat("id-ID", {
style: "currency",
currency: "IDR",
minimumFractionDigits: 0,
});
return "Rp " + format.format(angka).replace("Rp", "").trim();
},
},
};
</script>
<style scoped>
.label-value subheading mb-2 {
display: flex;
flex-direction: column;
margin-bottom: 1rem;
}
.label {
font-weight: bold;
margin-bottom: 0.25rem;
}
.value {
font-size: 1rem;
}
</style>

View File

@@ -0,0 +1,713 @@
<template>
<div>
<v-dialog v-model="dialogDelete" persistent width="500">
<v-card>
<v-card-title class="headline grey lighten-2" primary-title>
KONFIRMASI
</v-card-title>
<v-card-text>
Apakah anda yakin untuk menghapus
<span style="font-weight: bold;">{{
selectedPO.PurchaseOrderNumber
}}</span>
??
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="red" :disabled="loading" :loading="loading" flat @click="dialogDelete = false">
Tidak
</v-btn>
<v-btn color="green" :disabled="loading" :loading="loading" flat @click="deletePO()">
Ya
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
<v-dialog v-model="dialogConfirmation" persistent width="500">
<v-card>
<v-card-title class="headline grey lighten-2" primary-title>
KONFIRMASI
</v-card-title>
<v-card-text>
Apakah anda yakin untuk mengunci
<span style="font-weight: bold;">{{
selectedPO.PurchaseOrderNumber
}}</span>
untuk melanjutkan ke proses approve?
<p style="font-style: italic;" class="mt-3">
*Setelah dikunci PO tidak dapat di edit
</p>
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="red" :disabled="loading" :loading="loading" flat @click="dialogConfirmation = false">
Tidak
</v-btn>
<v-btn color="green" :disabled="loading" :loading="loading" flat @click="requestOrder()">
Ya
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
<v-snackbar v-model="snackbar.state" :color="snackbar.type" :timeout="3000" multi-line top>
{{ snackbar.message }}
<v-btn flat @click="snackbar.state = false">
Close
</v-btn>
</v-snackbar>
<v-toolbar color="primary" dark>
<v-toolbar-title class="white--text">PURCHASE ORDER APPROVE INVENTARIS</v-toolbar-title>
<v-spacer></v-spacer>
<v-btn v-if="(flag == 'G')" @click="goBack()" color="orange darken-2" title="Kembali ke listing pending approval" dark>
<v-icon dark left>arrow_back</v-icon>Back
</v-btn>
</v-toolbar>
<v-card>
<v-layout row wrap class="px-2 py-2">
<v-flex xs3>
<v-menu v-model="menuSelectedDate" :close-on-content-click="false" transition="scale-transition"
:nudge-right="40" lazy offset-y max-width="290px" min-width="290px">
<template v-slot:activator="{ on }">
<v-text-field :value="selectedDateFormatted" label="Tanggal Mulai" readonly class="mr-2"
outline hide-details v-on="on"></v-text-field>
</template>
<v-date-picker no-title hide-details v-model="selectedDate"
@input="menuSelectedDate = false"></v-date-picker>
</v-menu>
</v-flex>
<v-flex xs3>
<v-menu v-model="menuSelectedDateEnd" :close-on-content-click="false" transition="scale-transition"
:nudge-right="40" lazy offset-y max-width="290px" min-width="290px">
<template v-slot:activator="{ on }">
<v-text-field :value="endDateFormatted" label="Tanggal Akhir" readonly class="mr-2" outline
hide-details v-on="on"></v-text-field>
</template>
<v-date-picker no-title hide-details v-model="selectedDateEnd"
@input="menuSelectedDateEnd = false"></v-date-picker>
</v-menu>
</v-flex>
<v-flex xs3>
<v-select :items="statusOptions" label="Status" hide-details class="mini-select mr-2" v-model="selectedStatus"
item-text="title" return-object outline></v-select>
</v-flex>
<v-flex xs3>
<v-text-field v-model="search" label="Cari..." placeholder="NO. PO" class="mr-2" outline hide-details>
</v-text-field>
</v-flex>
</v-layout>
</v-card>
<v-card class="pa-2 mt-2">
<div style="height: 60vh; overflow-y: scroll;">
<v-data-table :headers="headers" :items="poList" :loading="loading" hide-actions class="elevation-1">
<template v-slot:items="props">
<td class="text-xs-center">{{ props.item.PurchaseOrderNumber }}</td>
<td class="text-xs-center">{{ props.item.PurchaseOrderDate }}</td>
<td class="text-xs-left">{{ props.item.SupplierName }}</td>
<td class="text-xs-center">
<p class="my-0 p-0">
<kbd>{{ props.item.PurchaseOrderWarehouseType }}</kbd>
</p>
<p class="my-0 p-0">
{{ props.item.WarehouseName }}
</p>
</td>
<td class="text-xs-left">{{ props.item.PurchaseOrderNote }}</td>
<td class="text-xs-right">
Rp. {{ props.item.PurchaseOrderGrandTotal != null ? oneMoney(props.item.PurchaseOrderGrandTotal) : '0' }}
</td>
<td class="text-xs-center">
<v-chip color="blue" v-if="props.item.PurchaseOrderStatus === 'Draft'" text-color="white">{{
props.item.PurchaseOrderStatus }}
</v-chip>
<v-chip color="warning" v-else-if="props.item.PurchaseOrderStatus === 'Pending'" text-color="white">{{
props.item.PurchaseOrderStatus }}
</v-chip>
<v-chip color="green" v-else-if="props.item.PurchaseOrderStatus === 'Approved'" text-color="white">{{
props.item.PurchaseOrderStatus }}
</v-chip>
<v-chip color="red" v-else-if="props.item.PurchaseOrderStatus === 'Rejected'" text-color="white">{{
props.item.PurchaseOrderStatus }}
</v-chip>
<v-chip color="primary" v-else-if="props.item.PurchaseOrderStatus === 'Completed'" text-color="white">{{
props.item.PurchaseOrderStatus }}
</v-chip>
<v-chip v-else text-color="white">{{ props.item.PurchaseOrderStatus }}
</v-chip>
</td>
<td class="text-xs-center">
<!-- Belum Approve -->
<div v-if="props.item.PurchaseOrderStatus === 'Pending'">
<v-btn
:disabled="loading || props.item.PurchaseOrderStatus == 'Approved' || approve_level != '1'"
@click="approvePO(props.item)" round color="primary" small :outline="isApproved(props.item, 'M')"
>
{{ props.item.PurchaseOrderApprovedManagerUserID == '0' ? 'Approve (Manager)' : 'Approved (Manager)'}}
<v-icon
small right dark
v-if="props.item.PurchaseOrderApprovedManagerUserID != '0'"
>done_all</v-icon>
</v-btn>
<v-btn
:disabled="loading || props.item.PurchaseOrderStatus == 'Approved' || approve_level != '2'"
@click="approvePO(props.item)" round color="primary" small :outline="isApproved(props.item, 'K')"
>
Approve (Kepala Reg)
<v-icon
small right dark
>done</v-icon>
</v-btn>
<v-tooltip bottom>
<template v-slot:activator="{ on }">
<v-btn icon :disabled="loading" @click="openDialogView(props.item)" v-on="on">
<v-icon color="blue">visibility</v-icon>
</v-btn>
</template>
<span>View PO</span>
</v-tooltip>
<v-tooltip bottom>
<template v-slot:activator="{ on }">
<v-btn icon :disabled="loading || props.item.PurchaseOrderStatus == 'Approve'" @click="openDialogEdit(props.item)" v-on="on">
<v-icon color="blue">edit</v-icon>
</v-btn>
</template>
<span>Edit PO</span>
</v-tooltip>
</div>
<div v-if="props.item.PurchaseOrderStatus == 'Approved'">
<v-tooltip bottom>
<template v-slot:activator="{ on }">
<v-btn icon :disabled="loading" @click="openDialogView(props.item)" v-on="on">
<v-icon color="blue">visibility</v-icon>
</v-btn>
</template>
<span>View PO</span>
</v-tooltip>
<v-tooltip bottom>
<template v-slot:activator="{ on }">
<v-btn icon :disabled="loading" @click="doPrint(props.item)" v-on="on">
<v-icon color="red">picture_as_pdf</v-icon>
</v-btn>
</template>
<span>PDF PO</span>
</v-tooltip>
</div>
</td>
</template>
</v-data-table>
</div>
</v-card>
<v-card class="text-xs-left pa-2">
<v-pagination v-model="selectedPage" :length="totalPage"></v-pagination>
</v-card>
<po-form></po-form>
<po-view></po-view>
<one-dialog-print :title="printtitle" :width="printwidth" :height="700" :status="openprint" :urlprint="urlprint"
@close-dialog-print="openprint = false"></one-dialog-print>
</div>
</template>
<style scoped>
.date-type-table {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.flex-items-center {
display: flex;
align-items: center;
gap: 0.25rem;
}
.table.v-table tbody td,
.table.v-table tbody tr {
height: 40px;
}
.table.v-table thead tr {
height: 40px;
}
</style>
<script>
module.exports = {
components: {
"po-form": httpVueLoader("./poForm.vue"),
"po-view": httpVueLoader("./dialogView.vue"),
'one-dialog-print': httpVueLoader('../../common/oneDialogPrintX.vue')
},
data() {
return {
menuSelectedDate: false,
menuSelectedDateEnd: false,
msgAlertDeleteOrReject: "",
dialogAlertRejectRequest: false,
dialogAlertDeleteDetail: false,
amountRules: [(v) => v >= 0 || "Jumlah harus diisi"],
validationDetail: false,
formatreport: "pdf",
urlprint: "",
printtitle: '',
printwidth: '100%',
headers: [
{
text: "NO PO",
align: "center",
sortable: false,
value: "no",
width: "5%",
class: "blue lighten-3 white--text",
},
{
text: "TANGGAL",
align: "center",
sortable: false,
value: "no",
width: "10%",
class: "blue lighten-3 white--text",
},
{
text: "VENDOR",
align: "center",
sortable: false,
value: "no",
width: "20%",
class: "blue lighten-3 white--text",
},
{
text: "GUDANG",
align: "center",
sortable: false,
value: "no",
width: "15%",
class: "blue lighten-3 white--text",
},
{
text: "KETERANGAN",
align: "center",
sortable: false,
value: "",
width: "20%",
class: "blue lighten-3 white--text",
},
{
text: "TOTAL",
align: "center",
sortable: false,
value: "",
width: "10%",
class: "blue lighten-3 white--text",
},
{
text: "STATUS",
align: "center",
sortable: false,
value: "",
width: "10%",
class: "blue lighten-3 white--text",
},
{
text: "AKSI",
align: "center",
sortable: false,
value: "",
width: "15%",
class: "blue lighten-3 white--text",
},
],
detailHeaders: [
{
text: "KODE ITEM",
align: "center",
sortable: false,
value: "no",
width: "15%",
class: "blue lighten-3 white--text",
},
{
text: "NAMA ITEM",
align: "left",
sortable: false,
value: "requestDate",
width: "35%",
class: "blue lighten-3 white--text",
},
{
text: "QTY",
align: "left",
sortable: false,
value: "requestDate",
width: "15%",
class: "blue lighten-3 white--text",
},
{
text: "HARGA",
align: "left",
sortable: false,
value: "requestDate",
width: "25%",
class: "blue lighten-3 white--text",
},
],
};
},
mounted() {
this.$store.dispatch("po/searchData");
this.$store.dispatch("po/getItemCategory");
this.$store.dispatch("po/getApprovalLevel");
},
computed: {
flag() {
return this.$store.state.po.flag;
},
status() {
return this.$store.state.po.status;
},
xstartdate() {
return this.$store.state.po.xstartdate;
},
statusOptions() {
return this.$store.state.po.statusOptions;
},
selectedDate: {
get() {
return this.$store.state.po.selectedDate;
},
set(val) {
this.$store.commit("po/update_selectedDate", val);
this.$store.dispatch("po/searchData");
},
},
selectedStatus: {
get() {
return this.$store.state.po.selectedStatus;
},
set(val) {
this.$store.commit("po/update_selectedStatus", val);
this.$store.dispatch("po/searchData");
},
},
statusOptions: {
get() {
return this.$store.state.po.statusOptions;
},
set(val) {
this.$store.commit("po/update_statusOptions", val);
},
},
selectedPO: {
get() {
return this.$store.state.po.selectedPO;
},
set(val) {
this.$store.commit("po/update_selectedPO", val);
},
},
dialogConfirmation: {
get() {
return this.$store.state.po.dialogConfirmation;
},
set(val) {
this.$store.commit("po/update_dialogConfirmation", val);
},
},
selectedDateEnd: {
get() {
return this.$store.state.po.selectedDateEnd;
},
set(val) {
this.$store.commit("po/update_selectedDateEnd", val);
this.$store.dispatch("po/searchData");
},
},
search: {
get() {
return this.$store.state.po.search;
},
set(val) {
this.$store.commit("po/update_search", val);
this.$store.dispatch("po/searchData");
},
},
selectedDateFormatted() {
return this.formatDate(this.selectedDate);
},
endDateFormatted() {
return this.formatDate(this.selectedDateEnd);
},
poList() {
return this.$store.state.po.poList;
},
snackbar: {
get() {
return this.$store.state.po.snackbar;
},
set(val) {
this.$store.commit("po/update_snackbar", val);
},
},
totalPage: {
get() {
return this.$store.state.po.totalPage;
},
set(val) {
this.$store.commit("po/update_totalPage", val);
},
},
selectedPage: {
get() {
return this.$store.state.po.selectedPage;
},
set(val) {
this.$store.commit("po/update_selectedPage", val);
this.$store.dispatch("po/searchData");
},
},
loading: {
get() {
return this.$store.state.po.loading;
},
set(val) {
this.$store.commit("po/update_loading", val);
},
},
dialogForm: {
get() {
return this.$store.state.po.dialogForm;
},
set(val) {
this.$store.commit("po/update_dialogForm", val);
},
},
dialogFormAct: {
get() {
return this.$store.state.po.dialogFormAct;
},
set(val) {
this.$store.commit("po/update_dialogFormAct", val);
},
},
dialogDelete: {
get() {
return this.$store.state.po.dialogDelete;
},
set(val) {
this.$store.commit("po/update_dialogDelete", val);
},
},
dialogView: {
get() {
return this.$store.state.po.dialogView;
},
set(val) {
this.$store.commit("po/update_dialogView", val);
},
},
openprint: {
get() {
return this.$store.state.po.open_print;
},
set(val) {
this.$store.commit("po/update_open_print", val);
},
},
approve_level() {
return this.$store.state.po.approve_level
}
},
methods: {
goBack() {
window.history.back();
// location.href = "/one-ui/test/vuex/one-accone-approve-all/"
},
doPrint(val) {
// console.log(val)
this.printwidth = 1028
this.printtitle = ""
let user = one_user()
tm = Date.now()
var rptname = 'rpt_po_001'
var formatrpt = this.formatreport
this.urlprint = "/birt/run?__report=report/one/accounting/" + rptname + ".rptdesign&__format=" + formatrpt + "&PID=" + val.PurchaseOrderID + "&username=" + user.M_StaffName + "&tm=" + tm
// console.log(this.urlprint)
this.$store.commit("po/update_open_print", true)
},
roundToThreeSignificantDigits(num) {
if (num === 0) return 0;
// Hitung jumlah digit
const absNum = Math.abs(num);
const magnitude = Math.floor(Math.log10(absNum)) + 1;
// Jika kurang dari 3 digit, tidak perlu dibulatkan
if (magnitude <= 3) return num;
// Hitung faktor pembulatan
const factor = Math.pow(10, magnitude - 3);
// Bulatkan
return Math.round(num / factor) * factor;
},
oneMoney(value) {
//return one_money(value);
// let splitValue = value.toString().split(".");
// if(splitValue.length > 1) {
// let val = splitValue[0]
// return val.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".") + "," + this.roundToThreeSignificantDigits(splitValue[1]);
// } else {
// return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".");
// }
// Ubah ke float jika belum angka
if (typeof value !== 'number') {
value = parseFloat(value);
}
if (isNaN(value)) return '0,00';
// Bulatkan dulu ke 2 desimal
const fixed = value.toFixed(2); // hasil string, misal "16200000.00" atau "123456.70"
const splitValue = fixed.split(".");
const val = splitValue[0]; // bagian ribuan
const decimal = splitValue[1]; // bagian desimal
const formatted = val.replace(/\B(?=(\d{3})+(?!\d))/g, ".");
return `${formatted},${decimal}`;
},
openDialogConfirmation(data) {
this.selectedPO = data;
this.dialogConfirmation = true;
},
openDialogDelete(data) {
this.selectedPO = data;
this.dialogDelete = true;
},
async requestOrder() {
await this.$store.dispatch("po/requestOrder");
await this.$store.dispatch("po/searchData");
// Wait for DOM to update
this.$nextTick(() => {
this.$forceUpdate();
});
},
deletePO() {
this.$store.dispatch("po/deleteOrder");
},
openDialogAdd() {
this.$store.dispatch("po/resetForm");
this.dialogForm = true;
},
openDialogView(data) {
this.selectedPO = data;
this.$store.dispatch("po/resetForm");
this.dialogView = true;
this.$store.dispatch("po/getItemUpdate");
},
openDialogEdit(data) {
this.selectedPO = data;
this.dialogFormAct = "EDIT";
this.dialogForm = true;
this.$store.dispatch("po/assignEdit");
this.$store.dispatch("po/getItemUpdate");
},
formatRupiah(angka) {
const format = new Intl.NumberFormat("id-ID", {
style: "currency",
currency: "IDR",
minimumFractionDigits: 0,
});
return "Rp " + format.format(angka).replace("Rp", "").trim();
},
formatDate(date) {
if (!date) return null;
const [year, month, day] = date.split("-");
return `${day}-${month}-${year}`;
},
deFormatedDate(date) {
if (!date) return null;
const [day, month, year] = date.split("-");
return `${year}-${month.padStart(2, "0")}-${day.padStart(2, "0")}`;
},
async approvePO(data) {
try {
if (this.approve_level == '1' && data.PurchaseOrderApprovedManagerUserID != '0') {
this.snackbar = {
state: true,
type: "warning",
message: "Sudah diapprove oleh manager"
};
return;
}
if (data.PurchaseOrderID != '' && data.PurchaseOrderStatus != 'Approved') {
await this.$store.dispatch("po/approveOrder", { poID: data.PurchaseOrderID });
setTimeout(() => {
window.location.reload();
}, 1000); // Short delay to allow the snackbar to be visible
}
} catch (error) {
console.error("Error approving order:", error);
this.snackbar = {
state: true,
type: "error",
message: "Gagal mengapprove Purchase Order"
};
}
},
isApproved(data, type) {
if (!data) {
return false
}
if (data.PurchaseOrderStatus == 'Approved') {
return false
}
if (type == 'M') {
if (data.PurchaseOrderApprovedManagerUserID == '0') {
return true
} else {
return false
}
}
if (type == 'K') {
return true
}
return true
}
},
watch: {
dialogApprove(val, old) { },
},
};
</script>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,411 @@
/**
* Utility functions for the ACC One Purchase Order application
*/
// /**
// * Groups an array of objects by a specified key
// * @param {Array} array - The array of objects to group
// * @param {String} key - The key to group by
// * @returns {Object} - An object with keys representing the grouped values and arrays as values
// */
// export const groupBy = (array, key) => {
// return array.reduce((result, item) => {
// const groupKey = item[key];
// if (!result[groupKey]) {
// result[groupKey] = [];
// }
// result[groupKey].push(item);
// return result;
// }, {});
// };
/**
* Groups an array of objects by one or multiple keys
* @param {Array} array - The array of objects to group
* @param {Function|String|Array} key - The key(s) to group by. Can be a string, array of strings, or a function.
* @returns {Object} - An object with keys representing the grouped values and arrays as values
*/
export const groupBy = (array, key) => {
return array.reduce((result, item) => {
let groupKey;
// Handle single key (string), multiple keys (array), or custom function
if (typeof key === 'function') {
groupKey = key(item);
} else if (Array.isArray(key)) {
groupKey = key.map(k => item[k]).join('_'); // Combine multiple keys with underscore
} else {
groupKey = item[key];
}
if (!result[groupKey]) {
result[groupKey] = [];
}
result[groupKey].push(item);
return result;
}, {});
};
/**
* Groups purchase request data by M_ItemID
* Terjadi jika ada beberapa item yang sama, maka akan digabungkan berdasarkan M_ItemID dan PoItemUnitID
* @param {Array} purchaseRequestData - Array of purchase request objects
* @returns {Array} - Array of objects with M_ItemID, M_ItemCode, M_ItemDesc, unit information, converted PoQty, and Details array
*/
export const groupPurchaseRequestsByItemId = (purchaseRequestData) => {
const grouped = groupBy(purchaseRequestData, ['M_ItemID', 'PoItemUnitID']);
// console.log("grouped");
// console.log(grouped);
return Object.keys(grouped).map(itemId => {
const items = grouped[itemId];
const firstItem = items[0];
/* Sebelum Kalkulasi Konversi Item di BE */
// // Calculate total PoQty from all items
// const totalPoQty = calculateTotalQuantity(items, 'PoQty');
// // Get the conversion factor from the first item
// const conversionFactor = Number(firstItem.DefaultPurchase.UnitConvertAmount) || 1;
// // Convert the total quantity and round up if it's a decimal
// const convertedPoQty = Math.ceil(convertUnits(totalPoQty, conversionFactor));
/* Sesudah Kalkulasi Konversi Item di BE getItem() */
const totalPoQty = calculateTotalQuantity(items, 'PoQty')
// console.log("Total PoQty for itemId", itemId, " : ", totalPoQty);
// get price real or default supplier price
const realPrice = Number(firstItem.RealPrice ?? firstItem.DefaultPurchase.SupplierPricePrice) || 0;
// let price = 0;
// calculagte price after discount
let priceAfterDiscount = realPrice;
if (parseFloat(firstItem.discount) > 0) {
if (firstItem.discountType === 'P') {
priceAfterDiscount = realPrice - (Number(firstItem.discount) * (realPrice / 100));
}
if (firstItem.discountType === 'R') {
priceAfterDiscount = realPrice - Number(firstItem.discount);
}
} else {
priceAfterDiscount = realPrice || 0;
}
// Get the price from the first item
// const realPrice = Number(firstItem.DefaultPurchase.SupplierPricePrice) || 0;
// Calculate the total (PoQty * priceAfterDiscount)
const total = totalPoQty * priceAfterDiscount;
const itemParts = itemId.split('_');
const M_ItemID = itemParts[0];
return {
keyID: itemId,
M_ItemID: M_ItemID,
PurchaseOrderID: firstItem.PurchaseOrderID ?? 0,
PurchaseOrderSummaryID: firstItem.PurchaseOrderSummaryID ?? 0,
M_ItemCode: firstItem.M_ItemCode,
M_ItemDesc: firstItem.M_ItemDesc,
discount: firstItem.discount,
discountType: firstItem.discountType,
PoItemUnitID: firstItem.DefaultPurchase.ItemUnitID,
ItemUnitCode: firstItem.DefaultPurchase.ItemUnitCode,
PoItemUnitName: firstItem.DefaultPurchase.ItemUnitName,
TotalPoQty: totalPoQty,
Price: priceAfterDiscount,
RealPrice: realPrice,
PriceAfterDiscount: priceAfterDiscount,
Total: total,
Details: items
};
});
};
/**
* Formats a number as currency (IDR)
* @param {Number} amount - The amount to format
* @returns {String} - Formatted currency string
*/
export const formatCurrency = (amount) => {
return new Intl.NumberFormat('id-ID', {
style: 'currency',
currency: 'IDR',
minimumFractionDigits: 0
}).format(amount);
};
/**
* Formats a date to a localized string
* @param {Date|String} date - The date to format
* @param {Object} options - Intl.DateTimeFormat options
* @returns {String} - Formatted date string
*/
export const formatDate = (date, options = {
year: 'numeric',
month: 'long',
day: 'numeric'
}) => {
if (!date) return '';
const dateObj = typeof date === 'string' ? new Date(date) : date;
return new Intl.DateTimeFormat('id-ID', options).format(dateObj);
};
/**
* Calculates the total value of purchase requests
* @param {Array} items - Array of purchase request items
* @returns {Number} - Total value
*/
export const calculateTotal = (items) => {
return items.reduce((sum, item) => sum + (Number(item.Total) || 0), 0);
};
/**
* Calculates the total quantity of items
* @param {Array} items - Array of purchase request items
* @param {String} qtyField - The field name containing quantity (e.g., 'PoQty')
* @returns {Number} - Total quantity
*/
export const calculateTotalQuantity = (items, qtyField = 'PoQty') => {
// console.log("Items in calculateTotalQuantity:", items);
return items.reduce((sum, item) => sum + (Number(item[qtyField]) || 0), 0);
};
/**
* Converts units based on the conversion factor
* @param {Number} quantity - The quantity to convert
* @param {Number} conversionFactor - The conversion factor
* @returns {Number} - Converted quantity
*/
export const convertUnits = (quantity, conversionFactor) => {
return quantity / conversionFactor;
};
/**
* Filters purchase requests by branch
* @param {Array} items - Array of purchase request items
* @param {String|Array} branchCodes - Branch code(s) to filter by
* @returns {Array} - Filtered items
*/
export const filterByBranch = (items, branchCodes) => {
if (!branchCodes) return items;
const codes = Array.isArray(branchCodes) ? branchCodes : [branchCodes];
return items.filter(item => codes.includes(item.BranchCode));
};
/**
* Filters purchase requests by regional
* @param {Array} items - Array of purchase request items
* @param {String|Array} regionalIds - Regional ID(s) to filter by
* @returns {Array} - Filtered items
*/
export const filterByRegional = (items, regionalIds) => {
if (!regionalIds) return items;
const ids = Array.isArray(regionalIds) ? regionalIds : [regionalIds];
return items.filter(item => ids.includes(item.S_RegionalID));
};
/**
* Validates if a purchase request item has all required fields
* @param {Object} item - Purchase request item
* @returns {Boolean} - True if valid, false otherwise
*/
export const validatePurchaseRequestItem = (item) => {
const requiredFields = [
'M_ItemID',
'M_ItemCode',
'M_ItemDesc',
'Price',
'RequestQty'
];
return requiredFields.every(field => item[field] !== undefined && item[field] !== null);
};
/**
* Sorts purchase request items by a specified field
* @param {Array} items - Array of purchase request items
* @param {String} field - Field to sort by
* @param {Boolean} ascending - Sort direction (true for ascending, false for descending)
* @returns {Array} - Sorted items
*/
export const sortPurchaseRequests = (items, field = 'M_ItemDesc', ascending = true) => {
return [...items].sort((a, b) => {
const valueA = a[field];
const valueB = b[field];
if (typeof valueA === 'string' && typeof valueB === 'string') {
return ascending
? valueA.localeCompare(valueB)
: valueB.localeCompare(valueA);
}
return ascending
? (valueA - valueB)
: (valueB - valueA);
});
};
/**
* Validates purchase order data before saving
* @param {Object} context - Vuex context object
* @returns {Boolean} - Returns true if validation passes, false otherwise
*/
export const validatePurchaseOrder = (context) => {
if (context.state.loading) {
let snackbar = {
state: true,
type: "warning",
message: 'Loading sedang berlangsung harap menunggu ...',
};
context.commit("update_snackbar", snackbar);
return false;
}
let warningMsg = [];
if (context.state.selectedItem.length == 0) {
warningMsg.push('Belum memilih item');
}
if (!context.state.refNumber || context.state.refNumber.trim() === '') {
warningMsg.push('Nomor Referensi belum diisi');
}
if (!context.state.selectedWarehouse || !context.state.selectedWarehouse.WarehouseID && context.state.warehouseType !== 'Multiple') {
warningMsg.push('Tipe Gudang Single Harus memilih Gudang');
}
if (!context.state.selectedSupplier || !context.state.selectedSupplier.SupplierID) {
warningMsg.push('Supplier belum dipilih');
}
if (context.state.discountType === 'Percentage') {
const discountValue = (context.state.itemTotal.total * context.state.discountAmount) / 100;
if (discountValue > context.state.itemTotal.total) {
warningMsg.push('Diskon tidak boleh melebihi total');
}
} else if (context.state.discountType === 'Absolute') {
if (context.state.discountAmount > context.state.itemTotal.total) {
warningMsg.push('Diskon tidak boleh melebihi total');
}
}
context.state.summary.forEach(element => {
if (Number(element.discount) < 0) {
warningMsg.push('Diskon ' + element.M_ItemDesc + ' tidak boleh kurang dari 0');
}
if (element.discountType === 'P') {
if (Number(element.discount) > 100) {
warningMsg.push('Diskon per item ' + element.M_ItemDesc + ' tidak boleh melebihi 100');
}
}
if (element.discountType === 'R') {
if (Number(element.discount) > Number(element.RealPrice)) {
warningMsg.push('Diskon per item ' + element.M_ItemDesc + ' tidak boleh melebihi dari harga');
}
}
});
if (warningMsg.length > 0) {
let snackbar = {
state: true,
type: "warning",
message: warningMsg.join(", "),
};
context.commit("update_snackbar", snackbar);
return false;
}
return true;
};
/**
* Menghitung total summary untuk purchase order
* @param {Array} summary - Array data summary
* @param {Number} taxPpn - Persentase pajak PPN
* @param {Number} taxPph - Persentase pajak PPH
* @param {String} discountType - Tipe diskon ('Percentage' atau 'Absolute')
* @param {Number} discountAmount - Jumlah diskon
* @returns {Object} - Object summaryTotal
*/
export const calculateSummaryTotal = (summary, typePpnSelected = 'Percentage', taxPpn = 0, taxPph = 0, discountType = 'Percentage', discountAmount = 0) => {
if (!summary || summary.length === 0) {
return {
total: 0,
tax: 0,
ppn: 0,
pph: 0,
discount: 0,
finalTotal: 0,
};
}
// Hitung total dari item summary
const total = summary.reduce((acc, item) => acc + (Number(item.Total) || 0), 0);
// Hitung diskon berdasarkan tipe
let discount = discountAmount;
if (discountType === 'Percentage') {
discount = (discountAmount / 100) * total;
}
// Hitung pajak
const newTotal = total - discount;
let ppn = taxPpn;
if (typePpnSelected === 'Percentage' && taxPpn > 0) {
ppn = (taxPpn / 100) * newTotal;
}
const pph = (taxPph / 100) * newTotal;
const tax = ppn + pph;
const finalTotal = newTotal + tax;
// Return object summaryTotal
return {
total: total,
tax: tax,
ppn: ppn,
pph: pph,
discount: discount,
finalTotal: finalTotal,
};
};
/**
* Menghapus item dari summary dan selectedItem berdasarkan itemId atau detailId
* @param {Array} summary - Array data summary
* @param {Array} selectedItem - Array data selectedItem
* @param {String} itemId - ID item yang akan dihapus (opsional)
* @param {String} detailId - ID detail yang akan dihapus (opsional)
* @returns {Object} - Object berisi summary dan selectedItem yang sudah diupdate
*/
export const deleteItemFromSummary = (summary, selectedItem, itemId = null, detailId = null) => {
// Jika itemId ada, hapus seluruh item dan detailsnya
if (itemId) {
const newSummary = summary.filter(item => item.M_ItemID !== itemId);
const newSelectedItem = selectedItem.filter(item => item.M_ItemID !== itemId);
return {
summary: newSummary,
selectedItem: newSelectedItem
};
}
// Jika detailId ada, hapus detail spesifik
if (detailId) {
// Hapus dari selectedItem
const newSelectedItem = selectedItem.filter(item => item.PurchaseRequestFlagID !== detailId);
// Regenerate summary dari selectedItem yang baru
const newSummary = groupPurchaseRequestsByItemId(newSelectedItem);
return {
summary: newSummary,
selectedItem: newSelectedItem
};
}
return {
summary,
selectedItem
};
};

View File

@@ -0,0 +1,69 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="../../../libs/vendor/css/google-fonts.css">
<link rel="stylesheet" href="../../../libs/vendor/css/icomoon-fonts.css">
<link rel="stylesheet" href="../../../libs/vendor/css/vuetify.min.css">
<title>One</title>
</head>
<body>
<div v-cloak id="app">
<v-app id="smartApp">
<one-navbar></one-navbar>
<v-content style="background: #F5E8DF!important">
<v-container fluid fill-height class="pl-1 pr-1 pt-2 pb-2">
<v-layout row wrap>
<v-flex xs12 class="left" fill-height pa-1>
<po></po>
</v-flex>
</v-layout>
</v-container>
</v-content>
<one-footer></one-footer>
</v-app>
</div>
<!-- Vendor -->
<script src="../../../libs/vendor/moment.min.js"></script>
<script src="../../../libs/vendor/numeral.min.js"></script>
<script src="../../../libs/vendor/moment-locale-id.js"></script>
<script src="../../../libs/vendor/lodash.js"></script>
<script src="../../../libs/vendor/axios.min.js"></script>
<script src="../../../libs/vendor/vue.js"></script>
<script src="../../../libs/vendor/vuex.js"></script>
<script src="../../../libs/vendor/vuetify.js"></script>
<script src="../../../libs/vendor/httpVueLoader.js"></script>
<script src="../../../libs/one_global.js"></script>
<!-- App Script -->
<script type="module">
import {
store
} from './store.js';
window.store = store;
new Vue({
store,
el: "#app",
methods: {},
components: {
'one-navbar': httpVueLoader('../../../apps/components/oneNavbarComponent.vue'),
'one-footer': httpVueLoader('../../../apps/components/oneFooter.vue'),
// 'request-listing': httpVueLoader('./components/requestListing.vue'),
// 'request-kacab': httpVueLoader('./components/acconeprkacab.vue'),
'po': httpVueLoader('./components/po.vue')
}
})
</script>
<style>
[v-cloak] {
display: none
}
</style>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,14 @@
// import manager from "./modules/manager.js";
// import prkacab from "./modules/prkacab.js"
import system from "../../../apps/modules/system/system.js";
import po from "./modules/po.js";
export const store = new Vuex.Store({
modules: {
po: po,
system: system
},
state: {},
mutations: {},
actions: {},
});

View File

@@ -0,0 +1,162 @@
const URL = "/one-api/mockup/purchase/order/PurchaseOrderService/";
const URLRO = "/one-api/mockup/receive-item-po/ReceiveOrderService/";
export async function getDaftarCabang(params) {
try {
var response = await axios.post(URL + "getDaftarCabang", params);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText
};
}
let data = response.data;
return data;
} catch (error) {
return {
status: "ERR",
message: error.message
};
}
}
export async function getDaftarSupplier(params) {
try {
var response = await axios.post(URL + "getDaftarSupplier", params);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText
};
}
let data = response.data;
return data;
} catch (error) {
return {
status: "ERR",
message: error.message
};
}
}
export async function getDaftarPOJasa(params) {
try {
var response = await axios.post(URL + "getDaftarPOJasa", params);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText
};
}
let data = response.data;
return data;
} catch (error) {
return {
status: "ERR",
message: error.message
};
}
}
export async function getDataKontrakPOJasa(params) {
try {
var response = await axios.post(URL + "getDataKontrakPOJasa", params);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText
};
}
let data = response.data;
return data;
} catch (error) {
return {
status: "ERR",
message: error.message
};
}
}
export async function getUserApproveLevel(params) {
try {
var response = await axios.post(URL + "getUserApproveLevel", params);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText
};
}
let data = response.data;
return data;
} catch (error) {
return {
status: "ERR",
message: error.message
};
}
}
export async function updateApprovalPO(params) {
try {
var response = await axios.post(URL + "updateApprovalPO", params);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText
};
}
let data = response.data;
return data;
} catch (error) {
return {
status: "ERR",
message: error.message
};
}
}
export async function generatePOItemReceive(params) {
try {
const response = await axios.post(URLRO + "generatePOItemReceive", params);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText
};
}
const data = response.data;
return data;
} catch (error) {
return {
status: "ERR",
message: error.message
};
}
}
export async function getDaftarAttachment(params) {
try {
const response = await axios.post(URL + "getDaftarAttachment", params);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText
};
}
const data = response.data;
return data;
} catch (error) {
return {
status: "ERR",
message: error.message
};
}
}

View File

@@ -0,0 +1,364 @@
<template>
<v-dialog v-model="dialog_confirm" persistent width="70vw">
<v-card>
<v-card-title class="headline grey lighten-2">KONFIRMASI PO JASA</v-card-title>
<v-card-text style="max-height: 80vh; overflow-y: auto;">
<!-- first row -->
<v-layout row wrap>
<v-flex xs4>
<v-text-field
v-model="formattedPODate" hide-details
label="Tanggal PO" readonly outline
></v-text-field>
</v-flex>
<v-flex xs4 pl-2>
<v-text-field
v-model="selected_pojasa.SupplierName" hide-details
label="Vendor" readonly outline
></v-text-field>
</v-flex>
<v-flex xs4 pl-2>
<v-text-field
v-model="selected_pojasa.reference" hide-details
label="Referensi" readonly outline
></v-text-field>
</v-flex>
</v-layout>
<!-- second row -->
<v-layout row wrap mt-2>
<v-flex xs4>
<v-text-field
v-model="selected_pojasa.M_BranchName"
label="Cabang" readonly outline hide-details
></v-text-field>
</v-flex>
<v-flex xs2 pl-2>
<v-text-field
v-model="selected_pojasa.typepajak" hide-details
label="Pajak (PPN)" readonly outline
></v-text-field>
</v-flex>
<v-flex xs2 pl-2>
<v-text-field
v-if="selected_pojasa.typepajak == 'percent'"
v-model="selected_pojasa.valuepajak" hide-details
label="Jumlah Pajak" readonly outline suffix="%"
></v-text-field>
<v-text-field
v-else hide-details outline prefix="Rp."
v-model="formattedPajak"
label="Jumlah Pajak" readonly
></v-text-field>
</v-flex>
<v-flex xs2 pl-2>
<v-text-field
v-model="selected_pojasa.typediskon" hide-details
label="Diskon" readonly outline
></v-text-field>
</v-flex>
<v-flex xs2 pl-2>
<v-text-field
v-if="selected_pojasa.typediskon == 'percent'"
v-model="selected_pojasa.valuediskon" hide-details
label="Jumlah Diskon" readonly outline suffix="%"
></v-text-field>
<v-text-field
v-else hide-details outline prefix="Rp."
v-model="formattedDiskon"
label="Jumlah Diskon" readonly
></v-text-field>
</v-flex>
</v-layout>
<!-- third row -->
<v-layout row wrap mt-2>
<v-flex xs3>
<v-text-field
v-model="selected_pojasa.typekontrak" outline
label="Jenis Kontrak" readonly hide-details
></v-text-field>
</v-flex>
<v-flex xs3 pl-2>
<v-text-field
v-model="formattedKontrakStartDate" hide-details
label="Tanggal Mulai Kontrak" readonly outline
></v-text-field>
</v-flex>
<v-flex xs3 pl-2>
<v-text-field
v-model="formattedKontrakEndDate" hide-details
label="Tanggal Akhir Kontrak" readonly outline
></v-text-field>
</v-flex>
<v-flex xs3 pl-2>
<v-text-field
v-model="selected_pojasa.PIOutQty" hide-details
label="Jumlah PI keluar" readonly outline
></v-text-field>
</v-flex>
</v-layout>
<v-textarea
v-model="selected_pojasa.catatan" auto-grow readonly
rows="1" outline label="Catatan" hide-details class="mt-2"
></v-textarea>
<!-- detail table -->
<v-layout row wrap class="mt-2">
<v-flex xs12>
<v-data-table
:headers="headers" :items="selected_pojasa.detail" :expand="expand"
class="elevation-1" hide-actions item-key="M_ItemCode"
>
<template v-slot:items="props">
<tr @click="props.expanded = !props.expanded">
<td class="text-xs-center pa-2">
<v-icon>{{ props.expanded
? "keyboard_arrow_down"
: "keyboard_arrow_right"
}}</v-icon>
</td>
<td class="text-xs-center pa-2">{{ props.item.M_ItemDesc }}</td>
<td class="text-xs-center pa-2">{{ props.item.RequestQty }}</td>
<td class="text-xs-center pa-2">
Rp. {{ formatCurrency(props.item.SupplierPrice) }}
</td>
<td class="text-xs-center pa-2">
Rp. {{ formatCurrency(props.item.DiskonAmount) }}
</td>
<td class="text-xs-center pa-2">
Rp. {{ formatCurrency(props.item.EndPrice) }}
</td>
<td class="text-xs-center pa-2">
Rp. {{ formatCurrency(props.item.TempTotal) }}
</td>
</tr>
</template>
<template v-slot:expand="props">
<v-card flat>
<v-card-text>
<v-data-table
:headers="headers_detail" class="elevation-0"
:items="props.item.detail" hide-actions
>
<template v-slot:items="obj">
<tr>
<td class="text-xs-center pa-2">{{ obj.item.M_ItemDesc }}</td>
<td class="text-xs-center pa-2">{{ obj.item.PurchaseRequestNumber }}</td>
<td class="text-xs-center pa-2">{{ obj.item.M_BranchName }}</td>
<td class="text-xs-center pa-2">{{ obj.item.RequestQty }}</td>
<td class="text-xs-center pa-2">{{ obj.item.ItemUnitName }}</td>
<td class="text-xs-center pa-2">
{{ formatCurrency(obj.item.SupplierPrice) }}
</td>
</tr>
</template>
</v-data-table>
</v-card-text>
</v-card>
</template>
<template v-slot:footer>
<tr>
<td colspan="1" class="text-xs-left pa-2"></td>
<td colspan="5" class="text-xs-left pa-2">
<strong>JUMLAH</strong>
</td>
<td colspan="1" class="text-xs-center pa-2">
<strong>Rp. {{ formatCurrency(selected_pojasa.summary.subtotal) }}</strong>
</td>
</tr>
<tr>
<td colspan="1" class="text-xs-left pa-2"></td>
<td colspan="5" class="text-xs-left pa-2">
<strong>DISKON</strong>
</td>
<td colspan="1" class="text-xs-center pa-2">
<strong>Rp. {{ formatCurrency(selected_pojasa.summary.diskon) }}</strong>
</td>
</tr>
<tr>
<td colspan="1" class="text-xs-left pa-2"></td>
<td colspan="5" class="text-xs-left pa-2">
<strong>PAJAK</strong>
</td>
<td colspan="1" class="text-xs-center pa-2">
<strong>Rp. {{ formatCurrency(selected_pojasa.summary.pajak) }}</strong>
</td>
</tr>
<tr>
<td colspan="1" class="text-xs-left pa-2"></td>
<td colspan="5" class="text-xs-left pa-2">
<strong>TOTAL</strong>
</td>
<td colspan="1" class="text-xs-center pa-2">
<strong>Rp. {{ formatCurrency(selected_pojasa.summary.total) }}</strong>
</td>
</tr>
</template>
</v-data-table>
</v-flex>
</v-layout>
</v-card-text>
<v-card-actions>
<v-btn @click="viewAttachment()" color="info" class="white--text">Attachment</v-btn>
<v-spacer></v-spacer>
<v-btn @click="batalKonfirmasi()" color="error" class="white--text">Batal</v-btn>
<v-btn v-if="!detail_view" @click="KonfirmasiJasa()" color="primary" class="white--text">
{{ selected_pojasa.verifiedby == '0' ? "Verifikasi" : "Approve" }}
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script>
module.exports = {
data() {
return {
expand: false,
headers: [
{
text: "", align: "center", sortable: false,
value: "item", width: "5%", class: "pa-1 blue lighten-3 white--text",
},
{
text: "ITEM", align: "center", sortable: false,
value: "item", width: "20%", class: "pa-1 blue lighten-3 white--text",
},
{
text: "JUMLAH", align: "center", sortable: false,
value: "qty", width: "10%", class: "pa-1 blue lighten-3 white--text",
},
{
text: "HARGA", align: "center", sortable: false,
value: "price", width: "15%", class: "pa-1 blue lighten-3 white--text",
},
{
text: "DISKON", align: "center", sortable: false,
value: "disc", width: "20%", class: "pa-1 blue lighten-3 white--text",
},
{
text: "HARGA SETELAH DISKON", align: "center", sortable: false,
value: "disc", width: "15%", class: "pa-1 blue lighten-3 white--text",
},
{
text: "TOTAL", align: "center", sortable: false,
value: "disc", width: "15%", class: "pa-1 blue lighten-3 white--text",
},
],
headers_detail: [
{
text: "NAMA PRODUK", align: "center", sortable: false,
value: "prod", width: "25%", class: "pa-1 blue lighten-4 black--text",
},
{
text: "NO REQUEST", align: "center", sortable: false,
value: "noreq", width: "20%", class: "pa-1 blue lighten-4 black--text",
},
{
text: "REQUESTER", align: "center", sortable: false,
value: "req", width: "20%", class: "pa-1 blue lighten-4 black--text",
},
{
text: "JUMLAH", align: "center", sortable: false,
value: "qty", width: "10%", class: "pa-1 blue lighten-4 black--text",
},
{
text: "UNIT", align: "center", sortable: false,
value: "unit", width: "10%", class: "pa-1 blue lighten-4 black--text",
},
{
text: "HARGA", align: "center", sortable: false,
value: "price", width: "15%", class: "pa-1 blue lighten-4 black--text",
}
]
}
},
computed: {
loading_process() {
return this.$store.state.poservice.loading_process
},
selected_pojasa() {
return this.$store.state.poservice.selected_pojasa
},
formattedPODate() {
return this.formatDate(this.selected_pojasa.podate)
},
formattedKontrakStartDate() {
return this.formatDate(this.selected_pojasa.kontrakstart)
},
formattedKontrakEndDate() {
return this.formatDate(this.selected_pojasa.kontrakend)
},
formattedPajak() {
return this.formatCurrency(this.selected_pojasa.valuepajak)
},
formattedDiskon() {
return this.formatCurrency(this.selected_pojasa.valuediskon)
},
detail_view() {
return this.$store.state.poservice.detail_view
},
dialog_confirm: {
get() {
return this.$store.state.poservice.dialog_confirm
},
set(val) {
this.$store.commit("poservice/update_dialog_confirm", val)
}
},
snackbar: {
get() {
return this.$store.state.poservice.snackbar
},
set(val) {
this.$store.commit("poservice/update_snackbar", val)
}
}
},
methods: {
formatDate(date) {
if (!date) return null;
const [year, month, day] = date.split('-');
return `${day}-${month}-${year}`;
},
formatCurrency(value) {
const num = parseFloat(value);
if (isNaN(num)) return 0;
return num.toFixed(2).replace('.', ',').replace(/\B(?=(\d{3})+(?!\d))/g, ".");
},
viewAttachment() {
let item = this.selected_pojasa
let param = {
TJasaID: item.T_KontrakJasaID,
poID: item.PurchaseOrderID
}
this.$store.dispatch("poservice/lookupAttachment", param)
this.$store.commit("poservice/update_dialog_attachment", true)
},
batalKonfirmasi() {
this.$store.commit("poservice/update_selected_pojasa", {
summary: {
subtotal: 0.00,
diskon: 0.00,
pajak: 0.00,
total: 0.00
}
})
this.dialog_confirm = false
},
KonfirmasiJasa() {
if (!this.loading_process) {
this.$store.dispatch("poservice/updateApprovePO");
} else {
let snac = {color: 'warning', msg: 'proses sedang berjalan', state: true}
this.snackbar = snac
}
}
}
}
</script>

View File

@@ -0,0 +1,104 @@
<template>
<div>
<v-dialog v-model="dialog_attachment" persistent max-width="60vw">
<v-card>
<v-card-title class="headline grey lighten-2" primary-title>
VIEW ATTACHMENT
</v-card-title>
<v-card-text>
<v-layout row wrap>
<v-flex
v-for="(nota) in prview_attachment"
xs4 class="pa-2" :key="nota.attach_id"
>
<div style="position: relative; padding-bottom: 35px;">
<v-img
:src="makeImageURL(nota)" aspect-ratio="1" contain
class="grey lighten-2" @click="fullview(nota)"
></v-img>
</div>
</v-flex>
</v-layout>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn @click="tutupViewAttachment()" color="error" class="white--text">Tutup</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
<v-dialog v-model="dialog_fullview" persistent max-width="60vw">
<v-card>
<v-card-title class="headline grey lighten-2" primary-title>
{{ view_title }}
</v-card-title>
<v-card-text style="max-height: 80vh; overflow-y: auto;">
<div class="pa-2">
<v-img :src="view_url" contain class="grey lighten-2"></v-img>
</div>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn class="mr-2" color="red" flat outline @click="dialog_fullview = false">
Tutup
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</div>
</template>
<style>
.close-button {
position: absolute;
top: 5px;
right: 5px;
z-index: 1;
cursor: pointer;
}
</style>
<script>
module.exports = {
data() {
return {
dialog_fullview: false,
view_title: "",
view_url: ""
}
},
computed: {
dialog_attachment: {
get() {
return this.$store.state.poservice.dialog_attachment
},
set(val) {
this.$store.commit("poservice/update_dialog_attachment", val)
}
},
prview_attachment() {
return this.$store.state.poservice.prview_attachment
}
},
methods: {
makeImageURL(nota) {
const year = new Date(nota.created).getFullYear();
const baseURL = BASE_URL + `/one-media/order-jasa/${year}/`;
return baseURL + nota.img_url;
},
fullview(nota) {
this.view_title = nota.img_url;
this.view_url = this.makeImageURL(nota)
this.dialog_fullview = true;
},
tutupViewAttachment() {
this.view_title = ""
this.view_url = ""
this.dialog_attachment = false
}
},
watch: {
},
}
</script>

View File

@@ -0,0 +1,275 @@
<template>
<div>
<v-toolbar color="primary" dark>
<v-toolbar-title class="white--text">APPROVE PURCHASE ORDER JASA</v-toolbar-title>
<v-spacer></v-spacer>
</v-toolbar>
<v-card class="pa-2">
<v-layout row align-center>
<v-flex xs3>
<v-menu
v-model="menuStartdateFilter" offset-y lazy min-width="290px"
transition="scale-transition" max-width="290px" full-width
:nudge-right="40" :close-on-content-click="false"
>
<template v-slot:activator="{on}">
<v-text-field
v-model="formattedStartdate" label="Tanggal Awal"
hide-details readonly v-on="on" outline
></v-text-field>
</template>
<v-date-picker
v-model="filterjasa.startdate" no-title
@input="menuStartdateFilter = false"
></v-date-picker>
</v-menu>
</v-flex>
<v-flex xs3 pl-2>
<v-menu
v-model="menuEnddateFilter" offset-y lazy min-width="290px"
transition="scale-transition" max-width="290px" full-width
:nudge-right="40" :close-on-content-click="false"
>
<template v-slot:activator="{on}">
<v-text-field
v-model="formattedEnddate" label="Tanggal Akhir"
hide-details readonly v-on="on" outline
></v-text-field>
</template>
<v-date-picker
v-model="filterjasa.enddate" no-title
@input="menuEnddateFilter = false"
></v-date-picker>
</v-menu>
</v-flex>
<v-flex xs3 pl-2>
<v-autocomplete
:items="liststatus" hide-details outline
v-model="filterjasa.status" label="Status"
></v-autocomplete>
</v-flex>
<v-flex xs3 pl-2>
<v-text-field
v-model="filterjasa.search" hide-details outline
label="Cari" placeholder="cai nomor po..."
></v-text-field>
</v-flex>
</v-layout>
</v-card>
<v-card class="pa-2 mt-2">
<v-data-table
:headers="headers" :items="list_pojasa.records"
class="elevation-1" hide-actions
>
<template v-slot:items="props">
<tr>
<td class="text-xs-center pa-2">{{ props.item.PurchaseOrderNumber }}</td>
<td class="text-xs-center pa-2">{{ props.item.PurchaseOrderDate }}</td>
<td class="text-xs-center pa-2">{{ props.item.SupplierName }}</td>
<td class="text-xs-center pa-2">{{ props.item.M_BranchName }}</td>
<td class="text-xs-center pa-2">{{ props.item.PurchaseOrderNote }}</td>
<td class="text-xs-center pa-2">
Rp. {{ formatCurrency(props.item.PurchaseOrderGrandTotal) }}
</td>
<td class="text-xs-center pa-2">{{ props.item.PurchaseOrderStatus }}</td>
<td class="text-xs-center pa-2">
<v-layout
v-if="props.item.PurchaseOrderStatus != 'Draft'"
align-center justify-center row
>
<v-flex shrink pr-1>
<v-btn
color="warning" @click="viewdetail(props.item)" small
>
detail
<v-icon small right>list_alt</v-icon>
</v-btn>
<v-chip
v-if="props.item.approvedby != '0'"
label color="success" text-color="white"
>
APPROVED
</v-chip>
</v-flex>
<v-flex pl-1 v-if="props.item.approvedby == '0'">
<v-btn
color="info" @click="updateStatusPO(props.item)" small
:disabled="userinfo.M_UserM_ApproveLevelID != '1'"
:outline="props.item.verifiedby == '0'"
>
verifikasi
<v-icon small right>done</v-icon>
</v-btn>
<v-btn
color="success" @click="updateStatusPO(props.item)" small
:disabled="userinfo.M_UserM_ApproveLevelID != '2'"
:outline="props.item.PurchaseOrderStatus != 'Approved'"
>
approve
<v-icon small right>done_all</v-icon>
</v-btn>
</v-flex>
</v-layout>
</td>
</tr>
</template>
</v-data-table>
<v-divider class="my-1"></v-divider>
<div class="po-2 mt-1 text-xs-center">
<v-pagination v-model="currpage" :length="pagelength" :total-visible="10"></v-pagination>
</div>
</v-card>
<v-snackbar v-model="snackbar.state" multi-line top :timeout="3000" :color="snackbar.color">
{{ snackbar.msg }}
<v-btn class="ml-2" round flat @click="snackbar.state = false">Tutup</v-btn>
</v-snackbar>
<dialog-confirm></dialog-confirm>
<dialog-attachs></dialog-attachs>
</div>
</template>
<script>
module.exports = {
components: {
'dialog-confirm': httpVueLoader('./dialog-confirm.vue'),
'dialog-attachs': httpVueLoader('./dialog-view-attachment.vue')
},
mounted() {
this.$store.dispatch("poservice/lookupVendor")
this.$store.dispatch("poservice/lookupCabang")
this.$store.dispatch("poservice/lookupPOJasa")
this.$store.dispatch("poservice/lookupUserApproveLevel")
},
data() {
return {
menuStartdateFilter: false,
menuEnddateFilter: false,
headers: [
{
text: "No PO", align: "center", sortable: false,
value: "action", width: "15%", class: "pa-1 blue lighten-3 white--text",
},
{
text: "TANGGAL", align: "center", sortable: false,
value: "date", width: "10%", class: "pa-1 blue lighten-3 white--text",
},
{
text: "VENDOR", align: "center", sortable: false,
value: "supplier", width: "15%", class: "pa-1 blue lighten-3 white--text",
},
{
text: "CABANG", align: "center", sortable: false,
value: "branch", width: "10%", class: "pa-1 blue lighten-3 white--text",
},
{
text: "KETERANGAN", align: "center", sortable: false,
value: "note", width: "20%", class: "pa-1 blue lighten-3 white--text",
},
{
text: "TOTAL", align: "center", sortable: false,
value: "total", width: "10%", class: "pa-1 blue lighten-3 white--text",
},
{
text: "STATUS", align: "center", sortable: false,
value: "status", width: "7%", class: "pa-1 blue lighten-3 white--text",
},
{
text: "AKSI", align: "center", sortable: false,
value: "action", width: "13%", class: "pa-1 blue lighten-3 white--text",
},
]
}
},
computed: {
filterjasa: {
get() {
return this.$store.state.poservice.filterjasa;
},
set(val) {
this.$store.commit("poservice/update_filterjasa", val);
}
},
formattedStartdate() {
return this.formatDate(this.filterjasa.startdate)
},
formattedEnddate() {
return this.formatDate(this.filterjasa.enddate)
},
liststatus() {
return this.$store.state.poservice.liststatus
},
list_pojasa() {
return this.$store.state.poservice.list_pojasa
},
pagelength() {
let total = this.list_pojasa.total
if (total === undefined || total < 1) return 1
return Math.ceil(total/10)
},
userinfo() {
return this.$store.state.poservice.userinfo
},
loading_process() {
return this.$store.state.poservice.loading_process
},
currpage: {
get() {
return this.$store.state.poservice.currpage
},
set(val) {
this.$store.commit("poservice/update_currpage", val)
this.$store.dispatch("poservice/lookupPOJasa")
}
},
snackbar: {
get() {
return this.$store.state.poservice.snackbar
},
set(val) {
this.$store.commit("poservice/update_snackbar", val)
}
}
},
methods: {
formatDate(date) {
if (!date) return null;
const [year, month, day] = date.split('-');
return `${day}-${month}-${year}`;
},
formatCurrency(value) {
const num = parseFloat(value);
if (isNaN(num)) return 0;
return num.toFixed(2).replace('.', ',').replace(/\B(?=(\d{3})+(?!\d))/g, ".");
},
updateStatusPO(item) {
let poid = item.PurchaseOrderID
let userlevel = this.userinfo.M_UserM_ApproveLevelID
if (item.verifiedby == '0' || userlevel != '1') {
this.$store.dispatch("poservice/lookupDetailPO", poid)
this.$store.commit("poservice/update_detail_view", false)
this.$store.commit("poservice/update_dialog_confirm", true)
} else {
let snac = {color: 'info', msg: 'po sudah diverifikasi', state: true}
this.snackbar = snac
}
},
viewdetail(item) {
this.$store.dispatch("poservice/lookupDetailPO", item.PurchaseOrderID)
this.$store.commit("poservice/update_detail_view", true)
this.$store.commit("poservice/update_dialog_confirm", true)
}
},
watch: {
filterjasa: {
handler(val) {
this.$store.dispatch("poservice/lookupPOJasa")
},
deep: true
}
},
}
</script>

View File

@@ -0,0 +1,60 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="../../../libs/vendor/css/google-fonts.css">
<link rel="stylesheet" href="../../../libs/vendor/css/icomoon-fonts.css">
<link rel="stylesheet" href="../../../libs/vendor/css/vuetify.min.css">
<title>One</title>
</head>
<body>
<div v-cloak id="app">
<v-app id="smartApp">
<one-navbar></one-navbar>
<v-content style="background: #F5E8DF!important">
<v-container fluid fill-height class="px-1 py-2">
<v-flex xs12 fill-height pa-1>
<one-layout-service></one-layout-service>
</v-flex>
</v-container>
</v-content>
<one-footer></one-footer>
</v-app>
</div>
<!-- Vendor -->
<script src="../../../libs/vendor/moment.min.js"></script>
<script src="../../../libs/vendor/numeral.min.js"></script>
<script src="../../../libs/vendor/moment-locale-id.js"></script>
<script src="../../../libs/vendor/lodash.js"></script>
<script src="../../../libs/vendor/axios.min.js"></script>
<script src="../../../libs/vendor/vue.js"></script>
<script src="../../../libs/vendor/vuex.js"></script>
<script src="../../../libs/vendor/vuetify.js"></script>
<script src="../../../libs/vendor/httpVueLoader.js"></script>
<script src="../../../libs/one_global.js"></script>
<!-- App Script -->
<script type="module">
import { store } from './store.js';
window.store = store;
new Vue({
store,
el: "#app",
methods: {},
components: {
'one-navbar': httpVueLoader('../../../apps/components/oneNavbarComponent.vue'),
'one-footer': httpVueLoader('../../../apps/components/oneFooter.vue'),
'one-layout-service': httpVueLoader('./components/one-layout-service.vue')
}
})
</script>
<style>
[v-cloak] {
display: none;
}
</style>
</body>
</html>

View File

@@ -0,0 +1,231 @@
import * as api from '../api/api.js';
export default {
namespaced: true,
state: {
/* utility */
snackbar: {
color: 'success',
msg: '',
state: false
},
filterjasa: {
startdate: moment(new Date()).format('YYYY-MM-DD'),
enddate: moment(new Date()).format('YYYY-MM-DD'),
status: "All",
search: ""
},
liststatus: ['All', 'Draft', 'Pending', 'Approved', 'Rejected', 'Completed'],
list_pojasa: {
records: [],
total: 0
},
currpage: 1,
loading_process: false,
list_supplier: [],
list_branch: [],
userinfo: {},
/* dialog konfirmasi */
dialog_confirm: false,
detail_view: false,
selected_pojasa: {
summary: {
subtotal: 0.00,
diskon: 0.00,
pajak: 0.00,
total: 0.00
}
},
/* dialog attachment */
dialog_attachment: false,
prview_attachment: []
},
mutations: {
update_snackbar(state, val) {
state.snackbar = val
},
update_filterjasa(state, val) {
state.filterjasa = val
},
update_liststatus(state, val) {
state.liststatus = val
},
update_list_pojasa(state, val) {
state.list_pojasa = val
},
update_currpage(state, val) {
state.currpage = val
},
update_loading_process(state, val) {
state.loading_process = val
},
update_list_supplier(state, val) {
state.list_supplier = val
},
update_list_branch(state, val) {
state.list_branch = val
},
update_userinfo(state, val) {
state.userinfo = val
},
update_dialog_confirm(state, val) {
state.dialog_confirm = val
},
update_detail_view(state, val) {
state.detail_view = val
},
update_selected_pojasa(state, val) {
state.selected_pojasa = val
},
update_dialog_attachment(state, val) {
state.dialog_attachment = val
},
update_prview_attachment(state, val) {
state.prview_attachment = val
}
},
actions: {
async lookupCabang(context) {
try {
const resp = await api.getDaftarCabang({token: one_token()})
if (resp.status != 'OK') {
let snac = {color: 'error', msg: resp.message, state: true}
context.commit('update_snackbar', snac)
} else {
context.commit("update_list_branch", resp.data)
}
} catch (error) {
let snac = {color: 'error', msg: error.message, state: true}
context.commit('update_snackbar', snac)
}
},
async lookupVendor(context) {
try {
const resp = await api.getDaftarSupplier({token: one_token()})
if (resp.status != 'OK') {
let snac = {color: 'error', msg: resp.message, state: true}
context.commit('update_snackbar', snac)
} 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 lookupPOJasa(context) {
try {
let param = {
token: one_token(),
currpage: context.state.currpage,
...context.state.filterjasa
}
const resp = await api.getDaftarPOJasa(param)
if (resp.status != 'OK') {
let snac = {color: 'error', msg: resp.message, state: true}
context.commit('update_snackbar', snac)
} else {
context.commit('update_list_pojasa', resp.data)
}
} catch (error) {
let snac = {color: 'error', msg: error.message, state: true}
context.commit('update_snackbar', snac)
}
},
async lookupDetailPO(context, poid) {
try {
let param = {
token: one_token(),
poID: poid
}
const resp = await api.getDataKontrakPOJasa(param)
if (resp.status != 'OK') {
let snac = {color: 'error', msg: resp.message, state: true}
context.commit('update_snackbar', snac)
} else {
context.commit("update_selected_pojasa", resp.data)
}
} catch (error) {
let snac = {color: 'error', msg: error.message, state: true}
context.commit('update_snackbar', snac)
}
},
async lookupUserApproveLevel(context) {
try {
const resp = await api.getUserApproveLevel({token: one_token()})
if (resp.status != 'OK') {
let snac = {color: 'error', msg: resp.message, state: true}
context.commit('update_snackbar', snac)
} else {
context.commit("update_userinfo", resp.data)
}
} catch (error) {
let snac = {color: 'error', msg: error.message, state: true}
context.commit('update_snackbar', snac)
}
},
async lookupAttachment(context, param) {
try {
param.token = one_token()
const resp = await api.getDaftarAttachment(param)
if (resp.status != 'OK') {
let snac = {color: 'error', msg: resp.message, state: true}
context.commit('update_snackbar', snac)
} else {
context.commit('update_prview_attachment', resp.data)
}
} catch (error) {
let snac = {color: 'error', msg: error.message, state: true}
context.commit('update_snackbar', snac)
}
},
async updateApprovePO(context) {
try {
context.state.loading_process = true;
const jasa = context.state.selected_pojasa;
const param = {
token: one_token(),
approvelevel: context.state.userinfo.M_UserM_ApproveLevelID,
poID: jasa.PurchaseOrderID,
kontrakid: jasa.T_KontrakJasaID
};
const resp = await api.updateApprovalPO(param);
if (resp.status !== 'OK') {
throw new Error(resp.message);
}
if (param.approvelevel === '2') {
const generate = await api.generatePOItemReceive(param);
if (generate.status !== 'OK') {
throw new Error(generate.message);
}
}
let snac = {color: 'success', msg: resp.data, state: true};
context.commit('update_snackbar', snac);
context.dispatch('lookupPOJasa');
context.state.dialog_confirm = false
} catch (error) {
let snac = {color: 'error', msg: error.message, state: true};
context.commit('update_snackbar', snac);
} finally {
context.state.loading_process = false;
}
}
}
}

View File

@@ -0,0 +1,11 @@
import system from "../../../apps/modules/system/system.js";
import poservice from "./modules/poservice.js";
export const store = new Vuex.Store({
modules: {
system: system,
poservice: poservice
},
state: {},
mutations: {},
actions: {}
});

View File

@@ -0,0 +1,293 @@
const URL = "/one-api/mockup/purchase/order/PurchaseOrderV2/";
const URLRO = "/one-api/mockup/receive-item-po/receiveitempo/";
export async function getSupplier(payload) {
try {
var response = await axios.post(URL + "getSupplier", payload);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function getItemCategory(payload) {
try {
var response = await axios.post(URL + "getItemCategory", payload);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function getWarehouse(payload) {
try {
var response = await axios.post(URL + "getWarehouse", payload);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function getItem(payload) {
try {
var response = await axios.post(URL + "getItem", payload);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function getItemUpdate(payload) {
try {
var response = await axios.post(URL + "getItemUpdate", payload);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function saveOrder(payload) {
try {
var response = await axios.post(URL + "saveOrder", payload);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function search(payload) {
try {
var response = await axios.post(URL + "search", payload);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function requestOrder(payload) {
try {
var response = await axios.post(URL + "requestOrder", payload);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function deleteOrder(payload) {
try {
var response = await axios.post(URL + "deleteOrder", payload);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function updateOrder(payload) {
try {
var response = await axios.post(URL + "updateOrder", payload);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function approvePOrder(payload) {
try {
var response = await axios.post(URL + "approvePOrder", payload);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function isValidMultipleWarehouse(payload) {
try {
var response = await axios.post(URL + "isValidMultipleWarehouse", payload);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function generateItemPO(params) {
try {
var response = await axios.post(URLRO + "generateItemPo", params);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function getApprovalLevel(params) {
try {
var response = await axios.post(URL + 'getApproveLevel', params);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function getDefaultSupplierPrice(payload) {
try {
var response = await axios.post(URL + "getDefaultSupplierPrice", payload);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}

View File

@@ -0,0 +1,593 @@
<template>
<div>
<!-- Dialog View -->
<v-dialog v-model="dialogView" persistent width="85vw">
<v-card>
<v-card-title class="headline grey lighten-2" primary-title>
DETAIL PURCHASE ORDER {{ selectedPO.PurchaseOrderNumber ?? "" }}
</v-card-title>
<v-card-text>
<v-layout row wrap class="px-2 py-2">
<!-- HEADER PO VIEW -->
<v-layout row wrap class="pa-0 ma-0">
<!-- Tanggal -->
<v-flex xs3>
<div class="label-value subheading mb-2">
<span class="label">Nomor PO</span>
</div>
</v-flex>
<v-flex xs9>
<div class="label-value subheading mb-2">
<span class="value">: {{ selectedPO.PurchaseOrderNumber }}</span>
</div>
</v-flex>
<!-- Tanggal -->
<v-flex xs3>
<div class="label-value subheading mb-2">
<span class="label">Tanggal</span>
</div>
</v-flex>
<v-flex xs9>
<div class="label-value subheading mb-2">
<span class="value">: {{ selectedPO.DisplayDate }}</span>
</div>
</v-flex>
<!-- Nomor Referensi -->
<v-flex xs3>
<div class="label-value subheading mb-2">
<span class="label">Nomor Referensi</span>
</div>
</v-flex>
<v-flex xs9>
<div class="label-value subheading mb-2">
<span class="value">: {{ selectedPO.PurchaseOrderRefNumber }}</span>
</div>
</v-flex>
<!-- Pajak Pendapatan (PPN) -->
<v-flex xs3>
<div class="label-value subheading mb-2">
<span class="label">Pajak Pendapatan (PPN):</span>
</div>
</v-flex>
<v-flex xs9>
<div class="label-value subheading mb-2">
<span class="value">: {{ selectedPO.PurchaseOrderTaxPercentPpn }}%</span>
</div>
</v-flex>
<!-- Pajak Penghasilan (PPH) -->
<v-flex xs3>
<div class="label-value subheading mb-2">
<span class="label">Pajak Penghasilan (PPH)</span>
</div>
</v-flex>
<v-flex xs9>
<div class="label-value subheading mb-2">
<span class="value">: {{ selectedPO.PurchaseOrderTaxPercentPph }}%</span>
</div>
</v-flex>
<!-- Vendor -->
<v-flex xs3>
<div class="label-value subheading mb-2">
<span class="label">Vendor</span>
</div>
</v-flex>
<v-flex xs9>
<div class="label-value subheading mb-2">
<span class="label">: {{ selectedPO.SupplierCode }}
{{ selectedPO.SupplierName }}
</span>
</div>
</v-flex>
<!-- Diskon Vendor -->
<v-flex xs3>
<div class="label-value subheading mb-2">
<span class="label">Diskon Vendor(Tipe Diskon)</span>
</div>
</v-flex>
<v-flex xs9>
<div class="label-value subheading mb-2">
<span v-if="selectedPO.DiscountType == 'Percentage'" class="label">: {{ selectedPO.PurchaseOrderDiscountPercent }}% (Percentage)</span>
<span v-if="selectedPO.DiscountType == 'Absolute'" class="label">: Rp {{ selectedPO.PurchaseOrderDiscountAmount }} (Absolut)</span>
<span v-if="selectedPO.DiscountType == ''" class="label">: - (-)</span>
</div>
</v-flex>
<!-- Jangka Waktu Pembayaran -->
<v-flex xs3>
<div class="label-value subheading mb-2">
<span class="label">Jangka Waktu Pembayaran</span>
</div>
</v-flex>
<v-flex xs9>
<div class="label-value subheading mb-2">
<span class="value">: {{ selectedPO.PurchaseOrderPaymentTerm }} hari</span>
</div>
</v-flex>
<!-- Tipe Gudang -->
<v-flex xs3>
<div class="label-value subheading mb-2">
<span class="label">Tipe Gudang</span>
</div>
</v-flex>
<!-- Tipe Gudang -->
<v-flex xs9>
<div class="label-value subheading mb-2">
<span class="value">: {{ selectedPO.PurchaseOrderWarehouseType }}</span>
</div>
</v-flex>
<!-- Gudang -->
<v-flex xs3 v-if="selectedPO.PurchaseOrderWarehouseType === 'Single'">
<div class="label-value subheading mb-2">
<span class="label">Gudang</span>
</div>
</v-flex>
<v-flex xs9 v-if="selectedPO.PurchaseOrderWarehouseType === 'Single'">
<div class="label-value subheading mb-2">
<span class="value">: {{ selectedPO.WarehouseName }}</span>
</div>
</v-flex>
<!-- Keterangan -->
<v-flex xs3>
<div class="label-value subheading mb-2">
<span class="label">Biaya Ekspedisi</span>
</div>
</v-flex>
<v-flex xs9>
<div class="label-value subheading mb-2">
<span class="value">: {{ selectedPO && selectedPO.PurchaseOrderShippingCost != null
? oneMoney(selectedPO.PurchaseOrderShippingCost) : '0' }}
<span v-if="selectedPO.PurchaseOrderShippingCostStatus === 'Y'">Sudah dibayar
</span>
<span v-if="selectedPO.PurchaseOrderShippingCostStatus === 'N'">Belum dibayar
</span>
</span>
</div>
</v-flex>
<!-- Keterangan -->
<v-flex xs3>
<div class="label-value subheading mb-2">
<span class="label">Keterangan</span>
</div>
</v-flex>
<v-flex xs9>
<div class="label-value subheading mb-2">
<span class="value">: {{ selectedPO.PurchaseOrderNote }}</span>
</div>
</v-flex>
</v-layout>
<!-- TABEL ITEM VIEW -->
<v-flex xs12>
<v-data-table v-if="summary.length > 0" :headers="summaryHeaders" :items="summary" :loading="loading"
hide-actions class="elevation-1 mt-4" expand item-key="M_ItemID">
<!-- Tabel Item -->
<template slot="items" slot-scope="props">
<tr @click="props.expanded = !props.expanded">
<td class="text-xs-center">
<v-icon>{{
props.expanded
? "keyboard_arrow_down"
: "keyboard_arrow_right"
}}</v-icon>
</td>
<td class="">
<kbd>{{ props.item.M_ItemCode }}</kbd>
{{ props.item.M_ItemDesc }}
</td>
<td class="text-xs-center">
{{ props.item.TotalPoQty }} {{ props.item.PoItemUnitName }}
</td>
<td class="text-xs-center">
{{ oneMoney(props.item.RealPrice) }}
</td>
<td class="text-xs-right">
<div v-if="props.item.discountType === 'R'">
{{ oneMoney(props.item.discount) }}
</div>
<div v-if="props.item.discountType === 'P'">
<kbd>{{ props.item.discount }}%</kbd>
{{ oneMoney(props.item.summaryDiscountAmount) }}
</div>
</td>
<td class="text-xs-right">
{{ oneMoney(props.item.Price) }}
</td>
<td class="text-xs-right">
{{ oneMoney(props.item.Total) }}
</td>
</tr>
</template>
<!-- Detail per Baris Item -->
<template slot="expand" slot-scope="props">
<v-card flat>
<v-card-text class="pl-3">
<div class="ml-3 mb-3">
<v-data-table :headers="detailHeaders" :items="props.item.Details" hide-actions
class="elevation-0">
<template slot="items" slot-scope="detailProps">
<td class="">
<kbd>{{ detailProps.item.M_ItemCode }}</kbd>
{{ detailProps.item.M_ItemDesc }}
</td>
<td class="">
{{
detailProps.item.PurchaseRequestNumber
}}
</td>
<td class="">
{{
detailProps.item.M_BranchName ??
detailProps.item.S_RegionalName
}}
</td>
<td class="py-1">
{{ detailProps.item.warehouse.WarehouseName }}
</td>
<td class="text-xs-center">
{{ detailProps.item.PoQty }}
{{ detailProps.item.PoItemUnitName }}
</td>
</template>
</v-data-table>
</div>
</v-card-text>
</v-card>
</template>
<!-- Tabel di bawah Item -->
<template v-slot:footer>
<tr>
<td :colspan="4">
<strong class="ml-2">TOTAL HARGA TANPA DISKON</strong>
</td>
<td :colspan="3" class="text-xs-right">
<strong>{{
selectedPO && selectedPO.TotalRealPrice != null
? oneMoney(selectedPO.TotalRealPrice) : '0'
}}</strong>
</td>
</tr>
<tr>
<td :colspan="4">
<strong class="ml-2">TOTAL DISKON PER ITEM</strong>
</td>
<td :colspan="3" class="text-xs-right">
<strong>{{
selectedPO && selectedPO.TotalDiskonPerItem != null
? oneMoney(selectedPO.TotalDiskonPerItem) : '0'
}}</strong>
</td>
</tr>
<tr>
<td :colspan="4">
<strong class="ml-2">DISKON VENDOR</strong>
</td>
<td :colspan="3" class="text-xs-right">
<strong>{{
selectedPO && selectedPO.DiscountAmount != null
? oneMoney(selectedPO.DiscountAmount) : '0'
}}</strong>
</td>
</tr>
<tr>
<td :colspan="4">
<strong class="ml-5">PAJAK PENDAPATAN(PPN)</strong>
</td>
<td :colspan="3" class="text-xs-right">
<strong>{{
selectedPO && selectedPO.PurchaseOrderTaxAmountPpn != null
? oneMoney(selectedPO.PurchaseOrderTaxAmountPpn) : '0'
}}</strong>
</td>
</tr>
<tr>
<td :colspan="4">
<strong class="ml-5">PAJAK PENGHASILAN(PPH)</strong>
</td>
<td :colspan="3" class="text-xs-right">
<strong>{{
selectedPO && selectedPO.PurchaseOrderTaxAmountPph != null
? oneMoney(selectedPO.PurchaseOrderTaxAmountPph) : '0'
}}</strong>
</td>
</tr>
<tr>
<td :colspan="4">
<strong class="ml-2">PAJAK</strong>
</td>
<td :colspan="3" class="text-xs-right">
<strong>{{ selectedPO && selectedPO.TaxAmount != null
? oneMoney(selectedPO.TaxAmount) : '0' }}</strong>
</td>
</tr>
<tr>
<td :colspan="4">
<strong>TOTAL</strong>
</td>
<td :colspan="3" class="text-xs-right">
<strong>{{
selectedPO && selectedPO.PurchaseOrderGrandTotal != null
? oneMoney(selectedPO.PurchaseOrderGrandTotal) : '0'
}}</strong>
</td>
</tr>
</template>
</v-data-table>
</v-flex>
</v-layout>
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="green" flat @click="dialogView = false">
TUTUP
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</div>
</template>
<script>
module.exports = {
data() {
return {
selectedDateForm: null,
refNumber: "",
taxPpn: 0,
taxPph: 0,
selectedSupplier: {},
paymentTerm: 0,
warehouseType: "",
selectedWarehouse: {},
note: "",
selectedItem: [],
detailHeaders: [
// {
// text: "KODE ITEM",
// align: "center",
// sortable: false,
// value: "M_ItemCode",
// width: "15%",
// class: "blue lighten-4 black--text",
// },
{
text: "NAMA PRODUK",
align: "center",
sortable: false,
value: "M_ItemDesc",
width: "20%",
class: "blue lighten-4 black--text",
},
{
text: "PR NUMBER",
align: "center",
sortable: false,
value: "M_ItemDesc",
width: "10%",
class: "blue lighten-4 black--text",
},
{
text: "CABANG",
align: "center",
sortable: false,
value: "M_BranchName",
width: "20%",
class: "blue lighten-4 black--text",
},
{
text: "GUDANG",
align: "center",
sortable: false,
value: "M_BranchName",
width: "30%",
class: "blue lighten-4 black--text",
},
// {
// text: "UNIT",
// align: "center",
// sortable: false,
// value: "ItemUnitName",
// width: "10%",
// class: "blue lighten-4 black--text",
// },
{
text: "QTY",
align: "center",
sortable: false,
value: "PoQty",
width: "15%",
class: "blue lighten-4 black--text",
},
],
summaryHeaders: [
{
text: "",
align: "center",
sortable: false,
value: "expand",
width: "5%",
class: "blue lighten-3 white--text",
},
{
text: "ITEM",
align: "center",
sortable: false,
value: "M_ItemCode",
width: "10%",
class: "blue lighten-3 white--text",
},
{
text: "QTY",
align: "center",
sortable: false,
value: "PoQty",
width: "10%",
class: "blue lighten-3 white--text",
},
{
text: "HARGA",
align: "center",
sortable: false,
value: "price",
width: "15%",
class: "blue lighten-3 white--text",
},
{
text: "DISKON",
align: "center",
sortable: false,
value: "price",
width: "20%",
class: "blue lighten-3 white--text",
},
{
text: "HARGA SETELAH DISKON",
align: "center",
sortable: false,
value: "price",
width: "15%",
class: "blue lighten-3 white--text",
},
{
text: "TOTAL",
align: "center",
sortable: false,
value: "Total",
width: "20%",
class: "blue lighten-3 white--text",
},
],
};
},
computed: {
statusOptions() {
return this.$store.state.po.statusOptions;
},
dialogView: {
get() {
return this.$store.state.po.dialogView;
},
set(val) {
this.$store.commit("po/update_dialogView", val);
},
},
selectedPO: {
get() {
return this.$store.state.po.selectedPO;
},
set(val) {
this.$store.commit("po/update_selectedPO", val);
},
},
summary: {
get() {
return this.$store.state.po.summary;
},
set(val) {
this.$store.commit("po/update_summary", val);
},
},
loading: {
get() {
return this.$store.state.po.loading;
},
set(val) {
this.$store.commit("po/update_loading", val);
},
},
},
methods: {
roundToThreeSignificantDigits(num) {
if (num === 0) return 0;
// Hitung jumlah digit
const absNum = Math.abs(num);
const magnitude = Math.floor(Math.log10(absNum)) + 1;
// Jika kurang dari 3 digit, tidak perlu dibulatkan
if (magnitude <= 3) return num;
// Hitung faktor pembulatan
const factor = Math.pow(10, magnitude - 3);
// Bulatkan
return Math.round(num / factor) * factor;
},
oneMoney(value) {
//return one_money(value);
// let splitValue = value.toString().split(".");
// if(splitValue.length > 1) {
// let val = splitValue[0]
// return val.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".") + "," + this.roundToThreeSignificantDigits(splitValue[1]);
// } else {
// return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".");
// }
// Ubah ke float jika belum angka
if (typeof value !== 'number') {
value = parseFloat(value);
}
if (isNaN(value)) return '0,00';
// Bulatkan dulu ke 2 desimal
const fixed = value.toFixed(2); // hasil string, misal "16200000.00" atau "123456.70"
const splitValue = fixed.split(".");
const val = splitValue[0]; // bagian ribuan
const decimal = splitValue[1]; // bagian desimal
const formatted = val.replace(/\B(?=(\d{3})+(?!\d))/g, ".");
return `${formatted},${decimal}`;
},
formatDate(date) {
if (!date) return null;
const [year, month, day] = date.split("-");
return `${day}-${month}-${year}`;
},
formatRupiah(angka) {
const format = new Intl.NumberFormat("id-ID", {
style: "currency",
currency: "IDR",
minimumFractionDigits: 0,
});
return "Rp " + format.format(angka).replace("Rp", "").trim();
},
},
};
</script>
<style scoped>
.label-value subheading mb-2 {
display: flex;
flex-direction: column;
margin-bottom: 1rem;
}
.label {
font-weight: bold;
margin-bottom: 0.25rem;
}
.value {
font-size: 1rem;
}
</style>

View File

@@ -0,0 +1,713 @@
<template>
<div>
<v-dialog v-model="dialogDelete" persistent width="500">
<v-card>
<v-card-title class="headline grey lighten-2" primary-title>
KONFIRMASI
</v-card-title>
<v-card-text>
Apakah anda yakin untuk menghapus
<span style="font-weight: bold;">{{
selectedPO.PurchaseOrderNumber
}}</span>
??
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="red" :disabled="loading" :loading="loading" flat @click="dialogDelete = false">
Tidak
</v-btn>
<v-btn color="green" :disabled="loading" :loading="loading" flat @click="deletePO()">
Ya
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
<v-dialog v-model="dialogConfirmation" persistent width="500">
<v-card>
<v-card-title class="headline grey lighten-2" primary-title>
KONFIRMASI
</v-card-title>
<v-card-text>
Apakah anda yakin untuk mengunci
<span style="font-weight: bold;">{{
selectedPO.PurchaseOrderNumber
}}</span>
untuk melanjutkan ke proses approve?
<p style="font-style: italic;" class="mt-3">
*Setelah dikunci PO tidak dapat di edit
</p>
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="red" :disabled="loading" :loading="loading" flat @click="dialogConfirmation = false">
Tidak
</v-btn>
<v-btn color="green" :disabled="loading" :loading="loading" flat @click="requestOrder()">
Ya
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
<v-snackbar v-model="snackbar.state" :color="snackbar.type" :timeout="3000" multi-line top>
{{ snackbar.message }}
<v-btn flat @click="snackbar.state = false">
Close
</v-btn>
</v-snackbar>
<v-toolbar color="primary" dark>
<v-toolbar-title class="white--text">PURCHASE ORDER APPROVE</v-toolbar-title>
<v-spacer></v-spacer>
<v-btn v-if="(flag == 'G')" @click="goBack()" color="orange darken-2" title="Kembali ke listing pending approval" dark>
<v-icon dark left>arrow_back</v-icon>Back
</v-btn>
</v-toolbar>
<v-card>
<v-layout row wrap class="px-2 py-2">
<v-flex xs3>
<v-menu v-model="menuSelectedDate" :close-on-content-click="false" transition="scale-transition"
:nudge-right="40" lazy offset-y max-width="290px" min-width="290px">
<template v-slot:activator="{ on }">
<v-text-field :value="selectedDateFormatted" label="Tanggal Mulai" readonly class="mr-2"
outline hide-details v-on="on"></v-text-field>
</template>
<v-date-picker no-title hide-details v-model="selectedDate"
@input="menuSelectedDate = false"></v-date-picker>
</v-menu>
</v-flex>
<v-flex xs3>
<v-menu v-model="menuSelectedDateEnd" :close-on-content-click="false" transition="scale-transition"
:nudge-right="40" lazy offset-y max-width="290px" min-width="290px">
<template v-slot:activator="{ on }">
<v-text-field :value="endDateFormatted" label="Tanggal Akhir" readonly class="mr-2" outline
hide-details v-on="on"></v-text-field>
</template>
<v-date-picker no-title hide-details v-model="selectedDateEnd"
@input="menuSelectedDateEnd = false"></v-date-picker>
</v-menu>
</v-flex>
<v-flex xs3>
<v-select :items="statusOptions" label="Status" hide-details class="mini-select mr-2" v-model="selectedStatus"
item-text="title" return-object outline></v-select>
</v-flex>
<v-flex xs3>
<v-text-field v-model="search" label="Cari..." placeholder="NO. PO" class="mr-2" outline hide-details>
</v-text-field>
</v-flex>
</v-layout>
</v-card>
<v-card class="pa-2 mt-2">
<div style="height: 60vh; overflow-y: scroll;">
<v-data-table :headers="headers" :items="poList" :loading="loading" hide-actions class="elevation-1">
<template v-slot:items="props">
<td class="text-xs-center">{{ props.item.PurchaseOrderNumber }}</td>
<td class="text-xs-center">{{ props.item.PurchaseOrderDate }}</td>
<td class="text-xs-left">{{ props.item.SupplierName }}</td>
<td class="text-xs-center">
<p class="my-0 p-0">
<kbd>{{ props.item.PurchaseOrderWarehouseType }}</kbd>
</p>
<p class="my-0 p-0">
{{ props.item.WarehouseName }}
</p>
</td>
<td class="text-xs-left">{{ props.item.PurchaseOrderNote }}</td>
<td class="text-xs-right">
Rp. {{ props.item.PurchaseOrderGrandTotal != null ? oneMoney(props.item.PurchaseOrderGrandTotal) : '0' }}
</td>
<td class="text-xs-center">
<v-chip color="blue" v-if="props.item.PurchaseOrderStatus === 'Draft'" text-color="white">{{
props.item.PurchaseOrderStatus }}
</v-chip>
<v-chip color="warning" v-else-if="props.item.PurchaseOrderStatus === 'Pending'" text-color="white">{{
props.item.PurchaseOrderStatus }}
</v-chip>
<v-chip color="green" v-else-if="props.item.PurchaseOrderStatus === 'Approved'" text-color="white">{{
props.item.PurchaseOrderStatus }}
</v-chip>
<v-chip color="red" v-else-if="props.item.PurchaseOrderStatus === 'Rejected'" text-color="white">{{
props.item.PurchaseOrderStatus }}
</v-chip>
<v-chip color="primary" v-else-if="props.item.PurchaseOrderStatus === 'Completed'" text-color="white">{{
props.item.PurchaseOrderStatus }}
</v-chip>
<v-chip v-else text-color="white">{{ props.item.PurchaseOrderStatus }}
</v-chip>
</td>
<td class="text-xs-center">
<!-- Belum Approve -->
<div v-if="props.item.PurchaseOrderStatus === 'Pending'">
<v-btn
:disabled="loading || props.item.PurchaseOrderStatus == 'Approved' || approve_level != '1'"
@click="approvePO(props.item)" round color="primary" small :outline="isApproved(props.item, 'M')"
>
{{ props.item.PurchaseOrderApprovedManagerUserID == '0' ? 'Approve (Manager)' : 'Approved (Manager)'}}
<v-icon
small right dark
v-if="props.item.PurchaseOrderApprovedManagerUserID != '0'"
>done_all</v-icon>
</v-btn>
<v-btn
:disabled="loading || props.item.PurchaseOrderStatus == 'Approved' || approve_level != '2'"
@click="approvePO(props.item)" round color="primary" small :outline="isApproved(props.item, 'K')"
>
Approve (Kepala Reg)
<v-icon
small right dark
>done</v-icon>
</v-btn>
<v-tooltip bottom>
<template v-slot:activator="{ on }">
<v-btn icon :disabled="loading" @click="openDialogView(props.item)" v-on="on">
<v-icon color="blue">visibility</v-icon>
</v-btn>
</template>
<span>View PO</span>
</v-tooltip>
<v-tooltip bottom>
<template v-slot:activator="{ on }">
<v-btn icon :disabled="loading || props.item.PurchaseOrderStatus == 'Approve'" @click="openDialogEdit(props.item)" v-on="on">
<v-icon color="blue">edit</v-icon>
</v-btn>
</template>
<span>Edit PO</span>
</v-tooltip>
</div>
<div v-if="props.item.PurchaseOrderStatus == 'Approved'">
<v-tooltip bottom>
<template v-slot:activator="{ on }">
<v-btn icon :disabled="loading" @click="openDialogView(props.item)" v-on="on">
<v-icon color="blue">visibility</v-icon>
</v-btn>
</template>
<span>View PO</span>
</v-tooltip>
<v-tooltip bottom>
<template v-slot:activator="{ on }">
<v-btn icon :disabled="loading" @click="doPrint(props.item)" v-on="on">
<v-icon color="red">picture_as_pdf</v-icon>
</v-btn>
</template>
<span>PDF PO</span>
</v-tooltip>
</div>
</td>
</template>
</v-data-table>
</div>
</v-card>
<v-card class="text-xs-left pa-2">
<v-pagination v-model="selectedPage" :length="totalPage"></v-pagination>
</v-card>
<po-form></po-form>
<po-view></po-view>
<one-dialog-print :title="printtitle" :width="printwidth" :height="700" :status="openprint" :urlprint="urlprint"
@close-dialog-print="openprint = false"></one-dialog-print>
</div>
</template>
<style scoped>
.date-type-table {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.flex-items-center {
display: flex;
align-items: center;
gap: 0.25rem;
}
.table.v-table tbody td,
.table.v-table tbody tr {
height: 40px;
}
.table.v-table thead tr {
height: 40px;
}
</style>
<script>
module.exports = {
components: {
"po-form": httpVueLoader("./poForm.vue"),
"po-view": httpVueLoader("./dialogView.vue"),
'one-dialog-print': httpVueLoader('../../common/oneDialogPrintX.vue')
},
data() {
return {
menuSelectedDate: false,
menuSelectedDateEnd: false,
msgAlertDeleteOrReject: "",
dialogAlertRejectRequest: false,
dialogAlertDeleteDetail: false,
amountRules: [(v) => v >= 0 || "Jumlah harus diisi"],
validationDetail: false,
formatreport: "pdf",
urlprint: "",
printtitle: '',
printwidth: '100%',
headers: [
{
text: "NO PO",
align: "center",
sortable: false,
value: "no",
width: "5%",
class: "blue lighten-3 white--text",
},
{
text: "TANGGAL",
align: "center",
sortable: false,
value: "no",
width: "10%",
class: "blue lighten-3 white--text",
},
{
text: "VENDOR",
align: "center",
sortable: false,
value: "no",
width: "20%",
class: "blue lighten-3 white--text",
},
{
text: "GUDANG",
align: "center",
sortable: false,
value: "no",
width: "15%",
class: "blue lighten-3 white--text",
},
{
text: "KETERANGAN",
align: "center",
sortable: false,
value: "",
width: "20%",
class: "blue lighten-3 white--text",
},
{
text: "TOTAL",
align: "center",
sortable: false,
value: "",
width: "10%",
class: "blue lighten-3 white--text",
},
{
text: "STATUS",
align: "center",
sortable: false,
value: "",
width: "10%",
class: "blue lighten-3 white--text",
},
{
text: "AKSI",
align: "center",
sortable: false,
value: "",
width: "15%",
class: "blue lighten-3 white--text",
},
],
detailHeaders: [
{
text: "KODE ITEM",
align: "center",
sortable: false,
value: "no",
width: "15%",
class: "blue lighten-3 white--text",
},
{
text: "NAMA ITEM",
align: "left",
sortable: false,
value: "requestDate",
width: "35%",
class: "blue lighten-3 white--text",
},
{
text: "QTY",
align: "left",
sortable: false,
value: "requestDate",
width: "15%",
class: "blue lighten-3 white--text",
},
{
text: "HARGA",
align: "left",
sortable: false,
value: "requestDate",
width: "25%",
class: "blue lighten-3 white--text",
},
],
};
},
mounted() {
this.$store.dispatch("po/searchData");
this.$store.dispatch("po/getItemCategory");
this.$store.dispatch("po/getApprovalLevel");
},
computed: {
flag() {
return this.$store.state.po.flag;
},
status() {
return this.$store.state.po.status;
},
xstartdate() {
return this.$store.state.po.xstartdate;
},
statusOptions() {
return this.$store.state.po.statusOptions;
},
selectedDate: {
get() {
return this.$store.state.po.selectedDate;
},
set(val) {
this.$store.commit("po/update_selectedDate", val);
this.$store.dispatch("po/searchData");
},
},
selectedStatus: {
get() {
return this.$store.state.po.selectedStatus;
},
set(val) {
this.$store.commit("po/update_selectedStatus", val);
this.$store.dispatch("po/searchData");
},
},
statusOptions: {
get() {
return this.$store.state.po.statusOptions;
},
set(val) {
this.$store.commit("po/update_statusOptions", val);
},
},
selectedPO: {
get() {
return this.$store.state.po.selectedPO;
},
set(val) {
this.$store.commit("po/update_selectedPO", val);
},
},
dialogConfirmation: {
get() {
return this.$store.state.po.dialogConfirmation;
},
set(val) {
this.$store.commit("po/update_dialogConfirmation", val);
},
},
selectedDateEnd: {
get() {
return this.$store.state.po.selectedDateEnd;
},
set(val) {
this.$store.commit("po/update_selectedDateEnd", val);
this.$store.dispatch("po/searchData");
},
},
search: {
get() {
return this.$store.state.po.search;
},
set(val) {
this.$store.commit("po/update_search", val);
this.$store.dispatch("po/searchData");
},
},
selectedDateFormatted() {
return this.formatDate(this.selectedDate);
},
endDateFormatted() {
return this.formatDate(this.selectedDateEnd);
},
poList() {
return this.$store.state.po.poList;
},
snackbar: {
get() {
return this.$store.state.po.snackbar;
},
set(val) {
this.$store.commit("po/update_snackbar", val);
},
},
totalPage: {
get() {
return this.$store.state.po.totalPage;
},
set(val) {
this.$store.commit("po/update_totalPage", val);
},
},
selectedPage: {
get() {
return this.$store.state.po.selectedPage;
},
set(val) {
this.$store.commit("po/update_selectedPage", val);
this.$store.dispatch("po/searchData");
},
},
loading: {
get() {
return this.$store.state.po.loading;
},
set(val) {
this.$store.commit("po/update_loading", val);
},
},
dialogForm: {
get() {
return this.$store.state.po.dialogForm;
},
set(val) {
this.$store.commit("po/update_dialogForm", val);
},
},
dialogFormAct: {
get() {
return this.$store.state.po.dialogFormAct;
},
set(val) {
this.$store.commit("po/update_dialogFormAct", val);
},
},
dialogDelete: {
get() {
return this.$store.state.po.dialogDelete;
},
set(val) {
this.$store.commit("po/update_dialogDelete", val);
},
},
dialogView: {
get() {
return this.$store.state.po.dialogView;
},
set(val) {
this.$store.commit("po/update_dialogView", val);
},
},
openprint: {
get() {
return this.$store.state.po.open_print;
},
set(val) {
this.$store.commit("po/update_open_print", val);
},
},
approve_level() {
return this.$store.state.po.approve_level
}
},
methods: {
goBack() {
window.history.back();
// location.href = "/one-ui/test/vuex/one-accone-approve-all/"
},
doPrint(val) {
// console.log(val)
this.printwidth = 1028
this.printtitle = ""
let user = one_user()
tm = Date.now()
var rptname = 'rpt_po_001'
var formatrpt = this.formatreport
this.urlprint = "/birt/run?__report=report/one/accounting/" + rptname + ".rptdesign&__format=" + formatrpt + "&PID=" + val.PurchaseOrderID + "&username=" + user.M_StaffName + "&tm=" + tm
// console.log(this.urlprint)
this.$store.commit("po/update_open_print", true)
},
roundToThreeSignificantDigits(num) {
if (num === 0) return 0;
// Hitung jumlah digit
const absNum = Math.abs(num);
const magnitude = Math.floor(Math.log10(absNum)) + 1;
// Jika kurang dari 3 digit, tidak perlu dibulatkan
if (magnitude <= 3) return num;
// Hitung faktor pembulatan
const factor = Math.pow(10, magnitude - 3);
// Bulatkan
return Math.round(num / factor) * factor;
},
oneMoney(value) {
//return one_money(value);
// let splitValue = value.toString().split(".");
// if(splitValue.length > 1) {
// let val = splitValue[0]
// return val.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".") + "," + this.roundToThreeSignificantDigits(splitValue[1]);
// } else {
// return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".");
// }
// Ubah ke float jika belum angka
if (typeof value !== 'number') {
value = parseFloat(value);
}
if (isNaN(value)) return '0,00';
// Bulatkan dulu ke 2 desimal
const fixed = value.toFixed(2); // hasil string, misal "16200000.00" atau "123456.70"
const splitValue = fixed.split(".");
const val = splitValue[0]; // bagian ribuan
const decimal = splitValue[1]; // bagian desimal
const formatted = val.replace(/\B(?=(\d{3})+(?!\d))/g, ".");
return `${formatted},${decimal}`;
},
openDialogConfirmation(data) {
this.selectedPO = data;
this.dialogConfirmation = true;
},
openDialogDelete(data) {
this.selectedPO = data;
this.dialogDelete = true;
},
async requestOrder() {
await this.$store.dispatch("po/requestOrder");
await this.$store.dispatch("po/searchData");
// Wait for DOM to update
this.$nextTick(() => {
this.$forceUpdate();
});
},
deletePO() {
this.$store.dispatch("po/deleteOrder");
},
openDialogAdd() {
this.$store.dispatch("po/resetForm");
this.dialogForm = true;
},
openDialogView(data) {
this.selectedPO = data;
this.$store.dispatch("po/resetForm");
this.dialogView = true;
this.$store.dispatch("po/getItemUpdate");
},
openDialogEdit(data) {
this.selectedPO = data;
this.dialogFormAct = "EDIT";
this.dialogForm = true;
this.$store.dispatch("po/assignEdit");
this.$store.dispatch("po/getItemUpdate");
},
formatRupiah(angka) {
const format = new Intl.NumberFormat("id-ID", {
style: "currency",
currency: "IDR",
minimumFractionDigits: 0,
});
return "Rp " + format.format(angka).replace("Rp", "").trim();
},
formatDate(date) {
if (!date) return null;
const [year, month, day] = date.split("-");
return `${day}-${month}-${year}`;
},
deFormatedDate(date) {
if (!date) return null;
const [day, month, year] = date.split("-");
return `${year}-${month.padStart(2, "0")}-${day.padStart(2, "0")}`;
},
async approvePO(data) {
try {
if (this.approve_level == '1' && data.PurchaseOrderApprovedManagerUserID != '0') {
this.snackbar = {
state: true,
type: "warning",
message: "Sudah diapprove oleh manager"
};
return;
}
if (data.PurchaseOrderID != '' && data.PurchaseOrderStatus != 'Approved') {
await this.$store.dispatch("po/approveOrder", { poID: data.PurchaseOrderID });
setTimeout(() => {
window.location.reload();
}, 1000); // Short delay to allow the snackbar to be visible
}
} catch (error) {
console.error("Error approving order:", error);
this.snackbar = {
state: true,
type: "error",
message: "Gagal mengapprove Purchase Order"
};
}
},
isApproved(data, type) {
if (!data) {
return false
}
if (data.PurchaseOrderStatus == 'Approved') {
return false
}
if (type == 'M') {
if (data.PurchaseOrderApprovedManagerUserID == '0') {
return true
} else {
return false
}
}
if (type == 'K') {
return true
}
return true
}
},
watch: {
dialogApprove(val, old) { },
},
};
</script>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,475 @@
/**
* Utility functions for the ACC One Purchase Order application
*/
// /**
// * Groups an array of objects by a specified key
// * @param {Array} array - The array of objects to group
// * @param {String} key - The key to group by
// * @returns {Object} - An object with keys representing the grouped values and arrays as values
// */
// export const groupBy = (array, key) => {
// return array.reduce((result, item) => {
// const groupKey = item[key];
// if (!result[groupKey]) {
// result[groupKey] = [];
// }
// result[groupKey].push(item);
// return result;
// }, {});
// };
/**
* Groups an array of objects by one or multiple keys
* @param {Array} array - The array of objects to group
* @param {Function|String|Array} key - The key(s) to group by. Can be a string, array of strings, or a function.
* @returns {Object} - An object with keys representing the grouped values and arrays as values
*/
export const groupBy = (array, key) => {
return array.reduce((result, item) => {
let groupKey;
// Handle single key (string), multiple keys (array), or custom function
if (typeof key === 'function') {
groupKey = key(item);
} else if (Array.isArray(key)) {
groupKey = key.map(k => item[k]).join('_'); // Combine multiple keys with underscore
} else {
groupKey = item[key];
}
if (!result[groupKey]) {
result[groupKey] = [];
}
result[groupKey].push(item);
return result;
}, {});
};
/**
* Groups purchase request data by M_ItemID
* Terjadi jika ada beberapa item yang sama, maka akan digabungkan berdasarkan M_ItemID dan PoItemUnitID
* @param {Array} purchaseRequestData - Array of purchase request objects
* @returns {Array} - Array of objects with M_ItemID, M_ItemCode, M_ItemDesc, unit information, converted PoQty, and Details array
*/
export const groupPurchaseRequestsByItemId_old = (purchaseRequestData) => {
const grouped = groupBy(purchaseRequestData, ['M_ItemID', 'PoItemUnitID']);
console.log("grouped");
console.log(grouped);
return Object.keys(grouped).map(itemId => {
const items = grouped[itemId];
const firstItem = items[0];
/* Sebelum Kalkulasi Konversi Item di BE */
// // Calculate total PoQty from all items
// const totalPoQty = calculateTotalQuantity(items, 'PoQty');
// // Get the conversion factor from the first item
// const conversionFactor = Number(firstItem.DefaultPurchase.UnitConvertAmount) || 1;
// // Convert the total quantity and round up if it's a decimal
// const convertedPoQty = Math.ceil(convertUnits(totalPoQty, conversionFactor));
/* Sesudah Kalkulasi Konversi Item di BE getItem() */
const convertedPoQty = calculateTotalQuantity(items, 'PoQty')
console.log("Total PoQty for itemId", itemId, " : ", convertedPoQty);
let price = 0;
if (parseFloat(firstItem.discount) > 0) {
if (firstItem.discountType === 'P') {
price = Number(firstItem.DefaultPurchase.SupplierPricePrice) - (Number(firstItem.discount) * (Number(firstItem.DefaultPurchase.SupplierPricePrice) / 100));
}
if (firstItem.discountType === 'R') {
price = Number(firstItem.DefaultPurchase.SupplierPricePrice) - Number(firstItem.discount);
}
} else {
price = Number(firstItem.DefaultPurchase.SupplierPricePrice) || 0;
}
// Get the price from the first item
const realPrice = Number(firstItem.DefaultPurchase.SupplierPricePrice) || 0;
// Calculate the total (PoQty * price)
const total = convertedPoQty * price;
const itemParts = itemId.split('_');
const M_ItemID = itemParts[0];
return {
keyID: itemId,
M_ItemID: M_ItemID,
PurchaseOrderID: firstItem.PurchaseOrderID ?? 0,
PurchaseOrderSummaryID: firstItem.PurchaseOrderSummaryID ?? 0,
M_ItemCode: firstItem.M_ItemCode,
M_ItemDesc: firstItem.M_ItemDesc,
discount: firstItem.discount,
discountType: firstItem.discountType,
PoItemUnitID: firstItem.DefaultPurchase.ItemUnitID,
ItemUnitCode: firstItem.DefaultPurchase.ItemUnitCode,
PoItemUnitName: firstItem.DefaultPurchase.ItemUnitName,
TotalPoQty: convertedPoQty,
Price: price,
RealPrice: realPrice,
PriceAfterDiscount: price,
Total: total,
Details: items
};
});
};
export const groupPurchaseRequestsByItemId = async (purchaseRequestData, context) => {
const grouped = groupBy(purchaseRequestData, ['M_ItemID', 'PoItemUnitID']);
console.log("grouped", grouped);
const results = await Promise.all(Object.keys(grouped).map(async (itemId) => {
const items = grouped[itemId];
const firstItem = items[0];
const convertedPoQty = calculateTotalQuantity(items, 'PoQty');
console.log("Total PoQty for itemId", itemId, ":", convertedPoQty);
// Fetch the default supplier price based on the first item's M_ItemID and the converted quantity
// penambahan multi harga di PO (untuk mendapatkan harga sesuai qty)
const supplierPrice = await context.dispatch('getDefaultSupplierPrice', {
itemID: firstItem.M_ItemID,
qty: convertedPoQty
});
if (supplierPrice == null) {
let snackbar = {
state: true,
type: "warning",
message: `Jumlah Quantity tidak tersedia di rentang harga supplier untuk item ${firstItem.M_ItemDesc}!`,
};
context.commit("update_snackbar", snackbar);
context.commit("update_supplierPriceSave", supplierPrice);
context.commit("update_itemDesc", firstItem.M_ItemDesc);
} else {
context.commit("update_supplierPriceSave", supplierPrice);
context.commit("update_itemDesc", '');
}
let price = 0;
if (parseFloat(firstItem.discount) > 0) {
if (firstItem.discountType === 'P') {
price = Number(supplierPrice?.SupplierPricePrice || 0) - (Number(firstItem.discount) * (Number(supplierPrice?.SupplierPricePrice || 0) / 100));
} else if (firstItem.discountType === 'R') {
price = Number(supplierPrice?.SupplierPricePrice || 0) - Number(firstItem.discount);
}
} else {
price = Number(supplierPrice?.SupplierPricePrice || 0) || 0;
}
const total = convertedPoQty * price;
const itemParts = itemId.split('_');
const M_ItemID = itemParts[0];
return {
keyID: itemId,
M_ItemID: M_ItemID,
PurchaseOrderID: firstItem.PurchaseOrderID ?? 0,
PurchaseOrderSummaryID: firstItem.PurchaseOrderSummaryID ?? 0,
M_ItemCode: firstItem.M_ItemCode,
M_ItemDesc: firstItem.M_ItemDesc,
discount: firstItem.discount,
discountType: firstItem.discountType,
PoItemUnitID: firstItem.DefaultPurchase.ItemUnitID,
ItemUnitCode: firstItem.DefaultPurchase.ItemUnitCode,
PoItemUnitName: firstItem.DefaultPurchase.ItemUnitName,
TotalPoQty: convertedPoQty,
Price: price,
RealPrice: Number(supplierPrice?.SupplierPricePrice || 0),
PriceAfterDiscount: price,
Total: total,
Details: items
};
}));
return results; // hasil sudah dalam bentuk array berisi semua item lengkap
};
/**
* Formats a number as currency (IDR)
* @param {Number} amount - The amount to format
* @returns {String} - Formatted currency string
*/
export const formatCurrency = (amount) => {
return new Intl.NumberFormat('id-ID', {
style: 'currency',
currency: 'IDR',
minimumFractionDigits: 0
}).format(amount);
};
/**
* Formats a date to a localized string
* @param {Date|String} date - The date to format
* @param {Object} options - Intl.DateTimeFormat options
* @returns {String} - Formatted date string
*/
export const formatDate = (date, options = {
year: 'numeric',
month: 'long',
day: 'numeric'
}) => {
if (!date) return '';
const dateObj = typeof date === 'string' ? new Date(date) : date;
return new Intl.DateTimeFormat('id-ID', options).format(dateObj);
};
/**
* Calculates the total value of purchase requests
* @param {Array} items - Array of purchase request items
* @returns {Number} - Total value
*/
export const calculateTotal = (items) => {
return items.reduce((sum, item) => sum + (Number(item.Total) || 0), 0);
};
/**
* Calculates the total quantity of items
* @param {Array} items - Array of purchase request items
* @param {String} qtyField - The field name containing quantity (e.g., 'PoQty')
* @returns {Number} - Total quantity
*/
export const calculateTotalQuantity = (items, qtyField = 'PoQty') => {
console.log("Items in calculateTotalQuantity:", items);
return items.reduce((sum, item) => sum + (Number(item[qtyField]) || 0), 0);
};
/**
* Converts units based on the conversion factor
* @param {Number} quantity - The quantity to convert
* @param {Number} conversionFactor - The conversion factor
* @returns {Number} - Converted quantity
*/
export const convertUnits = (quantity, conversionFactor) => {
return quantity / conversionFactor;
};
/**
* Filters purchase requests by branch
* @param {Array} items - Array of purchase request items
* @param {String|Array} branchCodes - Branch code(s) to filter by
* @returns {Array} - Filtered items
*/
export const filterByBranch = (items, branchCodes) => {
if (!branchCodes) return items;
const codes = Array.isArray(branchCodes) ? branchCodes : [branchCodes];
return items.filter(item => codes.includes(item.BranchCode));
};
/**
* Filters purchase requests by regional
* @param {Array} items - Array of purchase request items
* @param {String|Array} regionalIds - Regional ID(s) to filter by
* @returns {Array} - Filtered items
*/
export const filterByRegional = (items, regionalIds) => {
if (!regionalIds) return items;
const ids = Array.isArray(regionalIds) ? regionalIds : [regionalIds];
return items.filter(item => ids.includes(item.S_RegionalID));
};
/**
* Validates if a purchase request item has all required fields
* @param {Object} item - Purchase request item
* @returns {Boolean} - True if valid, false otherwise
*/
export const validatePurchaseRequestItem = (item) => {
const requiredFields = [
'M_ItemID',
'M_ItemCode',
'M_ItemDesc',
'Price',
'RequestQty'
];
return requiredFields.every(field => item[field] !== undefined && item[field] !== null);
};
/**
* Sorts purchase request items by a specified field
* @param {Array} items - Array of purchase request items
* @param {String} field - Field to sort by
* @param {Boolean} ascending - Sort direction (true for ascending, false for descending)
* @returns {Array} - Sorted items
*/
export const sortPurchaseRequests = (items, field = 'M_ItemDesc', ascending = true) => {
return [...items].sort((a, b) => {
const valueA = a[field];
const valueB = b[field];
if (typeof valueA === 'string' && typeof valueB === 'string') {
return ascending
? valueA.localeCompare(valueB)
: valueB.localeCompare(valueA);
}
return ascending
? (valueA - valueB)
: (valueB - valueA);
});
};
/**
* Validates purchase order data before saving
* @param {Object} context - Vuex context object
* @returns {Boolean} - Returns true if validation passes, false otherwise
*/
export const validatePurchaseOrder = (context) => {
if (context.state.loading) {
let snackbar = {
state: true,
type: "warning",
message: 'Loading sedang berlangsung harap menunggu ...',
};
context.commit("update_snackbar", snackbar);
return false;
}
let warningMsg = [];
if (context.state.selectedItem.length == 0) {
warningMsg.push('Belum memilih item');
}
if (!context.state.refNumber || context.state.refNumber.trim() === '') {
warningMsg.push('Nomor Referensi belum diisi');
}
if (!context.state.selectedWarehouse || !context.state.selectedWarehouse.WarehouseID && context.state.warehouseType !== 'Multiple') {
warningMsg.push('Tipe Gudang Single Harus memilih Gudang');
}
if (!context.state.selectedSupplier || !context.state.selectedSupplier.SupplierID) {
warningMsg.push('Supplier belum dipilih');
}
if (context.state.discountType === 'Percentage') {
const discountValue = (context.state.itemTotal.total * context.state.discountAmount) / 100;
if (discountValue > context.state.itemTotal.total) {
warningMsg.push('Diskon tidak boleh melebihi total');
}
} else if (context.state.discountType === 'Absolute') {
if (context.state.discountAmount > context.state.itemTotal.total) {
warningMsg.push('Diskon tidak boleh melebihi total');
}
}
context.state.summary.forEach(element => {
if (Number(element.discount) < 0) {
warningMsg.push('Diskon ' + element.M_ItemDesc + ' tidak boleh kurang dari 0');
}
if (element.discountType === 'P') {
if (Number(element.discount) > 100) {
warningMsg.push('Diskon per item ' + element.M_ItemDesc + ' tidak boleh melebihi 100');
}
}
if (element.discountType === 'R') {
if (Number(element.discount) > Number(element.RealPrice)) {
warningMsg.push('Diskon per item ' + element.M_ItemDesc + ' tidak boleh melebihi dari harga');
}
}
});
if (warningMsg.length > 0) {
let snackbar = {
state: true,
type: "warning",
message: warningMsg.join(", "),
};
context.commit("update_snackbar", snackbar);
return false;
}
return true;
};
/**
* Menghitung total summary untuk purchase order
* @param {Array} summary - Array data summary
* @param {Number} taxPpn - Persentase pajak PPN
* @param {Number} taxPph - Persentase pajak PPH
* @param {String} discountType - Tipe diskon ('Percentage' atau 'Absolute')
* @param {Number} discountAmount - Jumlah diskon
* @returns {Object} - Object summaryTotal
*/
export const calculateSummaryTotal = (summary, taxPpn = 0, taxPph = 0, discountType = 'Percentage', discountAmount = 0) => {
if (!summary || summary.length === 0) {
return {
total: 0,
tax: 0,
ppn: 0,
pph: 0,
discount: 0,
finalTotal: 0,
};
}
// Hitung total dari item summary
const total = summary.reduce((acc, item) => acc + (Number(item.Total) || 0), 0);
// Hitung diskon berdasarkan tipe
let discount = discountAmount;
if (discountType === 'Percentage') {
discount = (discountAmount / 100) * total;
}
// Hitung pajak
const newTotal = total - discount;
const ppn = (taxPpn / 100) * newTotal;
const pph = (taxPph / 100) * newTotal;
const tax = ppn + pph;
const finalTotal = newTotal + tax;
// Return object summaryTotal
return {
total: total,
tax: tax,
ppn: ppn,
pph: pph,
discount: discount,
finalTotal: finalTotal,
};
};
/**
* Menghapus item dari summary dan selectedItem berdasarkan itemId atau detailId
* @param {Array} summary - Array data summary
* @param {Array} selectedItem - Array data selectedItem
* @param {String} itemId - ID item yang akan dihapus (opsional)
* @param {String} detailId - ID detail yang akan dihapus (opsional)
* @returns {Object} - Object berisi summary dan selectedItem yang sudah diupdate
*/
export const deleteItemFromSummary = (summary, selectedItem, itemId = null, detailId = null) => {
// Jika itemId ada, hapus seluruh item dan detailsnya
if (itemId) {
const newSummary = summary.filter(item => item.M_ItemID !== itemId);
const newSelectedItem = selectedItem.filter(item => item.M_ItemID !== itemId);
return {
summary: newSummary,
selectedItem: newSelectedItem
};
}
// Jika detailId ada, hapus detail spesifik
if (detailId) {
// Hapus dari selectedItem
const newSelectedItem = selectedItem.filter(item => item.PurchaseRequestFlagID !== detailId);
// Regenerate summary dari selectedItem yang baru
const newSummary = groupPurchaseRequestsByItemId(newSelectedItem);
return {
summary: newSummary,
selectedItem: newSelectedItem
};
}
return {
summary,
selectedItem
};
};

View File

@@ -0,0 +1,69 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="../../../libs/vendor/css/google-fonts.css">
<link rel="stylesheet" href="../../../libs/vendor/css/icomoon-fonts.css">
<link rel="stylesheet" href="../../../libs/vendor/css/vuetify.min.css">
<title>One</title>
</head>
<body>
<div v-cloak id="app">
<v-app id="smartApp">
<one-navbar></one-navbar>
<v-content style="background: #F5E8DF!important">
<v-container fluid fill-height class="pl-1 pr-1 pt-2 pb-2">
<v-layout row wrap>
<v-flex xs12 class="left" fill-height pa-1>
<po></po>
</v-flex>
</v-layout>
</v-container>
</v-content>
<one-footer></one-footer>
</v-app>
</div>
<!-- Vendor -->
<script src="../../../libs/vendor/moment.min.js"></script>
<script src="../../../libs/vendor/numeral.min.js"></script>
<script src="../../../libs/vendor/moment-locale-id.js"></script>
<script src="../../../libs/vendor/lodash.js"></script>
<script src="../../../libs/vendor/axios.min.js"></script>
<script src="../../../libs/vendor/vue.js"></script>
<script src="../../../libs/vendor/vuex.js"></script>
<script src="../../../libs/vendor/vuetify.js"></script>
<script src="../../../libs/vendor/httpVueLoader.js"></script>
<script src="../../../libs/one_global.js"></script>
<!-- App Script -->
<script type="module">
import {
store
} from './store.js';
window.store = store;
new Vue({
store,
el: "#app",
methods: {},
components: {
'one-navbar': httpVueLoader('../../../apps/components/oneNavbarComponent.vue'),
'one-footer': httpVueLoader('../../../apps/components/oneFooter.vue'),
// 'request-listing': httpVueLoader('./components/requestListing.vue'),
// 'request-kacab': httpVueLoader('./components/acconeprkacab.vue'),
'po': httpVueLoader('./components/po.vue')
}
})
</script>
<style>
[v-cloak] {
display: none
}
</style>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,14 @@
// import manager from "./modules/manager.js";
// import prkacab from "./modules/prkacab.js"
import system from "../../../apps/modules/system/system.js";
import po from "./modules/po.js";
export const store = new Vuex.Store({
modules: {
po: po,
system: system
},
state: {},
mutations: {},
actions: {},
});

View File

@@ -0,0 +1,401 @@
const URL = "/one-api/mockup/purchase/cashier/";
export async function search(prm) {
try {
var resp = await axios.post(URL + "purchaseRequestDirectRealitation/search", prm);
if (resp.status !== 200) {
return {
status: "ERR",
message: resp.statusText,
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function searchBranch(token, prm) {
try {
var resp = await axios.post(URL + 'purchaseRequestDirect/getbranch',{
token: token,
search: prm
});
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function searchAccDana(token, prm) {
try {
var resp = await axios.post(URL + 'purchaseRequestDirect/getcoa', {
token: token,
search: prm
});
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function searchAccBiaya(token, prm) {
try {
var resp = await axios.post(URL + 'purchaseRequestDirect/getcoa', {
token: token,
search: prm
});
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function searchAccTemp(token, prm) {
try {
var resp = await axios.post(URL + 'purchaseRequestDirect/getcoa', {
token: token,
search: prm
});
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function getPurchase(token, prm) {
try {
var resp = await axios.post(URL + "purchaseRequestDirect/getPurchase", {
token: token,
branchcode: prm,
}
);
if (resp.status !== 200) {
return {
status: "ERR",
message: resp.statusText,
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function searchdetail(token, prm) {
try {
var resp = await axios.post(URL + "purchaseRequestDirectRealitation/searchdetail", {
token: token,
ID: prm,
}
);
if (resp.status !== 200) {
return {
status: "ERR",
message: resp.statusText,
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function saveDetail(token, prm) {
try {
var resp = await axios.post(URL + "purchaseRequestDirect/save", {
token: token,
BranchCode: prm.branch,
CoaSourceID: prm.accountDana,
CoaExpenseID: prm.accountBiaya,
CoaTemporaryID: prm.accountTemp,
total: prm.total,
details: prm.details
}
);
if (resp.status !== 200) {
return {
status: "ERR",
message: resp.statusText,
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function getTotalDraft(token) {
try {
var resp = await axios.post(URL + 'purchaseRequestDirectRealitation/getTotalDraft', {
token: token
});
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function getTotalPaid(token) {
try {
var resp = await axios.post(URL + 'purchaseRequestDirectRealitation/getTotalPaid', {
token: token
});
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function deleteVoucher(token, prm) {
try {
var resp = await axios.post(URL + 'purchaseRequestDirect/delete', {
token: token,
ID: prm.PVID
});
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function editVoucher(prm) {
try {
// console.log(prm)
var resp = await axios.post(URL + "purchaseRequestDirectRealitation/update",prm);
// console.log(resp)
if (resp.status !== 200) {
return {
status: "ERR",
message: resp.statusText,
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function updatepaid(prm) {
try {
// console.log(prm)
var resp = await axios.post(URL + "purchaseRequestDirectRealitation/updatepaid", prm);
console.log('api resp',resp)
if (resp.status !== 200) {
return {
status: "ERR",
message: resp.statusText,
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function getPurchaseUpdateNew(token, prm) {
try {
var resp = await axios.post(URL + "purchaseRequestDirect/getPurchaseUpdateNew", {
token: token,
branchcode: prm.branchcode,
ID: prm.voucherID
}
);
if (resp.status !== 200) {
return {
status: "ERR",
message: resp.statusText,
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function getUserReceive(prm) {
try {
var resp = await axios.post(URL + "purchaseRequestDirectRealitation/getUserReceive", prm);
if (resp.status !== 200) {
return {
status: "ERR",
message: resp.statusText,
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function getVoucherDetail(params) {
try {
var resp = await axios.post(URL + "purchaseRequestDirectRealitation/getVoucherDetail", params);
if (resp.status !== 200) {
return {
status: "ERR",
message: resp.statusText,
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function saveVoucherDetail(params) {
try {
var resp = await axios.post(URL + "purchaseRequestDirectRealitation/saveVoucherDetail", params);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.message
}
}
let data = resp.data
return data;
} catch (error) {
return {
status: "ERR",
message: error.message
}
}
}
export async function editVoucherV2(prm) {
try {
// console.log(prm)
var resp = await axios.post(URL + "purchaseRequestDirectRealitation/updateV2",prm);
// console.log(resp)
if (resp.status !== 200) {
return {
status: "ERR",
message: resp.statusText,
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}

View File

@@ -0,0 +1,700 @@
<template>
<div style="width: 100%;">
<!-- SNACKBAR -->
<v-snackbar
v-model="snackbar"
:timeout="5000"
:multi-line="false"
:vertical="false"
:top="true"
>
{{ msgSnackbar }}
<v-btn flat @click="updateAlertSuccess(false)"> Tutup </v-btn>
</v-snackbar>
<!-- ERROR DIALOG -->
<v-dialog v-model="dialog_error" max-width="500px">
<v-card>
<v-card-title>
<span>ERROR !</span>
<v-spacer></v-spacer>
</v-card-title>
<v-divider></v-divider>
<div class="ma-3 red--text">{{ msgError }}</div>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="primary" flat @click="dialog_error = false"
>Tutup</v-btn
>
</v-card-actions>
</v-card>
</v-dialog>
<!-- END ERROR DIALOG -->
<v-layout row wrap>
<v-flex xs12 fill-height pa-1>
<v-toolbar color="primary" dark>
<v-toolbar-title class="white--text"
>KASIR</v-toolbar-title
>
<v-spacer></v-spacer>
<v-btn v-if="(status != '' || status != null) && (xdate != '' && xdate != null)" @click="goBack()" color="orange darken-2" title="Kembali ke listing pending approval" dark>
<v-icon dark left>arrow_back</v-icon>Back
</v-btn>
</v-toolbar>
<v-card class="pa-2">
<v-layout>
<v-flex xs3 pl-2>
<v-menu
v-model="menuStartDate"
:close-on-content-click="false"
transition="scale-transition"
:nudge-right="40"
lazy
offset-y
max-width="290px"
min-width="290px"
>
<template v-slot:activator="{ on }">
<v-text-field
v-model="startDateFormatted"
label="Tanggal Awal"
readonly
style="max-width: 250px"
outline
hide-details
v-on="on"
@blur="dStartDate = deFormatedDate(startDateFormatted)"
></v-text-field>
</template>
<v-date-picker
no-title
v-model="xStartDate"
@input="menuStartDate = false"
></v-date-picker>
</v-menu>
</v-flex>
<v-flex xs3 pl-2>
<v-menu
v-model="menuEndDate"
:close-on-content-click="false"
transition="scale-transition"
:nudge-right="40"
lazy
offset-y
max-width="290px"
min-width="290px"
>
<template v-slot:activator="{ on }">
<v-text-field
v-model="endDateFormatted"
label="Tanggal Akhir"
readonly
style="max-width: 250px"
outline
hide-details
v-on="on"
@blur="dEndDate = deFormatedDate(endDateFormatted)"
></v-text-field>
</template>
<v-date-picker
no-title
v-model="xEndDate"
@input="menuEndDate = false"
></v-date-picker>
</v-menu>
</v-flex>
<v-flex xs3 pl-2>
<v-autocomplete
return-object
item-text="text"
label="Status"
:items="statusOptions"
v-model="selected_status"
outline
hide-details
></v-autocomplete>
</v-flex>
<v-flex xs3 pl-2>
<v-text-field
label="Cari..."
placeholder="NO."
outline
hide-details
v-model="xsearch"
></v-text-field>
</v-flex>
<v-flex pl-2 pr-2>
<v-btn
dark
color="primary"
style="min-width: 50px; height: 50px; margin: 0"
@click="mainTableSearch()"
>
<v-icon>search</v-icon>
</v-btn>
</v-flex>
</v-layout>
</v-card>
<v-card class="pa-2 mt-2">
<v-layout row wrap>
<v-flex xs12 pl-2>
<div v-if="selected_status.text == 'Draft'">
<span>Total belum di bayar : </span>
<span>{{ totalDraft }}</span>
</div>
<div v-if="selected_status.text == 'Paid'">
<span>Total belum di realisasi : </span>
<span>{{ totalPaid }}</span>
</div>
</v-flex>
</v-layout>
<v-layout row style="max-height: 600px; overflow: auto">
<v-flex xs12 pl-2 pr-2 pt-2 pb-2>
<v-data-table
:items="xvoucehrList"
:headers="headers"
:loading="isLoading"
hide-actions
class="elevation-1"
>
<template slot="items" slot-scope="props">
<td
class="text-xs-left pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)"
>
<p class="mb-0 font-weight-bold" style="color:#000000">{{ props.item.PaymentVoucherNumber }}</p>
<p class="mb-0 info--text mono font-weight-bold caption">{{ formatDateHeader(props.item.PaymentVoucherDate) }}</p>
</td>
<td
class="text-xs-left pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)"
>
<p class="mb-0">{{ props.item.M_BranchName }}</p>
<p class="mb-0 font-weight-bold" style="color:#000000">Total : Rp {{ convertMoney(props.item.PaymentVoucherTotal) }}</p>
</td>
<td
class="text-xs-left pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)"
>{{ formatDateHeader(props.item.PaymentVoucherRealitationDate) }}</td>
<td
class="text-xs-center pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)"
>
<v-chip
small
:text-color="props.item.PaymentVoucherStatus === 'Draft' ? 'black' : 'white'"
:color="getChipStatusColor(props.item.PaymentVoucherStatus)">
{{ props.item.PaymentVoucherStatus }}
</v-chip>
</td>
<template v-if="props.item.PaymentVoucherStatus == 'Draft'">
<td class="text-xs-center pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)"
>
<v-btn small color="lime darken-2" dark @click="openDialogPay(props.item)">Bayar</v-btn>
</td>
</template>
<template v-else-if="props.item.PaymentVoucherStatus == 'Paid'">
<td class="text-xs-center pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)"
>
<v-icon class="mr-2" color="orange" small @click="doPrintPaid(props.item)">picture_as_pdf</v-icon>
<v-btn small color="teal darken-2" dark @click="openDialogUpdate(props.item)">Realisasi</v-btn>
</td>
</template>
<template v-else-if="props.item.PaymentVoucherStatus == 'Realitation'">
<td
class="text-xs-center pa-2"
v-bind:class="{
'amber lighten-4': isSelected(props.item),
}"
>
<v-icon class="mr-2" color="orange" small @click="doPrintPaid(props.item)">picture_as_pdf</v-icon>
<v-icon class="mr-2" color="teal" small @click="doPrintRealitation(props.item)">picture_as_pdf</v-icon>
</td>
</template>
</template>
</v-data-table>
</v-flex>
</v-layout>
<v-divider></v-divider>
<v-pagination
style="margin-top: 10px; margin-bottom: 10px"
v-model="curr_page"
:length="xtotal_page"
></v-pagination>
</v-card>
</v-flex>
</v-layout>
<!-- <dialog-form></dialog-form> -->
<!-- <dialog-realized-item></dialog-realized-item> -->
<dialog-form-realise></dialog-form-realise>
<dialog-view-img></dialog-view-img>
<dialog-form-pay></dialog-form-pay>
<one-dialog-alert
:status="dialogAlertDelete"
:msg="msgAlertDelete"
@forget-dialog-alert="dialogAlertDelete = false"
@close-dialog-alert="closeAndDelete()"
></one-dialog-alert>
<one-dialog-print :title="printtitle" :width="printwidth" :height="700" :status="openprint" :urlprint="urlprint"
@close-dialog-print="openprint = false"></one-dialog-print>
</div>
</template>
<style scoped>
.date-type-table {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.table.v-table tbody td,
table.v-table tbody th {
height: 40px;
}
.table.v-table thead tr {
height: 40px;
}
.scroll-container {
scroll-padding: 50px 0 0 50px;
}
.wrap-header {
white-space: normal !important;
line-height: 1.2;
word-break: break-word;
text-align: center;
}
</style>
<script>
module.exports = {
components: {
"dialog-form": httpVueLoader("./dialogForm.vue"),
"dialog-form-pay": httpVueLoader("./dialogFormPay.vue"),
"dialog-realized-item": httpVueLoader("./dialogItemRealize.vue"),
"dialog-form-realise": httpVueLoader("./dialogFormRealise.vue"),
"dialog-view-img": httpVueLoader("./dialogViewImg.vue"),
"one-dialog-alert": httpVueLoader("../../common/oneDialogAlert.vue"),
"one-dialog-error": httpVueLoader("../../common/oneDialogError.vue"),
'one-dialog-print': httpVueLoader('../../common/oneDialogPrintX.vue')
},
data() {
return {
msgAlertDelete: "",
dialogAlertDelete: false,
xPVID: 0,
xPVNumber: "",
formatreport: "pdf",
urlprint: "",
printtitle: '',
printwidth: '100%',
headers: [
{
text: "NO / TANGGAL",
align: "center",
sortable: false,
value: "no",
width: "20%",
class: "blue lighten-3 white--text",
},
{
text: "PENERIMA",
align: "center",
sortable: false,
value: "supplier",
width: "19%",
class: "blue lighten-3 white--text",
},
{
text: "TANGGAL REALISASI",
align: "center",
sortable: false,
value: "total",
width: "16%",
class: "blue lighten-3 white--text",
},
{
text: "STATUS",
align: "center",
sortable: false,
value: "status",
width: "15%",
class: "blue lighten-3 white--text",
},
{
text: "AKSI",
align: "center",
sortable: false,
value: "status",
width: "15%",
class: "blue lighten-3 white--text",
},
],
}
},
mounted() {
this.$store.dispatch("cashier/search");
this.$store.dispatch("cashier/getTotalDraft");
this.$store.dispatch("cashier/getTotalPaid");
},
computed: {
status() {
return this.$store.state.cashier.status;
},
xdate() {
return this.$store.state.cashier.xdate;
},
statusOptions() {
return this.$store.state.cashier.status_options;
},
selected_status: {
get() {
return this.$store.state.cashier.selected_status;
},
set(val) {
this.$store.commit("cashier/update_selected_status", val);
this.mainTableSearch();
},
},
menuStartDate: {
get() {
return this.$store.state.cashier.menuStartDate;
},
set(val) {
this.$store.commit("cashier/update_menuStartDate", val);
},
},
menuEndDate: {
get() {
return this.$store.state.cashier.menuEndDate;
},
set(val) {
this.$store.commit("cashier/update_menuEndDate", val);
},
},
startDateFormatted() {
return this.formatDate(this.xStartDate);
},
endDateFormatted() {
return this.formatDate(this.xEndDate);
},
xStartDate: {
get() {
return this.$store.state.cashier.xStartDate;
},
set(val) {
this.$store.commit("cashier/update_xStartDate", val);
},
},
xEndDate: {
get() {
return this.$store.state.cashier.xEndDate;
},
set(val) {
this.$store.commit("cashier/update_xEndDate", val);
},
},
dEndDate: {
get() {
return this.$store.state.cashier.dEndDate;
},
set(val) {
this.$store.commit("cashier/update_dEndDate", val);
},
},
dStartDate: {
get() {
return this.$store.state.cashier.dStartDate;
},
set(val) {
this.$store.commit("cashier/update_dStartDate", val);
},
},
xvoucehrList() {
return this.$store.state.cashier.cashierList;
},
curr_page: {
get() {
return this.$store.state.cashier.currentPage;
},
set(val) {
this.$store.commit("cashier/update_currentPage", val);
this.mainTableSearch();
},
},
xtotal_page: {
get() {
return this.$store.state.cashier.total_page_cashier;
},
set(val) {
this.$store.commit("cashier/update_total_page_cashier", val);
},
},
xsearch: {
get() {
return this.$store.state.cashier.xsearch;
},
set(val) {
this.$store.commit("cashier/update_xsearch", val);
},
},
isLoading() {
return this.$store.state.cashier.search_status === 1;
},
msgSnackbar() {
return this.$store.state.cashier.success_message;
},
snackbar: {
get() {
return this.$store.state.cashier.alert_success;
},
set(val) {
this.$store.commit("cashier/update_alert_success", val);
},
},
dialog_error: {
get() {
return this.$store.state.cashier.alert_error;
},
set(val) {
this.$store.commit("cashier/update_alert_error", val);
},
},
msgError: {
get() {
return this.$store.state.cashier.error_message;
},
set(val) {
this.$store.commit("cashier/update_error_message", val);
}
},
totalDraft() {
return this.$store.state.cashier.totalDraft
},
totalPaid() {
return this.$store.state.cashier.totalPaid
},
openprint: {
get() {
return this.$store.state.cashier.openprint;
},
set(val) {
this.$store.commit("cashier/update_openprint", val);
},
},
voucher_details() {
return this.$store.state.cashier.details
}
},
methods: {
goBack() {
window.history.back();
// location.href = "/one-ui/test/vuex/one-accone-approve-all/"
},
convertMoney(money){
return one_money(money)
},
doPrintPaid(val) {
// console.log(val)
this.printwidth = 1028
this.printtitle = ""
let user = one_user()
tm = Date.now()
var rptname = 'rpt_payment_voucher_paid_001'
var formatrpt = this.formatreport
this.urlprint = "/birt/run?__report=report/one/accounting/" + rptname + ".rptdesign&__format=" + formatrpt + "&PID=" + val.PaymentVoucherID + "&username=" + user.M_StaffName + "&tm=" + tm
// console.log(this.urlprint)
this.$store.commit("cashier/update_openprint", true)
},
doPrintRealitation(val) {
// console.log(val)
this.printwidth = 1028
this.printtitle = ""
let user = one_user()
tm = Date.now()
var rptname = 'rpt_payment_voucher_realitation_001'
var formatrpt = this.formatreport
this.urlprint = "/birt/run?__report=report/one/accounting/" + rptname + ".rptdesign&__format=" + formatrpt + "&PID=" + val.PaymentVoucherID + "&username=" + user.M_StaffName + "&tm=" + tm
// console.log(this.urlprint)
this.$store.commit("cashier/update_openprint", true)
},
isSelected(o) {
return o.PaymentVoucherID == this.$store.state.cashier.selected_cashier.PaymentVoucherID;
},
selectMe(sc) {
this.$store.commit("cashier/update_selected_cashier", sc);
this.$store.dispatch("cashier/searchdetail", sc.PaymentVoucherID);
this.$store.dispatch("cashier/getVoucherDetail");
},
openDialogVoucher() {
this.$store.commit("cashier/update_dialog_cashier", true);
this.$store.commit("cashier/update_act", "new");
this.$store.commit("cashier/update_selected_branch", {});
this.$store.commit("cashier/update_selected_accountDana", {});
this.$store.commit("cashier/update_selected_accountBiaya", {});
this.$store.commit("cashier/update_selected_accountTemp", {});
this.$store.commit("cashier/update_selected_purchase", []);
this.$store.commit("cashier/update_purchaseList", []);
this.$store.commit("cashier/update_resume_total", {"totalRealitation": 0});
},
formatDate(date) {
if (!date) return null;
const [year, month, day] = date.split("-");
return `${day}-${month}-${year}`;
},
formatDateHeader(date) {
if (!date) return null;
const cleanDate = date.split(" ")[0];
const [year, month, day] = cleanDate.split("-");
return `${day}-${month}-${year}`;
},
deFormatedDate(date) {
if (!date) return null;
const [day, month, year] = date.split("-");
return `${year}-${month.padStart(2, "0")}-${day.padStart(2, "0")}`;
},
getChipStatusColor(status) {
switch (status) {
case "Paid":
return "warning";
case "Realitation":
return "success";
default:
return "";
}
},
mainTableSearch() {
this.$store.dispatch("cashier/search");
},
thr_searchDate: _.debounce(function () {
this.$store.dispatch("cashier/search")
}, 1000),
thr_search: _.debounce(function () {
this.$store.dispatch("cashier/search")
}, 1000),
deleteVoucher(data) {
this.xPVID = data.PaymentVoucherID;
this.xPVNumber = data.PaymentVoucherNumber;
this.msgAlertDelete = `Yakin, mau hapus Payment Voucher [${data.PaymentVoucherNumber}] ?`;
this.dialogAlertDelete = true;
},
closeAndDelete() {
// this.$store.dispatch("cashier/delete", {
// PVID: this.xPVID,
// PVNumber: this.xPVNumber
// });
this.dialogAlertDelete = false
},
openDialogUpdate(data) {
this.$store.commit("cashier/update_act", "edit");
this.$store.commit("cashier/update_dialog_cashier", true);
this.$store.commit("cashier/update_imageRelationPreviews", []);
this.$store.commit("cashier/update_imageRelationFiles", []);
const fileBaseUrl = BASE_URL + "/one-media/cashier/";
const allImageUrls = [];
for (let index = 0; index < data.dataAttachment.length; index++) {
const element = data.dataAttachment[index];
if (element.PurchaseDirectAttachmentName == null || element.PurchaseDirectAttachmentName == '') {
continue;
}
allImageUrls.push(fileBaseUrl + element.PurchaseDirectAttachmentName)
}
this.$store.commit("cashier/update_imagePrevPaid", allImageUrls);
},
openDialogPay(data) {
// cek detail sudah terisi account biaya atau belum
const voucherdetails = this.voucher_details;
const incomplete = voucherdetails.some(element => {
const acc = element.account_biaya
const splitacc = acc.split(';').map(part => part.trim())
return splitacc.some(account => account === 'notset')
});
if (incomplete) {
this.dialog_error = true
this.msgError = 'Terdapat item voucher yang belum diset account biayanya'
return;
}
this.$store.dispatch("cashier/getUserReceive");
this.$store.commit("cashier/update_act", "edit");
this.$store.commit("cashier/update_dialog_cashier_pay", true);
this.$store.commit("cashier/update_imagePayPreviews", []);
const fileBaseUrl = BASE_URL + "/one-media/cashier/";
const allImageUrls = [];
const allNumberRequest = [];
let descriptions = '';
for (let index = 0; index < data.dataAttachment.length; index++) {
const element = data.dataAttachment[index];
if (element.PurchaseDirectAttachmentName == null || element.PurchaseDirectAttachmentName == '') {
continue;
}
allImageUrls.push(fileBaseUrl + element.PurchaseDirectAttachmentName)
}
this.$store.commit("cashier/update_imagePreviews", allImageUrls);
for (let index = 0; index < data.requestNumber.length; index++) {
const element = data.requestNumber[index];
allNumberRequest.push(element.PurchaseRequestDirectNumber)
let desc = element.PurchaseRequestDirectDescription;
descriptions += desc;
if (index !== data.requestNumber.length - 1) {
descriptions += ', ';
}
}
this.$store.commit("cashier/update_numberRequest", allNumberRequest);
this.$store.commit("cashier/update_requestDescription", descriptions);
}
},
watch: {
xStartDate(val, old) {
this.xStartDate = val;
this.thr_searchDate();
},
xEndDate(val, old) {
this.xEndDate = val;
this.thr_searchDate();
},
xsearch(val, old) {
this.xsearch = val;
this.thr_search();
},
}
}
</script>

View File

@@ -0,0 +1,682 @@
<template>
<v-layout row justify-center>
<v-dialog v-model="dialogVoucher" persistent max-width="50vw">
<v-card>
<v-card-title class="headline grey lighten-2" primary-title>
FORM REALISASI
</v-card-title>
<v-card-text class="pt-2 pb-0">
<v-layout row>
<v-flex xs12 pa-2>
<v-textarea
filled
outline
hide-details
label="Catatan*"
rows="3"
v-model="xnote"
></v-textarea>
<p v-if="checkErrorForm('requireNote')" class="error pl-2 pr-2" style="color:#fff">Catatan harus diisi</p>
</v-flex>
</v-layout>
<v-layout mr-2 ml-2 style="border:1px solid black" align-center row pa-2 mb-2>
<v-flex xs9>
<!-- <input type="file" ref="image" accept="image/*" @change="onFilePicked"> -->
<input type="file" id="files" ref="files" accept="image/*" multiple v-on:change="onFilePicked()"/>
</v-flex>
</v-layout>
<v-layout v-if="show_progrees_upload" row align-center mr-2 ml-2>
<v-flex xs12>
<v-progress-linear :indeterminate="true"></v-progress-linear>
</v-flex>
</v-layout>
<v-layout v-if="imageRelationPreviews.length > 0 && !show_progrees_upload" align-center row wrap>
<v-flex
v-for="(imgUrl, index) in imageRelationPreviews"
:key="index"
xs6
class="pa-2">
<v-img :src="imgUrl">
<div class="fill-height bottom-gradient"></div>
</v-img>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs12 pa-2>
<v-text-field
prefix="Rp"
v-model="formatted_total_price"
readonly
hide-details
outline
label="Total Bayar">
</v-text-field>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs11 pl-2>
<v-text-field
prefix="Rp"
v-model="formattedRestPrice"
@blur="resetRestPrice"
@focus="clearRestPrice"
outline readonly
hide-details
label="Harga">
</v-text-field>
</v-flex>
<v-flex xs>
<v-btn
outline color="blue lighten-2"
@click="openRealisedItem()"
>
<v-icon small color="blue">edit</v-icon>
</v-btn>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs12 pa-2>
<v-text-field
prefix="Rp"
v-model="formattedTotalAkhir"
readonly
hide-details
outline
label="Sisa">
</v-text-field>
</v-flex>
</v-layout>
<v-divider></v-divider>
<v-layout v-if="imagePrevPaid.length > 0" pt-2>
<v-flex xs12 pa-2>
<span class="font-weight-bold">BUKTI PEMBAYARAN :</span>
</v-flex>
</v-layout>
<v-layout v-if="imagePrevPaid.length > 0" align-center row wrap>
<v-flex
v-for="(img, index) in imagePrevPaid"
:key="index"
xs6
class="pa-2"
>
<v-img :src="img">
<div class="fill-height bottom-gradient"></div>
</v-img>
</v-flex>
</v-layout>
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="error" flat @click="closeDiallogCashier()"> Tutup </v-btn>
<v-btn v-if="xact === 'new'" color="primary" dark @click="saveVoucher()">Simpan</v-btn>
<v-btn v-if="xact === 'edit'" color="primary" dark @click="updateChasier()">Realisasi & Simpan</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-layout>
</template>
<script>
module.exports = {
name: "DialogFormVoucher",
data() {
return {
url: "",
filesToUpload: [],
fileName: "", // Untuk menyimpan nama file
imageName: "",
imageFile: "",
imageUrl: "",
headers: [
{
text: "NO",
align: "left",
sortable: false,
value: "no",
width: "15%",
class: "blue lighten-3 white--text",
},
{
text: "DESKRIPSI",
align: "left",
sortable: false,
value: "date",
width: "40%",
class: "blue lighten-3 white--text",
},
{
text: "TOTAL REALISASI",
align: "left",
sortable: false,
value: "supplier",
width: "30%",
class: "blue lighten-3 white--text",
},
{
text: "AKSI",
align: "left",
sortable: false,
value: "status",
width: "15%",
class: "blue lighten-3 white--text",
},
],
};
},
mounted() {
},
computed: {
formatted_total_price() {
var val = Object.keys(this.$store.state.cashier.selected_cashier).length > 0 ? this.$store.state.cashier.selected_cashier.PaymentVoucherTotal : 0;
return this.oneMoney(val);
},
formattedRestPrice: {
get() {
return this.oneMoney(this.restPrice);
},
set(value) {
// Hilangkan titik dan koma, ubah jadi number
let raw = value.replace(/\./g, '').replace(',', '.');
this.restPrice = parseFloat(raw) || 0;
}
},
total_akhir() {
return this.$store.state.cashier.total_akhir;
},
formattedTotalAkhir: {
get() {
return this.oneMoney(this.total_akhir);
},
set(value) {
// Hilangkan titik dan koma, ubah jadi number
let raw = value.replace(/\./g, '').replace(',', '.');
this.total_akhir = parseFloat(raw) || 0;
}
},
dialogVoucher: {
get() {
return this.$store.state.cashier.dialog_cashier;
},
set(val) {
this.$store.commit("cashier/update_dialog_cashier", val);
},
},
branchList() {
return this.$store.state.cashier.branchList;
},
selectedBranch: {
get() {
return this.$store.state.cashier.selected_branch;
},
set(val) {
this.$store.commit("cashier/update_selected_branch", val);
this.getPurchaseReq();
},
},
search_branch: {
get() {
return this.$store.state.cashier.search_branch;
},
set(val) {
this.$store.commit("cashier/update_search_branch", val);
},
},
accountDanaList() {
return this.$store.state.cashier.accountDanaList;
},
selectedAccountDana: {
get() {
return this.$store.state.cashier.selected_accountDana;
},
set(val) {
this.$store.commit("cashier/update_selected_accountDana", val);
},
},
search_accountDana: {
get() {
return this.$store.state.cashier.search_accountDana;
},
set(val) {
this.$store.commit("cashier/update_search_accountDana", val);
},
},
accountBiayaList() {
return this.$store.state.cashier.accountBiayaList;
},
selectedAccountBiaya: {
get() {
return this.$store.state.cashier.selected_accountBiaya;
},
set(val) {
this.$store.commit("cashier/update_selected_accountBiaya", val);
},
},
search_accountBiaya: {
get() {
return this.$store.state.cashier.search_accountBiaya;
},
set(val) {
this.$store.commit("cashier/update_search_accountBiaya", val);
},
},
accountTempList() {
return this.$store.state.cashier.accountTempList;
},
selectedAccountTemp: {
get() {
return this.$store.state.cashier.selected_accountTemp;
},
set(val) {
this.$store.commit("cashier/update_selected_accountTemp", val);
},
},
search_accountTemp: {
get() {
return this.$store.state.cashier.search_accountTemp;
},
set(val) {
this.$store.commit("cashier/update_search_accountTemp", val);
},
},
purchaseList() {
return this.$store.state.cashier.purchaseList;
},
selected_purchase: {
get() {
return this.$store.state.cashier.selected_purchase;
},
set(val) {
this.$store.commit("cashier/update_selected_purchase", val);
},
},
resume() {
return this.$store.state.cashier.resume_total;
},
xact: {
get() {
return this.$store.state.cashier.act;
},
set(val) {
this.$store.commit("cashier/update_act", val);
},
},
show_progrees_upload: {
get() {
return this.$store.state.cashier.show_progrees_upload
},
set(val) {
this.$store.commit("cashier/update_show_progrees_upload", val)
}
},
xnote: {
get() {
return this.$store.state.cashier.note
},
set(val) {
this.$store.commit("cashier/update_note", val)
}
},
restPrice: {
get() {
return this.$store.state.cashier.restPrice
},
set(val) {
this.$store.commit("cashier/update_restPrice", val)
}
},
imagePrevPaid: {
get() {
return this.$store.state.cashier.imagePrevPaid
},
set(val) {
this.$store.commit("cashier/update_imagePrevPaid", val)
}
},
imageRelationPreviews: {
get() {
return this.$store.state.cashier.imageRelationPreviews;
},
set(val) {
this.$store.commit("cashier/update_imageRelationPreviews", val);
},
},
imageRelationFiles: {
get() {
return this.$store.state.cashier.imageRelationFiles;
},
set(val) {
this.$store.commit("cashier/update_imageRelationFiles", val);
},
},
},
methods: {
roundToThreeSignificantDigits(num) {
if (num === 0) return 0;
// Hitung jumlah digit
const absNum = Math.abs(num);
const magnitude = Math.floor(Math.log10(absNum)) + 1;
// Jika kurang dari 3 digit, tidak perlu dibulatkan
if (magnitude <= 3) return num;
// Hitung faktor pembulatan
const factor = Math.pow(10, magnitude - 3);
// Bulatkan
return Math.round(num / factor) * factor;
},
oneMoney(value){
//return one_money(value);
let splitValue = value.toString().split(".");
if(splitValue.length > 1) {
let val = splitValue[0]
return val.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".") + "," + this.roundToThreeSignificantDigits(splitValue[1]);
} else {
return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".");
}
},
convertMoney(money){
return one_money(money)
},
formatAngka(nilai) {
// Jika tidak ada nilai
if (!nilai) return '';
try {
// Ubah ke string
let strNilai = String(nilai);
// Jika berisi titik desimal
if (strNilai.includes('.')) {
// Split bagian utama dan desimal
let bagian = strNilai.split('.');
let utama = bagian[0];
let desimal = bagian[1];
// Format bagian utama
utama = utama.replace(/\B(?=(\d{3})+(?!\d))/g, '.');
// Kembalikan gabungan
return utama + ',' + desimal;
} else {
// Tidak ada desimal, hanya format bagian utama
return strNilai.replace(/\B(?=(\d{3})+(?!\d))/g, '.');
}
} catch (error) {
console.error("Error formatting:", error);
return nilai;
}
},
resetRestPrice() {
if (this.restPrice === '' || this.restPrice === null) {
this.restPrice = 0
}
},
clearRestPrice() {
if (this.restPrice === 0) {
this.restPrice = ''
}
},
handleFileUploadsbkp(){
// this.files = this.$refs.files.files
const files = this.$refs.files.files;
this.urls = [];
this.filesToUpload = [];
for (let i = 0; i < files.length; i++) {
const file = files[i];
const url = URL.createObjectURL(file);
this.urls.push(url);
this.filesToUpload.push(file);
}
// console.log('urls', this.urls)
console.log('filesToUpload', this.filesToUpload)
},
handleFileUploads(){
const file = this.$refs.files.files[0];
if (file) {
this.fileName = file.name; // Simpan nama file
this.filesToUpload = [file]; // Masukkan ke array untuk konsistensi
this.url = URL.createObjectURL(file); // Preview jika diperlukan
}
},
onFilePicked(){
// this.files = this.$refs.files.files
const files = this.$refs.files.files;
this.imageRelationPreviews = [];
this.imageRelationFiles = [];
for (let i = 0; i < files.length; i++) {
const file = files[i];
const url = URL.createObjectURL(file);
this.imageRelationPreviews.push(url);
this.imageRelationFiles.push(file);
}
},
onFilePicked_old(e) {
const files = e.target.files
console.log('cek files',files[0]);
if (files[0] !== undefined) {
this.imageName = files[0].name
if (this.imageName.lastIndexOf('.') <= 0) {
return
}
const fr = new FileReader()
fr.readAsDataURL(files[0])
fr.addEventListener('load', () => {
this.imageUrl = fr.result
this.imageFile = files[0] // this is an image file that can be sent to server...
})
// console.log('imageName', this.imageName)
// console.log('imageFile', this.imageFile)
// console.log('imageUrl', this.imageUrl)
} else {
this.imageName = ''
this.imageFile = ''
this.imageUrl = ''
}
},
thr_search_branch: _.debounce(function() {
this.$store.dispatch("cashier/searchBranch", this.search_branch);
}, 500),
thr_search_accountDana: _.debounce(function() {
this.$store.dispatch("cashier/searchAccDana", this.search_accountDana);
}, 500),
thr_search_accountBiaya: _.debounce(function() {
this.$store.dispatch("cashier/searchAccBiaya", this.search_accountBiaya);
}, 500),
thr_search_accountTemp: _.debounce(function() {
this.$store.dispatch("cashier/searchAccTemp", this.search_accountTemp);
}, 500),
getPurchaseReq() {
this.$store.dispatch("cashier/getPurchase", this.selectedBranch === undefined ? "" : this.selectedBranch.M_BranchCode);
},
formatCurrency(val) {
// Format the price above to USD using the locale, style, and currency.
let price = parseFloat(val);
let USDollar = new Intl.NumberFormat("id-ID", {
style: "currency",
currency: "IDR",
});
// console.log(
// `The formated version of ${price} is ${USDollar.format(price)}`
// );
return `${USDollar.format(price)}`;
},
addPurchase(item) {
let selected_purchase = this.$store.state.cashier.selected_purchase;
selected_purchase.push(item);
let totalRealitation = 0;
for (let i = 0; i < selected_purchase.length; i++) {
const e = selected_purchase[i];
totalRealitation += parseFloat(e.PurchaseRequestDirectTotalRealitation);
}
let xresume = {
"totalRealitation": totalRealitation,
};
this.$store.commit("cashier/update_resume_total", xresume);
},
purchaseExist(item) {
let selected_purchase = this.$store.state.cashier.selected_purchase;
let found = selected_purchase.find((el) => el.PurchaseRequestDirectID === item.PurchaseRequestDirectID);
if (found) {
return false;
}
return true;
},
removePurchase(item) {
let selected_purchase = this.$store.state.cashier.selected_purchase;
let found = selected_purchase.find((el) => el.PurchaseRequestDirectID === item.PurchaseRequestDirectID);
if (found) {
let index = selected_purchase.indexOf(found);
selected_purchase.splice(index, 1);
}
let totalRealitation = 0;
for (let i = 0; i < selected_purchase.length; i++) {
const e = selected_purchase[i];
totalRealitation += parseFloat(e.PurchaseRequestDirectTotalRealitation);
}
let xresume = {
"totalRealitation": totalRealitation,
};
this.$store.commit("cashier/update_resume_total", xresume);
},
checkErrorForm(val) {
let errors = this.$store.state.cashier.errors;
if (errors.includes(val)) {
return true;
} else {
return false;
}
},
closeDiallogCashier() {
this.dialogVoucher = false;
this.xnote = ""
this.url = ""
this.filesToUpload = []
this.imageName = ''
this.imageFile = ''
this.imageUrl = ''
this.restPrice = 0
this.$store.commit("cashier/update_total_akhir", 0);
this.$store.commit("cashier/update_errors", []);
},
saveVoucher() {
this.$store.commit("cashier/update_errors", []);
var errors = this.$store.state.cashier.errors;
if (_.isEmpty(this.selectedBranch)) {
errors.push("requireBranch");
}
if (_.isEmpty(this.selectedAccountDana)) {
errors.push("requireAccountDana");
}
if (_.isEmpty(this.selectedAccountBiaya)) {
errors.push("requireAccountBiaya");
}
if (_.isEmpty(this.selectedAccountTemp)) {
errors.push("requireAccountTemp");
}
if (errors.length === 0) {
let prm = {
"branch": this.selectedBranch.M_BranchCode,
"accountDana": this.selectedAccountDana.coaID,
"accountBiaya": this.selectedAccountBiaya.coaID,
"accountTemp": this.selectedAccountTemp.coaID,
"total": this.$store.state.cashier.resume_total.totalRealitation,
"details": this.$store.state.cashier.selected_purchase,
};
// this.$store.dispatch("cashier/save", prm);
}
},
resetAllInput() {
this.xnote = ""
this.restPrice = 0
this.$store.commit("cashier/update_total_akhir", 0);
this.$store.commit("cashier/update_imageRelationPreviews", []);
this.$store.commit("cashier/update_imageRelationFiles", []);
},
updateChasier() {
this.$store.commit("cashier/update_errors", []);
var errors = this.$store.state.cashier.errors;
if (_.isEmpty(this.xnote)) {
errors.push("requireNote");
}
if (errors.length === 0) {
var formData = new FormData()
for( var i = 0; i < this.imageRelationFiles.length; i++ ){
let file = this.imageRelationFiles[i]
formData.append('files[' + i + ']', file)
}
formData.append("token", one_token())
formData.append("note", this.xnote)
formData.append("restPrice", this.restPrice)
formData.append("ID", this.$store.state.cashier.selected_cashier.PaymentVoucherID)
this.$store.dispatch("cashier/update", formData);
}
},
calculateTotalPrice() {
var totalHarga = Object.keys(this.$store.state.cashier.selected_cashier).length > 0 ? this.$store.state.cashier.selected_cashier.PaymentVoucherTotal : 0;
if (this.restPrice > 0) {
let total = totalHarga - this.restPrice;
this.$store.commit("cashier/update_total_akhir", total);
}
},
openRealisedItem() {
this.$store.dispatch("cashier/getVoucherDetail")
this.$store.commit("cashier/update_dialog_realise_item", true)
}
},
watch: {
search_branch(val, old) {
if (val == old) return;
if (!val) return;
if (val.length < 1) return;
if (this.$store.state.cashier.load_status_branch == 1) return;
this.thr_search_branch();
},
search_accountDana(val, old) {
if (val == old) return;
if (!val) return;
if (val.length < 1) return;
if (this.$store.state.cashier.load_status_accDana == 1) return;
this.thr_search_accountDana();
},
search_accountBiaya(val, old) {
if (val == old) return;
if (!val) return;
if (val.length < 1) return;
if (this.$store.state.cashier.load_status_accBiaya == 1) return;
this.thr_search_accountBiaya();
},
search_accountTemp(val, old) {
if (val == old) return;
if (!val) return;
if (val.length < 1) return;
if (this.$store.state.cashier.load_status_accTemp == 1) return;
this.thr_search_accountTemp();
},
restPrice(val, old) {
if (val < 0) {
this.$store.commit("cashier/update_restPrice",0);
}
this.calculateTotalPrice();
}
},
}
</script>

View File

@@ -0,0 +1,649 @@
<template>
<v-layout row justify-center>
<v-dialog v-model="dialogVoucherPay" persistent max-width="50vw">
<v-card>
<v-card-title class="headline grey lighten-2" primary-title>
FORM PEMBAYARAN
</v-card-title>
<v-card-text class="pt-2 pb-0">
<v-layout pt-2>
<v-flex xs12 pa-2>
<span class="font-weight-bold">NOMOR REQUEST:</span>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs12 pa-2>
<v-chip label
v-for="(item, index) in numberRequest"
:key="index"
class="ma-1"
>
{{ item }}
</v-chip label>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs12 pa-2>
<v-textarea
filled
outline
hide-details
label="Catatan*"
rows="3"
v-model="xnotepay"
></v-textarea>
<p v-if="checkErrorForm('requireNote')" class="error pl-2 pr-2" style="color:#fff">Catatan harus diisi</p>
</v-flex>
</v-layout>
<v-layout>
<v-flex xs12 pa-2>
<v-textarea
filled
outline
hide-details
label="Deskripsi Request"
rows="3"
readonly
v-model="requestDescription"
></v-textarea>
</v-flex>
</v-layout>
<v-layout>
<v-flex xs12 pa-2>
<v-text-field
v-model="this.$store.state.cashier.selected_cashier.user_request"
readonly
hide-details
outline
label="Nama Request">
</v-text-field>
</v-flex>
</v-layout>
<v-layout>
<v-flex xs12 pa-2>
<v-autocomplete
v-model="selected_userReceive"
menu-icon="mdi-chevron-down"
:items="userReceive"
item-text="M_UserUsername"
item-value="M_UserID"
label="Penerima Uang*"
outline
hide-details
></v-autocomplete>
<p v-if="checkErrorForm('requireUserReceive')" class="error pl-2 pr-2" style="color:#fff">Penerima uang belum di pilih</p>
</v-flex>
</v-layout>
<v-layout>
<v-flex xs12 pa-2>
<v-text-field
prefix="Rp"
v-model="formatted_total_price"
readonly
hide-details
outline
label="Total Bayar">
</v-text-field>
</v-flex>
</v-layout>
<v-layout mr-2 ml-2 style="border:1px solid black" align-center row pa-2 mb-2>
<v-flex xs9>
<!-- <input type="file" ref="image" accept="image/*" @change="onFilePicked"> -->
<input type="file" id="files" ref="files" accept="image/*" multiple v-on:change="onFilePicked()"/>
</v-flex>
</v-layout>
<v-layout v-if="show_progrees_upload" row align-center mr-2 ml-2>
<v-flex xs12>
<v-progress-linear :indeterminate="true"></v-progress-linear>
</v-flex>
</v-layout>
<v-layout v-if="imagePayPreviews.length > 0 && !show_progrees_upload" align-center row wrap>
<v-flex
v-for="(imgUrl, index) in imagePayPreviews"
:key="index"
xs6
class="pa-2">
<v-img :src="imgUrl">
<div class="fill-height bottom-gradient"></div>
</v-img>
</v-flex>
</v-layout>
<v-divider></v-divider>
<v-layout v-if="imagePreviews.length > 0" pt-2>
<v-flex xs12 pa-2>
<span class="font-weight-bold">BUKTI PEMBAYARAN :</span>
</v-flex>
</v-layout>
<v-layout v-if="imagePreviews.length > 0" align-center row wrap>
<v-flex
v-for="(img, index) in imagePreviews"
:key="index"
xs6
class="pa-2"
>
<v-img :src="img">
<div class="fill-height bottom-gradient"></div>
</v-img>
</v-flex>
</v-layout>
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="error" flat @click="closeDiallogCashier()"> Tutup </v-btn>
<v-btn v-if="xact === 'new'" color="primary" dark @click="saveVoucher()">Simpan</v-btn>
<v-btn v-if="xact === 'edit'" color="primary" dark @click="updatePay()">Bayar & Simpan</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-layout>
</template>
<script>
module.exports = {
name: "DialogFormVoucher",
data() {
return {
url: "",
filesToUpload: [],
fileName: "", // Untuk menyimpan nama file
imageName: "",
imageFile: "",
imageUrl: "",
headers: [
{
text: "NO",
align: "left",
sortable: false,
value: "no",
width: "15%",
class: "blue lighten-3 white--text",
},
{
text: "DESKRIPSI",
align: "left",
sortable: false,
value: "date",
width: "40%",
class: "blue lighten-3 white--text",
},
{
text: "TOTAL REALISASI",
align: "left",
sortable: false,
value: "supplier",
width: "30%",
class: "blue lighten-3 white--text",
},
{
text: "AKSI",
align: "left",
sortable: false,
value: "status",
width: "15%",
class: "blue lighten-3 white--text",
},
],
};
},
mounted() {
},
computed: {
formatted_total_price() {
var val = Object.keys(this.$store.state.cashier.selected_cashier).length > 0 ? this.$store.state.cashier.selected_cashier.PaymentVoucherTotal : 0;
return this.oneMoney(val);
},
dialogVoucherPay: {
get() {
return this.$store.state.cashier.dialog_cashier_pay;
},
set(val) {
this.$store.commit("cashier/update_dialog_cashier_pay", val);
},
},
branchList() {
return this.$store.state.cashier.branchList;
},
selectedBranch: {
get() {
return this.$store.state.cashier.selected_branch;
},
set(val) {
this.$store.commit("cashier/update_selected_branch", val);
this.getPurchaseReq();
},
},
search_branch: {
get() {
return this.$store.state.cashier.search_branch;
},
set(val) {
this.$store.commit("cashier/update_search_branch", val);
},
},
accountDanaList() {
return this.$store.state.cashier.accountDanaList;
},
selectedAccountDana: {
get() {
return this.$store.state.cashier.selected_accountDana;
},
set(val) {
this.$store.commit("cashier/update_selected_accountDana", val);
},
},
search_accountDana: {
get() {
return this.$store.state.cashier.search_accountDana;
},
set(val) {
this.$store.commit("cashier/update_search_accountDana", val);
},
},
accountBiayaList() {
return this.$store.state.cashier.accountBiayaList;
},
selectedAccountBiaya: {
get() {
return this.$store.state.cashier.selected_accountBiaya;
},
set(val) {
this.$store.commit("cashier/update_selected_accountBiaya", val);
},
},
search_accountBiaya: {
get() {
return this.$store.state.cashier.search_accountBiaya;
},
set(val) {
this.$store.commit("cashier/update_search_accountBiaya", val);
},
},
accountTempList() {
return this.$store.state.cashier.accountTempList;
},
selectedAccountTemp: {
get() {
return this.$store.state.cashier.selected_accountTemp;
},
set(val) {
this.$store.commit("cashier/update_selected_accountTemp", val);
},
},
search_accountTemp: {
get() {
return this.$store.state.cashier.search_accountTemp;
},
set(val) {
this.$store.commit("cashier/update_search_accountTemp", val);
},
},
purchaseList() {
return this.$store.state.cashier.purchaseList;
},
selected_purchase: {
get() {
return this.$store.state.cashier.selected_purchase;
},
set(val) {
this.$store.commit("cashier/update_selected_purchase", val);
},
},
resume() {
return this.$store.state.cashier.resume_total;
},
xact: {
get() {
return this.$store.state.cashier.act;
},
set(val) {
this.$store.commit("cashier/update_act", val);
},
},
show_progrees_upload: {
get() {
return this.$store.state.cashier.show_progrees_upload
},
set(val) {
this.$store.commit("cashier/update_show_progrees_upload", val)
}
},
xnotepay: {
get() {
return this.$store.state.cashier.notepay
},
set(val) {
this.$store.commit("cashier/update_notepay", val)
}
},
imagePreviews: {
get() {
return this.$store.state.cashier.imagePreviews
},
set(val) {
this.$store.commit("cashier/update_imagePreviews", val)
}
},
numberRequest: {
get() {
return this.$store.state.cashier.numberRequest;
},
set(val) {
this.$store.commit("cashier/update_numberRequest", val);
},
},
requestDescription: {
get() {
return this.$store.state.cashier.requestDescription;
},
set(val) {
this.$store.commit("cashier/update_requestDescription", val);
},
},
imagePayPreviews: {
get() {
return this.$store.state.cashier.imagePayPreviews;
},
set(val) {
this.$store.commit("cashier/update_imagePayPreviews", val);
},
},
imagePayFiles: {
get() {
return this.$store.state.cashier.imagePayFiles;
},
set(val) {
this.$store.commit("cashier/update_imagePayFiles", val);
},
},
selected_userReceive: {
get() {
return this.$store.state.cashier.selected_userReceive;
},
set(val) {
this.$store.commit("cashier/update_selected_userReceive", val);
},
},
userReceive() {
return this.$store.state.cashier.userReceive;
},
},
methods: {
roundToThreeSignificantDigits(num) {
if (num === 0) return 0;
// Hitung jumlah digit
const absNum = Math.abs(num);
const magnitude = Math.floor(Math.log10(absNum)) + 1;
// Jika kurang dari 3 digit, tidak perlu dibulatkan
if (magnitude <= 3) return num;
// Hitung faktor pembulatan
const factor = Math.pow(10, magnitude - 3);
// Bulatkan
return Math.round(num / factor) * factor;
},
oneMoney(value){
//return one_money(value);
let splitValue = value.toString().split(".");
if(splitValue.length > 1) {
let val = splitValue[0]
return val.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".") + "," + this.roundToThreeSignificantDigits(splitValue[1]);
} else {
return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".");
}
},
handleFileUploadsbkp(){
// this.files = this.$refs.files.files
const files = this.$refs.files.files;
this.urls = [];
this.filesToUpload = [];
for (let i = 0; i < files.length; i++) {
const file = files[i];
const url = URL.createObjectURL(file);
this.urls.push(url);
this.filesToUpload.push(file);
}
// console.log('urls', this.urls)
console.log('filesToUpload', this.filesToUpload)
},
handleFileUploads(){
const file = this.$refs.files.files[0];
if (file) {
this.fileName = file.name; // Simpan nama file
this.filesToUpload = [file]; // Masukkan ke array untuk konsistensi
this.url = URL.createObjectURL(file); // Preview jika diperlukan
}
},
onFilePicked(){
// this.files = this.$refs.files.files
const files = this.$refs.files.files;
this.imagePayPreviews = [];
this.imagePayFiles = [];
for (let i = 0; i < files.length; i++) {
const file = files[i];
const url = URL.createObjectURL(file);
this.imagePayPreviews.push(url);
this.imagePayFiles.push(file);
}
},
onFilePickedold(e) {
const files = e.target.files
console.log('cek files',files[0]);
if (files[0] !== undefined) {
this.imageName = files[0].name
if (this.imageName.lastIndexOf('.') <= 0) {
return
}
const fr = new FileReader()
fr.readAsDataURL(files[0])
fr.addEventListener('load', () => {
this.imageUrl = fr.result
this.imageFile = files[0] // this is an image file that can be sent to server...
})
// console.log('imageName', this.imageName)
// console.log('imageFile', this.imageFile)
// console.log('imageUrl', this.imageUrl)
} else {
this.imageName = ''
this.imageFile = ''
this.imageUrl = ''
}
},
thr_search_branch: _.debounce(function() {
this.$store.dispatch("cashier/searchBranch", this.search_branch);
}, 500),
thr_search_accountDana: _.debounce(function() {
this.$store.dispatch("cashier/searchAccDana", this.search_accountDana);
}, 500),
thr_search_accountBiaya: _.debounce(function() {
this.$store.dispatch("cashier/searchAccBiaya", this.search_accountBiaya);
}, 500),
thr_search_accountTemp: _.debounce(function() {
this.$store.dispatch("cashier/searchAccTemp", this.search_accountTemp);
}, 500),
getPurchaseReq() {
this.$store.dispatch("cashier/getPurchase", this.selectedBranch === undefined ? "" : this.selectedBranch.M_BranchCode);
},
formatCurrency(val) {
// Format the price above to USD using the locale, style, and currency.
let price = parseFloat(val);
let USDollar = new Intl.NumberFormat("id-ID", {
style: "currency",
currency: "IDR",
});
// console.log(
// `The formated version of ${price} is ${USDollar.format(price)}`
// );
return `${USDollar.format(price)}`;
},
addPurchase(item) {
let selected_purchase = this.$store.state.cashier.selected_purchase;
selected_purchase.push(item);
let totalRealitation = 0;
for (let i = 0; i < selected_purchase.length; i++) {
const e = selected_purchase[i];
totalRealitation += parseFloat(e.PurchaseRequestDirectTotalRealitation);
}
let xresume = {
"totalRealitation": totalRealitation,
};
this.$store.commit("cashier/update_resume_total", xresume);
},
purchaseExist(item) {
let selected_purchase = this.$store.state.cashier.selected_purchase;
let found = selected_purchase.find((el) => el.PurchaseRequestDirectID === item.PurchaseRequestDirectID);
if (found) {
return false;
}
return true;
},
removePurchase(item) {
let selected_purchase = this.$store.state.cashier.selected_purchase;
let found = selected_purchase.find((el) => el.PurchaseRequestDirectID === item.PurchaseRequestDirectID);
if (found) {
let index = selected_purchase.indexOf(found);
selected_purchase.splice(index, 1);
}
let totalRealitation = 0;
for (let i = 0; i < selected_purchase.length; i++) {
const e = selected_purchase[i];
totalRealitation += parseFloat(e.PurchaseRequestDirectTotalRealitation);
}
let xresume = {
"totalRealitation": totalRealitation,
};
this.$store.commit("cashier/update_resume_total", xresume);
},
checkErrorForm(val) {
let errors = this.$store.state.cashier.errors;
if (errors.includes(val)) {
return true;
} else {
return false;
}
},
closeDiallogCashier() {
this.dialogVoucherPay = false;
this.xnotepay = ""
this.url = ""
this.filesToUpload = []
this.imageName = ''
this.imageFile = ''
this.imageUrl = ''
this.$store.commit("cashier/update_errors", []);
this.$store.commit("cashier/update_selected_userReceive",);
},
saveVoucher() {
this.$store.commit("cashier/update_errors", []);
var errors = this.$store.state.cashier.errors;
if (_.isEmpty(this.selectedBranch)) {
errors.push("requireBranch");
}
if (_.isEmpty(this.selectedAccountDana)) {
errors.push("requireAccountDana");
}
if (_.isEmpty(this.selectedAccountBiaya)) {
errors.push("requireAccountBiaya");
}
if (_.isEmpty(this.selectedAccountTemp)) {
errors.push("requireAccountTemp");
}
if (errors.length === 0) {
let prm = {
"branch": this.selectedBranch.M_BranchCode,
"accountDana": this.selectedAccountDana.coaID,
"accountBiaya": this.selectedAccountBiaya.coaID,
"accountTemp": this.selectedAccountTemp.coaID,
"total": this.$store.state.cashier.resume_total.totalRealitation,
"details": this.$store.state.cashier.selected_purchase,
};
// this.$store.dispatch("cashier/save", prm);
}
},
resetAllInput() {
this.xnotepay = ""
this.imageName = ''
this.imageFile = ''
this.imageUrl = ''
},
updatePay() {
this.$store.commit("cashier/update_errors", []);
var errors = this.$store.state.cashier.errors;
if (_.isEmpty(this.xnotepay)) {
errors.push("requireNote");
}
if (_.isEmpty(this.selected_userReceive)) {
errors.push("requireUserReceive");
}
if (errors.length === 0) {
var formData = new FormData()
console.log("formData",this.imagePayFiles.length)
for( var i = 0; i < this.imagePayFiles.length; i++ ){
let file = this.imagePayFiles[i]
formData.append('files[' + i + ']', file)
console.log("formData",formData)
}
formData.append("token", one_token())
formData.append("note", this.xnotepay)
formData.append("ID", this.$store.state.cashier.selected_cashier.PaymentVoucherID)
formData.append("userReceiveID", this.$store.state.cashier.selected_userReceive)
// let prm = {
// "img": this.imageUrl + '/' + this.imageName + '/' + this.imageFile,
// "note": this.xnotepay,
// "ID": this.$store.state.cashier.selected_cashier.PaymentVoucherID
// }
this.$store.dispatch("cashier/updatepaid", formData);
}
},
},
watch: {
search_branch(val, old) {
if (val == old) return;
if (!val) return;
if (val.length < 1) return;
if (this.$store.state.cashier.load_status_branch == 1) return;
this.thr_search_branch();
},
search_accountDana(val, old) {
if (val == old) return;
if (!val) return;
if (val.length < 1) return;
if (this.$store.state.cashier.load_status_accDana == 1) return;
this.thr_search_accountDana();
},
search_accountBiaya(val, old) {
if (val == old) return;
if (!val) return;
if (val.length < 1) return;
if (this.$store.state.cashier.load_status_accBiaya == 1) return;
this.thr_search_accountBiaya();
},
search_accountTemp(val, old) {
if (val == old) return;
if (!val) return;
if (val.length < 1) return;
if (this.$store.state.cashier.load_status_accTemp == 1) return;
this.thr_search_accountTemp();
},
},
}
</script>

View File

@@ -0,0 +1,392 @@
<template>
<v-dialog v-model="dialog_form_realise" persistent width="50vw">
<v-card>
<v-card-title class="headline grey lighten-2" primary-title>
FORM REALISASI
</v-card-title>
<v-card-text>
<v-layout row wrap>
<v-flex xs12 class="mb-2">
<v-textarea
filled outline hide-details label="Catatan*"
rows="3" v-model="xnote"
></v-textarea>
<p v-show="checkErrorForm('requireNote')" class="error">Catatan harus diisi</p>
</v-flex>
<v-flex xs3 class="pr-1">
<v-text-field
prefix="Rp." v-model="formated_total_price" outline
label="Total Bayar" hide-details readonly
></v-text-field>
</v-flex>
<v-flex xs3 class="px-1">
<v-text-field
prefix="Rp." v-model="formatted_adj_price" outline
readonly hide-details label="Tambahan"
></v-text-field>
</v-flex>
<v-flex xs3 class="px-1">
<v-text-field
prefix="Rp." v-model="formated_rest_price" outline
readonly hide-details label="Harga"
></v-text-field>
</v-flex>
<v-flex xs3 class="pl-1">
<v-text-field
prefix="Rp." v-model="formated_sisa_price" outline
readonly hide-details label="Sisa"
></v-text-field>
</v-flex>
</v-layout>
<v-expansion-panel class="mt-4">
<v-expansion-panel-content v-for="(item, index) in listing_item_realise" :key="index">
<template v-slot:header>
<div>{{ item.PurchaseRequestDirectDescription }}</div>
</template>
<v-card>
<v-card-text>
<v-layout row wrap>
<v-flex xs3 class="pr-1">
<p class="mb-0">{{ item.PurchaseRequestDirectNumber }}</p>
</v-flex>
<v-flex xs3 class="px-1">
<p class="mb-0">{{ item.PurchaseRequestDirectDescription }}</p>
<p class="mb-0 font-weight-bold" style="color:#000000">
Kategori: {{ item.PurchaseDirectCategoryName }}
</p>
</v-flex>
<v-flex xs3>
<p class="mb-0">Harga Estimasi: </p>
<p class="mb-0">Rp. {{ oneMoney(item.estimate_price) }}</p>
</v-flex>
<v-flex xs3 class="pl-1">
<v-text-field
prefix="Rp" v-model="item.realised_price"
outline hide-details label="Harga Realisasi"
@input="processMoney()"
></v-text-field>
</v-flex>
<v-flex xs12 style="border:1px solid black" class="pa-2 mt-2">
<input
type="file" id="files" ref="files"
accept="image/*" multiple
v-on:change="onFilePicked(item, $event)"
/>
</v-flex>
<v-flex
v-for="(nota) in item.prevNota"
xs4 class="pa-2" :key="nota.nota_id"
>
<div class="image-container">
<v-img
:src="makeImgUrl(nota)" aspect-ratio="1" contain
class="grey lighten-2" @click="viewImage(makeImgUrl(nota))"
></v-img>
</div>
</v-flex>
<v-flex
v-for="(url, index) in item.attachPreview"
xs4 class="pa-2" :key="index"
>
<div class="image-container">
<v-img
:src="url" aspect-ratio="1" contain
class="grey lighten-2" @click="viewImage(url)"
></v-img>
<v-icon
color="red"
class="close-button"
@click="removeImage(index, item)"
>
close
</v-icon>
</div>
</v-flex>
</v-layout>
</v-card-text>
</v-card>
</v-expansion-panel-content>
</v-expansion-panel>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn
color="error" flat outline
@click="closeFormRealise()"
>Tutup</v-btn>
<v-btn
color="primary" dark
@click="realiseForm()"
>Simpan & Realisasi</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<style>
.close-button {
position: absolute;
top: 5px;
right: 5px;
z-index: 1;
cursor: pointer;
}
.image-container {
position: relative;
padding-bottom: 35px;
}
</style>
<script>
module.exports = {
data() {
return {
store_temp_attach: {},
penyesuaian: 0
}
},
computed: {
dialog_form_realise: {
get() {
return this.$store.state.cashier.dialog_cashier;
},
set(val) {
this.$store.commit("cashier/update_dialog_cashier", val);
}
},
xnote: {
get() {
return this.$store.state.cashier.note
},
set(val) {
this.$store.commit("cashier/update_note", val)
}
},
formated_total_price() {
const price = this.$store.state.cashier.selected_cashier
if (price.PaymentVoucherTotal) {
return this.oneMoney(price.PaymentVoucherTotal)
}
return this.oneMoney(0)
},
formated_rest_price() {
let rest = this.$store.state.cashier.restPrice || 0
return this.oneMoney(rest)
},
formated_sisa_price() {
let sisa = this.$store.state.cashier.total_akhir || 0
return this.oneMoney(sisa)
},
formatted_adj_price() {
return this.oneMoney(this.calcAdjustmentMoney());
},
selected_cashier() {
return this.$store.state.cashier.selected_cashier;
},
listing_item_realise: {
get() {
return this.$store.state.cashier.listing_item_realise
},
set(val) {
this.$store.commit("cashier/update_listing_item_realise", val);
}
},
detail_voucher() {
return this.$store.state.cashier.details;
},
dialog_error: {
get() {
return this.$store.state.cashier.alert_error;
},
set(val) {
this.$store.commit("cashier/update_alert_error", val);
},
},
msgError: {
get() {
return this.$store.state.cashier.error_message;
},
set(val) {
this.$store.commit("cashier/update_error_message", val);
}
},
},
methods: {
roundToThreeSignificantDigits(digit) {
const num = parseInt(digit, 10)
if (isNaN(num) || num <= 0) {
return '00';
}
const scale = 10 ** digit.length;
const decimal = num / scale
return Math.round(decimal * 100);
},
oneMoney(value) {
let splitValue = value.toString().split(".");
if(splitValue.length > 1) {
let val = splitValue[0]
return val.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".") + "," + this.roundToThreeSignificantDigits(splitValue[1]);
} else {
return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".");
}
},
processMoney() {
let data = JSON.parse(JSON.stringify(this.listing_item_realise))
let realised = 0
data.forEach(element => {
if (!element.realised_price) {
element.realised_price = 0
}
realised = realised + Number(element.realised_price)
element.realised_price = Number(element.realised_price)
});
this.listing_item_realise = data
let adjusment = this.calcAdjustmentMoney();
let total = Number(this.selected_cashier.PaymentVoucherTotal) + adjusment
let sisa = total - realised
this.$store.commit("cashier/update_restPrice", realised)
this.$store.commit("cashier/update_total_akhir", sisa)
},
checkErrorForm(val) {
let errors = this.$store.state.cashier.errors;
if (errors.includes(val)) {
return true
} else {
return false
}
},
onFilePicked(item, event) {
const files = event.target.files;
if (files.length == 0) {
return
}
if (!this.store_temp_attach[item.detail_id]) {
this.$set(this.store_temp_attach, item.detail_id, {
files: []
})
}
for (let index = 0; index < files.length; index++) {
const file = files[index];
const url = URL.createObjectURL(file);
this.store_temp_attach[item.detail_id].files.push(file);
item.attachFiles.push(file);
item.attachPreview.push(url);
}
event.target.value = null;
},
removeImage(index, item) {
URL.revokeObjectURL(item.attachPreview[index])
item.attachPreview.splice(index, 1)
item.attachFiles.splice(index, 1)
// remove that in local
const filestore = this.store_temp_attach[item.detail_id];
if (filestore && filestore.files.length > index) {
filestore.files.splice(index, 1);
}
},
viewImage(url) {
this.$store.commit("cashier/update_selected_img_view", url)
this.$store.commit("cashier/update_dialog_view_img", true)
},
makeImgUrl(nota) {
const imgbase_url = BASE_URL + "/one-media/cashier/";
return imgbase_url + nota.img_url
},
calcAdjustmentMoney() {
const detail = this.detail_voucher
const adj_val = detail.reduce((sum, item) => sum + Number(item.PurchaseRequestDirectAdjustment), 0)
return adj_val;
},
closeFormRealise() {
this.store_temp_attach = {}
this.listing_item_realise = []
this.$store.commit("cashier/update_selected_cashier", {})
this.dialog_form_realise = false
},
realiseForm() {
let detail = this.detail_voucher
const nota_pending = detail.filter(element => element.PurchaseRequestDirectNotaStatus == 'Pending');
if (nota_pending.length > 0) {
const req_number = nota_pending.map(item => item.PurchaseRequestDirectNumber).join(',');
this.dialog_error = true;
this.msgError = 'Terdapat nota yang belum di-approve pada ' + req_number;
return;
}
const voucher = this.selected_cashier
if (voucher.PaymentVoucherRealitationApproved == 'N') {
this.dialog_error = true;
this.msgError = 'Voucher ini belum di approve realisasi oleh kacab';
return;
}
this.$store.commit("cashier/update_errors", []);
var errors = this.$store.state.cashier.errors;
if (_.isEmpty(this.xnote)) {
errors.push('requireNote')
}
if (errors.length === 0) {
var formData = new FormData()
const dataSerialize = JSON.parse(JSON.stringify(this.listing_item_realise));
let allFiles = [];
let notanotfound = [];
dataSerialize.forEach(item => {
const detail_id = item.detail_id;
const file = this.store_temp_attach[detail_id] ? this.store_temp_attach[detail_id].files : []
item.fileCount = file.length;
allFiles = allFiles.concat(file);
if (item.attachFiles.length < 1) {
if (item.prevNota.length < 1) {
notanotfound.push(item.PurchaseRequestDirectDescription);
}
}
delete item.attachFiles;
delete item.attachPreview;
});
if (notanotfound.length > 0) {
const nonota = notanotfound.join(", ");
this.dialog_error = true;
this.msgError = 'Belum ada nota realisasi pada barang berikut: ' + nonota;
return;
}
formData.append("data", JSON.stringify(dataSerialize));
allFiles.forEach(file => {
formData.append("files[]", file);
});
formData.append("token", one_token())
formData.append("note", this.xnote)
formData.append("restPrice", this.$store.state.cashier.restPrice)
formData.append("ID", this.$store.state.cashier.selected_cashier.PaymentVoucherID)
this.$store.dispatch("cashier/update", formData);
}
},
},
watch: {
},
}
</script>

View File

@@ -0,0 +1,136 @@
<template>
<v-dialog v-model="dialog_realise_item" persistent width="40vw">
<v-card>
<v-card-title class="headline grey lighten-2">ITEM REALISE</v-card-title>
<v-card-text>
<v-layout row wrap v-for="(item, index) in listing_item_realise" class="mt-2">
<v-flex xs3 class="pr-1">
<p class="mb-0">{{ item.PurchaseRequestDirectNumber }}</p>
</v-flex>
<v-flex xs3 class="px-1">
<p class="mb-0">{{ item.PurchaseRequestDirectDescription }}</p>
<p class="mb-0 font-weight-bold" style="color:#000000">Kategori: {{ item.PurchaseDirectCategoryName }}</p>
</v-flex>
<v-flex xs3>
<p class="mb-0">Harga Estimasi: </p>
<p class="mb-0">Rp. {{ oneMoney(item.estimate_price) }}</p>
</v-flex>
<v-flex xs3 class="pl-1">
<v-text-field
prefix="Rp" v-model="item.realised_price"
outline hide-details label="Harga Realisasi"
@input="formatMoney()"
>
</v-text-field>
</v-flex>
<v-flex xs12>
<v-divider class="mt-2" v-if="index + 1 < listing_item_realise.length" :key="`divider-${index}`"></v-divider>
</v-flex>
</v-layout>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="error" @click="batalAccItem()">BATAL</v-btn>
<v-btn color="primary" @click="simpanAccItem()">SIMPAN</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script>
module.exports = {
data() {
return {
}
},
computed: {
dialog_realise_item: {
get() {
return this.$store.state.cashier.dialog_realise_item
},
set(val) {
this.$store.commit("cashier/update_dialog_realise_item", val);
}
},
listing_item_realise: {
get() {
return this.$store.state.cashier.listing_item_realise
},
set(val) {
this.$store.commit("cashier/update_listing_item_realise", val);
}
}
},
methods: {
oneMoney(value) {
// First, remove any non-digit characters (like existing dots or commas)
// to get a clean number.
let cleanValue = String(value).replace(/\D/g, '');
// Convert the clean value to a number.
const num = parseInt(cleanValue, 10);
// If the result is not a number, return an empty string or '0'.
if (isNaN(num)) {
return '';
}
// Use toLocaleString() to format the number with dots as thousand separators.
// The 'id-ID' locale is used here for Indonesian Rupiah formatting.
return num.toLocaleString('id-ID');
},
oneMoneyToInt(formattedValue) {
if (formattedValue === null || formattedValue === undefined || formattedValue === '') {
return 0; // Return 0 for empty or null values
}
// Remove all dots (thousand separators) from the string.
// The global flag 'g' is important to replace all occurrences.
const cleanString = String(formattedValue).replace(/\./g, '');
// Convert the clean string to an integer.
// The second argument '10' is the radix, ensuring it's parsed as base-10.
const intValue = parseInt(cleanString, 10);
// Check if the result is a valid number.
if (isNaN(intValue)) {
return 0; // Return 0 if the conversion fails
}
return intValue;
},
batalAccItem() {
this.listing_item_realise = []
this.dialog_realise_item = false
},
simpanAccItem() {
let data = JSON.parse(JSON.stringify(this.listing_item_realise))
let isEmpty = false
data.forEach(element => {
if (element.realised_price == '' ) {
isEmpty = true
} else {
element.realised_price = this.oneMoneyToInt(element.realised_price)
}
});
if (isEmpty) {
return
}
this.$store.dispatch("cashier/saveVoucherDetail", {detail: data});
},
formatMoney() {
let data = this.listing_item_realise
data.forEach(element => {
element.realised_price = this.oneMoney(element.realised_price)
});
this.listing_item_realise = data
}
},
watch: {
}
}
</script>

View File

@@ -0,0 +1,62 @@
<template>
<v-dialog v-model="dialog_view_img" persistent width="50vw">
<v-card>
<v-card-title>
<v-spacer></v-spacer>
<v-btn color="red" fab outline @click="dialog_view_img = false">
<v-icon color="red">close</v-icon>
</v-btn>
</v-card-title>
<v-card-text class="dialog-content-scroll">
<div class="pa-2">
<v-img
:src="selected_img_view" contain
class="grey lighten-2"
></v-img>
</div>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn class="mr-2" color="red" flat outline @click="dialog_view_img = false">
Tutup
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<style>
.dialog-content-scroll {
max-height: 70vh;
overflow-y: auto;
}
</style>
<script>
module.exports = {
data() {
return {
}
},
computed: {
dialog_view_img: {
get() {
return this.$store.state.cashier.dialog_view_img
},
set(val) {
this.$store.commit("cashier/update_dialog_view_img", val)
}
},
selected_img_view() {
return this.$store.state.cashier.selected_img_view
}
},
methods: {
closeViewImg() {
this.$store.commit("cashier/update_selected_img_view", '')
this.dialog_view_img = false;
}
},
}
</script>

View File

@@ -0,0 +1,208 @@
<template>
<div style="width: 100%;">
<v-layout row wrap>
<v-flex xs12 fill-height pa-1>
<v-card>
<v-card-text>
<v-layout row wrap>
<v-flex xs12>
<v-layout row wrap>
<v-flex xs11>
<v-layout row wrap>
<v-flex xs12>
<div>
<span>No : </span>
<span>{{
selected_cashier.PaymentVoucherNumber
}}</span>
</div>
</v-flex>
<v-flex xs12>
<div>
<span>Sumber Dana : </span>
<span>{{
selected_cashier.CoaSource
}}</span>
</div>
</v-flex>
<!-- <v-flex xs12>
<div>
<span>Biaya : </span>
<span>{{
selected_cashier.CoaExpense
}}</span>
</div>
</v-flex> -->
<v-flex xs12>
<div>
<span>Tampungan Sementara : </span>
<span>{{
selected_cashier.CoaTemporary
}}</span>
</div>
</v-flex>
</v-layout>
</v-flex>
<!-- <v-flex xs1>
<v-btn
color="primary"
flat
icon
@click="openDialogDetail()"
>
<v-icon>add_box</v-icon>
</v-btn>
</v-flex> -->
</v-layout>
</v-flex>
<v-flex xs12 pt-2 pb-2>
<v-layout row wrap>
<v-flex xs12>
<v-data-table
:headers="headers"
:items="xdetails"
:loading="isLoading"
hide-actions
class="elevation-1"
>
<template slot="items" slot-scope="props">
<td class="text-xs-center pa-2">
{{ props.index + 1 }}
</td>
<td class="text-xs-left pa-2">
{{ props.item.M_UserUsername }}
</td>
<td class="text-xs-left pa-2">
{{ props.item.PurchaseRequestDirectNumber }}
</td>
<td class="text-xs-left pa-2">
Rp
{{
convertMoney(props.item.PaymentVoucherDetailTotal)
}}
</td>
<td class="text-xs-left pa-2">
<p v-for="value in splitArray(props.item.account_biaya)" class="mb-0">
{{ value == 'notset'? '-' : value }}
</p>
</td>
</template>
</v-data-table>
</v-flex>
</v-layout>
</v-flex>
</v-layout>
</v-card-text>
</v-card>
</v-flex>
</v-layout>
</div>
</template>
<style scoped>
.date-type-table {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.table.v-table tbody td,
table.v-table tbody th {
height: 40px;
}
.table.v-table thead tr {
height: 40px;
}
.scroll-container {
scroll-padding: 50px 0 0 50px;
}
</style>
<script>
module.exports = {
components: {
},
data() {
return {
headers: [
{
text: "NO",
align: "left",
sortable: false,
value: "no",
width: "10%",
class: "blue lighten-3 white--text",
},
{
text: "USER REQUEST",
align: "left",
sortable: false,
value: "no",
width: "15%",
class: "blue lighten-3 white--text",
},
{
text: "NO REQUEST",
align: "left",
sortable: false,
value: "request",
width: "30%",
class: "blue lighten-3 white--text",
},
{
text: "TOTAL",
align: "left",
sortable: false,
value: "total",
width: "20%",
class: "blue lighten-3 white--text",
},
{
text: "ACCOUNT BIAYA",
align: "left",
sortable: false,
value: "total",
width: "25%",
class: "blue lighten-3 white--text",
},
],
}
},
mounted() {
},
computed: {
xdetails() {
return this.$store.state.cashier.details;
},
isLoading() {
return this.$store.state.cashier.search_status_detail === 1;
},
selected_cashier: {
get() {
return this.$store.state.cashier.selected_cashier;
},
set(val) {
this.$store.commit("cashier/update_selected_cashier", val);
},
},
},
methods: {
convertMoney(money){
return one_money(money)
},
splitArray(data) {
const list = data.split(';').map(part => part.trim())
return list
}
},
watch: {
}
}
</script>

View File

@@ -0,0 +1,71 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="../../../libs/vendor/css/google-fonts.css">
<link rel="stylesheet" href="../../../libs/vendor/css/icomoon-fonts.css">
<link rel="stylesheet" href="../../../libs/vendor/css/vuetify.min.css">
<title>One</title>
</head>
<body>
<div v-cloak id="app">
<v-app id="smartApp">
<one-navbar></one-navbar>
<v-content style="background: #F5E8DF!important">
<v-container fluid fill-height class="pl-1 pr-1 pt-2 pb-2">
<v-layout row wrap>
<v-flex xs6 class="left" fill-height pa-1>
<cashier-listing></cashier-listing>
</v-flex>
<v-flex xs6 class="right" fill-height pa-1>
<listing-detail></listing-detail>
</v-flex>
</v-layout>
</v-container>
</v-content>
<one-footer></one-footer>
</v-app>
</div>
<!-- Vendor -->
<script src="../../../libs/vendor/moment.min.js"></script>
<script src="../../../libs/vendor/numeral.min.js"></script>
<script src="../../../libs/vendor/moment-locale-id.js"></script>
<script src="../../../libs/vendor/lodash.js"></script>
<script src="../../../libs/vendor/axios.min.js"></script>
<script src="../../../libs/vendor/vue.js"></script>
<script src="../../../libs/vendor/vuex.js"></script>
<script src="../../../libs/vendor/vuetify.js"></script>
<script src="../../../libs/vendor/httpVueLoader.js"></script>
<script src="../../../libs/one_global.js"></script>
<!-- App Script -->
<script type="module">
import {
store
} from './store.js';
window.store = store;
new Vue({
store,
el: "#app",
methods: {},
components: {
'one-navbar': httpVueLoader('../../../apps/components/oneNavbarComponent.vue'),
'one-footer': httpVueLoader('../../../apps/components/oneFooter.vue'),
'cashier-listing': httpVueLoader('./components/cashierListing.vue'),
'listing-detail': httpVueLoader('./components/listingDetail.vue')
}
})
</script>
<style>
[v-cloak] {
display: none
}
</style>
</body>
</html>

View File

@@ -0,0 +1,790 @@
// 1 => LOADING
// 2 => DONE
// 3 => ERROR
import * as api from "../api/cashier.js";
export default {
namespaced: true,
state: {
dialog_cashier: false,
status_options: [
{ val: 0, text: 'All' }, { val: 1, text: 'Draft' },
{ val: 2, text: 'Paid' }, { val: 3, text: 'Realitation' }
],
selected_status: { val: 1, text: 'Draft' },
menuStartDate: false,
menuEndDate: false,
dStartDate: new Date().toISOString().substring(0, 10),
dEndDate: new Date().toISOString().substring(0, 10),
xStartDate: moment(new Date()).format('YYYY-MM-DD'),
xEndDate: moment(new Date()).format('YYYY-MM-DD'),
// listing
currentPage: 1,
search_status: 0,
search_error_message: "",
cashierList: [],
selected_cashier: {},
total_page_cashier: 0,
xsearch: "",
act: "new",
imagePreviews: [],
imagePrevPaid: [],
// form
load_status_branch: 0,
error_message: "",
alert_error: false,
branchList: [],
selected_branch: {},
search_branch: "",
accountDanaList: [],
selected_accountDana: {},
search_accountDana: "",
load_status_accDana: 0,
accountBiayaList: [],
selected_accountBiaya: {},
search_accountBiaya: "",
load_status_accBiaya: 0,
accountTempList: [],
selected_accountTemp: {},
search_accountTemp: "",
load_status_accTemp: 0,
load_status: 0,
purchaseList: [],
selected_purchase: [],
resume_total: {"totalRealitation": 0},
errors: [],
alert_error: false,
alert_success: false,
success_message: "",
totalDraft: 0,
// detail
search_status_detail: 0,
details: [],
show_progrees_upload: false,
note: "",
notepay: "",
dialog_cashier_pay: false,
totalPaid: 0,
restPrice: 0,
openprint: false,
numberRequest: [],
total_akhir: 0,
requestDescription: "",
status: '',
xdate: '',
imagePayPreviews: [],
imagePayFiles: [],
user: one_user(),
userReceive: [],
selected_userReceive:'',
imageRelationPreviews: [],
imageRelationFiles: [],
// voucher detail
dialog_view_img: false,
listing_item_realise: [],
selected_img_view: ''
},
mutations: {
update_dialog_cashier(state, val) {
state.dialog_cashier = val;
},
update_status_options(state, val) {
state.status_options = val;
},
update_selected_status(state, val) {
state.selected_status = val;
},
update_menuStartDate(state, val) {
state.menuStartDate = val;
},
update_menuEndDate(state, val) {
state.menuEndDate = val;
},
update_dStartDate(state, val) {
state.dStartDate = val;
},
update_dEndDate(state, val) {
state.dEndDate = val;
},
update_xStartDate(state, val) {
state.xStartDate = val;
},
update_xEndDate(state, val) {
state.xEndDate = val;
},
update_currentPage(state, val) {
state.currentPage = val;
},
update_search_status(state, val) {
state.search_status = val;
},
update_search_error_message(state, val) {
state.search_error_message = val;
},
update_cashierList(state, val) {
state.cashierList = val;
},
update_selected_cashier(state, val) {
state.selected_cashier = val;
},
update_total_page_cashier(state, val) {
state.total_page_cashier = val;
},
update_xsearch(state, val) {
state.xsearch = val;
state.currentPage = 1;
},
update_act(state, val) {
state.act = val
},
update_load_status_branch(state, val) {
state.load_status_branch = val;
},
update_error_message(state, val) {
state.error_message = val;
},
update_alert_error(state, val) {
state.alert_error = val;
},
update_branchList(state, val) {
state.branchList = val;
},
update_selected_branch(state, val) {
state.selected_branch = val;
},
update_search_branch(state, val) {
state.search_branch = val;
},
update_accountDanaList(state, val) {
state.accountDanaList = val;
},
update_selected_accountDana(state, val) {
state.selected_accountDana = val;
},
update_search_accountDana(state, val) {
state.search_accountDana = val;
},
update_load_status_accDana(state, val) {
state.load_status_accDana = val;
},
update_accountBiayaList(state, val) {
state.accountBiayaList = val;
},
update_selected_accountBiaya(state, val) {
state.selected_accountBiaya = val;
},
update_search_accountBiaya(state, val) {
state.search_accountBiaya = val;
},
update_load_status_accBiaya(state, val) {
state.load_status_accBiaya = val;
},
update_accountTempList(state, val) {
state.accountTempList = val;
},
update_selected_accountTemp(state, val) {
state.selected_accountTemp = val;
},
update_search_accountTemp(state, val) {
state.search_accountTemp = val;
},
update_load_status_accTemp(state, val) {
state.load_status_accTemp = val;
},
update_load_status(state, val) {
state.load_status = val;
},
update_purchaseList(state, val) {
state.purchaseList = val;
},
update_selected_purchase(state, val) {
state.selected_purchase = val;
},
update_resume_total(state, val) {
state.resume_total = val;
},
update_errors(state, val) {
state.errors = val;
},
update_alert_error(state, val) {
state.alert_error = val;
},
update_alert_success(state, val) {
state.alert_success = val;
},
update_success_message(state, val) {
state.success_message = val;
},
update_totalDraft(state, val) {
state.totalDraft = val
},
update_search_status_detail(state, val) {
state.search_status_detail = val;
},
update_details(state, val) {
state.details = val
},
update_show_progrees_upload(state, val) {
state.show_progrees_upload = val
},
update_note(state, val) {
state.note = val
},
update_notepay(state, val) {
state.notepay = val
},
update_dialog_cashier_pay(state, val) {
state.dialog_cashier_pay = val
},
update_totalPaid(state, val) {
state.totalPaid = val
},
update_restPrice(state, val) {
state.restPrice = val
},
update_openprint(state, val) {
state.openprint = val
},
update_imagePreviews(state, val) {
state.imagePreviews = val
},
update_imagePrevPaid(state, val) {
state.imagePrevPaid = val
},
update_numberRequest(state, val) {
state.numberRequest = val
},
update_total_akhir(state, val) {
state.total_akhir = val
},
update_requestDescription(state, val) {
state.requestDescription = val
},
update_status(state, val) {
state.status = val
},
update_xdate(state, val) {
state.xdate = val
},
update_imagePayPreviews(state, val) {
state.imagePayPreviews = val;
},
update_imagePayFiles(state, val) {
state.imagePayFiles = val;
},
update_user(state, val) {
state.user = val;
},
update_userReceive(state, val) {
state.userReceive = val;
},
update_selected_userReceive(state, val) {
state.selected_userReceive = val;
},
update_imageRelationPreviews(state, val) {
state.imageRelationPreviews = val;
},
update_imageRelationFiles(state, val) {
state.imageRelationFiles = val;
},
update_dialog_view_img(state, val) {
state.dialog_view_img = val
},
update_listing_item_realise(state, val) {
state.listing_item_realise = val
},
update_selected_img_view(state, val) {
state.selected_img_view = val
}
},
actions: {
async search(context) {
context.commit("update_search_status", 1);
try {
var url_string = window.location.href
var url = new URL(url_string);
var status = url.searchParams.get("status");
var xstartdate = url.searchParams.get("startdate");
context.commit("update_status", status);
context.commit("update_xdate", xstartdate);
const today = moment(new Date()).format('YYYY-MM-DD');
var startDate = xstartdate == null || xstartdate == '' ? context.state.xStartDate : xstartdate;
var endDate = xstartdate == null || xstartdate == '' ? context.state.xEndDate : today;
var prm = {
token: one_token(),
currentPage: context.state.currentPage,
status: status == null || status == '' ? context.state.selected_status.text : status,
search: context.state.xsearch,
startdate: startDate,
enddate: endDate,
lastId: -1,
};
let resp = await api.search(prm);
if (resp.status != "OK") {
context.commit("update_search_status", 3);
context.commit("update_search_error_message", resp.message);
} else {
context.commit("update_search_status", 2);
context.commit("update_search_error_message", "");
let data = {
records: resp.data.records,
total: resp.data.total,
};
context.commit("update_cashierList", data.records);
context.commit("update_total_page_cashier", data.total);
}
} catch (e) {
context.commit("update_search_status", 3);
context.commit("update_search_error_message", e.message);
}
},
async searchBranch(context, prm) {
context.commit("update_load_status_branch", 1)
try {
let resp = await api.searchBranch(one_token(), prm)
if (resp.status != "OK") {
context.commit("update_load_status_branch", 3)
context.commit("update_error_message", resp.message);
context.commit("update_alert_error", true);
} else {
context.commit("update_load_status_branch", 2)
context.commit("update_error_message", "");
let data = {
records: resp.data.records
}
context.commit("update_branchList", data.records)
}
} catch (e) {
context.commit("update_load_status_branch", 3)
context.commit("update_error_message", e.message);
context.commit("update_alert_error", true);
}
},
async searchAccDana(context, prm) {
context.commit("update_load_status_accDana", 1)
try {
let resp = await api.searchAccDana(one_token(), prm)
if (resp.status != "OK") {
context.commit("update_load_status_accDana", 3)
context.commit("update_error_message", resp.message);
context.commit("update_alert_error", true);
} else {
context.commit("update_load_status_accDana", 2)
context.commit("update_error_message", "");
let data = {
records: resp.data.records
}
context.commit("update_accountDanaList", data.records)
}
} catch (e) {
context.commit("update_load_status_accDana", 3)
context.commit("update_error_message", e.message);
context.commit("update_alert_error", true);
}
},
async searchAccBiaya(context, prm) {
context.commit("update_load_status_accBiaya", 1)
try {
let resp = await api.searchAccBiaya(one_token(), prm)
if (resp.status != "OK") {
context.commit("update_load_status_accBiaya", 3)
context.commit("update_error_message", resp.message);
context.commit("update_alert_error", true);
} else {
context.commit("update_load_status_accBiaya", 2)
context.commit("update_error_message", "");
let data = {
records: resp.data.records
}
context.commit("update_accountBiayaList", data.records)
}
} catch (e) {
context.commit("update_load_status_accBiaya", 3)
context.commit("update_error_message", e.message);
context.commit("update_alert_error", true);
}
},
async searchAccTemp(context, prm) {
context.commit("update_load_status_accTemp", 1)
try {
let resp = await api.searchAccTemp(one_token(), prm)
if (resp.status != "OK") {
context.commit("update_load_status_accTemp", 3)
context.commit("update_error_message", resp.message);
context.commit("update_alert_error", true);
} else {
context.commit("update_load_status_accTemp", 2)
context.commit("update_error_message", "");
let data = {
records: resp.data.records
}
context.commit("update_accountTempList", data.records)
}
} catch (e) {
context.commit("update_load_status_accTemp", 3)
context.commit("update_error_message", e.message);
context.commit("update_alert_error", true);
}
},
async getPurchase(context, prm) {
context.commit("update_load_status", 1)
try {
let resp = await api.getPurchase(one_token(), prm)
if (resp.status != "OK") {
context.commit("update_load_status", 3)
context.commit("update_error_message", resp.message);
context.commit("update_alert_error", true);
} else {
context.commit("update_load_status", 2)
context.commit("update_error_message", "");
let data = {
records: resp.data.records
}
context.commit("update_purchaseList", data.records)
}
} catch (e) {
context.commit("update_load_status", 3)
context.commit("update_error_message", e.message);
context.commit("update_alert_error", true);
}
},
async searchdetail(context, prm) {
context.commit("update_search_status_detail", 1)
try {
let resp = await api.searchdetail(one_token(), prm)
if (resp.status != "OK") {
context.commit("update_search_status_detail", 3)
context.commit("update_search_error_message", resp.message);
} else {
context.commit("update_search_status_detail", 2)
context.commit("update_search_error_message", "");
let data = {
records: resp.data.records
}
let total = 0;
data.records.forEach(element => {
total = total + Number(element.realised_price)
});
context.commit("update_details", data.records)
context.commit("update_restPrice", total)
}
} catch (e) {
context.commit("update_search_status_detail", 3)
context.commit("update_search_error_message", e.message);
}
},
async save(context, prm) {
context.commit("update_search_status_detail", 1)
try {
let resp = await api.saveDetail(one_token(), prm)
if (resp.status != "OK") {
context.commit("update_search_status_detail", 3)
context.commit("update_error_message", resp.message);
context.commit("update_alert_error", true);
} else {
context.commit("update_search_status_detail", 2)
context.commit("update_error_message", resp.message);
let data = {
records: resp.data.records
}
context.commit("update_alert_success", true);
context.commit("update_dialog_cashier", false);
var msg = `Sukses menyimpan data baru dengan kode ${data.records[0].PaymentVoucherNumber}`;
context.commit("update_success_message", msg);
context.commit("update_selected_cashier", data.records[0]);
context.dispatch("search");
context.dispatch("searchdetail", data.records[0].PaymentVoucherID);
}
} catch (e) {
context.commit("update_search_status_detail", 3)
context.commit("update_error_message", e.message);
context.commit("update_alert_error", true);
}
},
async getTotalDraft(context, prm) {
context.commit("update_search_status", 1)
try {
let resp = await api.getTotalDraft(one_token(), prm)
if (resp.status != "OK") {
context.commit("update_search_status", 3)
context.commit("update_error_message", resp.message);
} else {
context.commit("update_search_status", 2)
context.commit("update_error_message", "");
let data = {
total: resp.data.total
}
context.commit("update_totalDraft", data.total)
}
} catch (e) {
context.commit("update_search_status", 3)
context.commit("update_error_message", e.message);
}
},
async getTotalPaid(context, prm) {
context.commit("update_search_status", 1)
try {
let resp = await api.getTotalPaid(one_token(), prm)
if (resp.status != "OK") {
context.commit("update_search_status", 3)
context.commit("update_error_message", resp.message);
} else {
context.commit("update_search_status", 2)
context.commit("update_error_message", "");
let data = {
total: resp.data.total
}
context.commit("update_totalPaid", data.total)
}
} catch (e) {
context.commit("update_search_status", 3)
context.commit("update_error_message", e.message);
}
},
async delete(context, prm) {
context.commit("update_search_status", 1)
try {
let resp = await api.deleteVoucher(one_token(), prm)
if (resp.status != "OK") {
context.commit("update_search_status", 3)
context.commit("update_error_message", resp.message);
context.commit("update_alert_error", true);
} else {
context.commit("update_search_status", 2)
context.commit("update_error_message", resp.message);
let data = {
records: resp.data.records
}
context.commit("update_alert_success", true);
context.commit("update_dialog_cashier", false);
var msg = `Sukses menghapus data dengan kode ` + prm.PVNumber;
context.commit("update_success_message", msg);
// context.commit("update_selected_cashier", data.records[0]);
context.dispatch("search");
context.dispatch("searchdetail", "");
}
} catch (e) {
context.commit("update_search_status", 3)
context.commit("update_error_message", e.message);
context.commit("update_alert_error", true);
}
},
async update(context, prm) {
context.commit("update_search_status_detail", 1)
try {
let resp = await api.editVoucherV2(prm)
if (resp.status != "OK") {
context.commit("update_search_status_detail", 3)
context.commit("update_error_message", resp.message);
context.commit("update_alert_error", true);
} else {
context.commit("update_search_status_detail", 2)
context.commit("update_error_message", resp.message);
let data = {
records: resp.data.records
}
context.commit("update_note", "");
context.commit("update_restPrice", 0);
context.commit("update_total_akhir", 0);
context.commit("update_imageRelationPreviews", []);
context.commit("update_imageRelationFiles", []);
context.commit("update_alert_success", true);
context.commit("update_dialog_cashier", false);
var msg = `Sukses Realisasi dengan kode ${data.records[0].PaymentVoucherNumber}`;
context.commit("update_success_message", msg);
// context.commit("update_selected_cashier", data.records[0]);
context.dispatch("search");
// context.dispatch("searchdetail", data.records[0].PaymentVoucherID);
}
} catch (e) {
context.commit("update_search_status_detail", 3)
context.commit("update_error_message", e.message);
context.commit("update_alert_error", true);
}
},
async updatepaid(context, prm) {
context.commit("update_search_status_detail", 1)
try {
let resp = await api.updatepaid(prm)
console.log("updatepaid resp", resp)
if (resp.status != "OK") {
context.commit("update_search_status_detail", 3)
context.commit("update_error_message", resp.message);
context.commit("update_alert_error", true);
} else {
context.commit("update_search_status_detail", 2)
context.commit("update_error_message", resp.message);
let data = {
records: resp.data.records
}
context.commit("update_notepay", "");
context.commit("update_imagePayPreviews", []);
context.commit("update_imagePayFiles", []);
context.commit("update_selected_userReceive", '');
context.commit("update_alert_success", true);
context.commit("update_dialog_cashier_pay", false);
var msg = `Sukses Pembayaran dengan kode ${data.records[0].PaymentVoucherNumber}`;
context.commit("update_success_message", msg);
// context.commit("update_selected_cashier", data.records[0]);
context.dispatch("search");
// context.dispatch("searchdetail", data.records[0].PaymentVoucherID);
}
} catch (e) {
context.commit("update_search_status_detail", 3)
context.commit("update_error_message", e.message);
context.commit("update_alert_error", true);
}
},
async getPurchaseUpdateNew(context, prm) {
context.commit("update_load_status", 1)
try {
let resp = await api.getPurchaseUpdateNew(one_token(), prm)
if (resp.status != "OK") {
context.commit("update_load_status", 3)
context.commit("update_error_message", resp.message);
context.commit("update_alert_error", true);
} else {
context.commit("update_load_status", 2)
context.commit("update_error_message", "");
let data = {
records: resp.data.records
}
context.commit("update_purchaseList", data.records)
}
} catch (e) {
context.commit("update_load_status", 3)
context.commit("update_error_message", e.message);
context.commit("update_alert_error", true);
}
},
async getUserReceive(context) {
context.commit("update_load_status", 1)
try {
let prm = {
token: one_token(),
userId: context.state.user.M_UserID,
}
let resp = await api.getUserReceive(prm)
if (resp.status != "OK") {
context.commit("update_load_status", 3)
context.commit("update_error_message", resp.message);
context.commit("update_alert_error", true);
} else {
context.commit("update_load_status", 2)
context.commit("update_error_message", "");
let data = {
records: resp.data.records
}
context.commit("update_userReceive", data.records)
}
} catch (e) {
context.commit("update_load_status", 3)
context.commit("update_error_message", e.message);
context.commit("update_alert_error", true);
}
},
async getVoucherDetail(context) {
try {
let param = {
token: one_token(),
ID: context.state.selected_cashier.PaymentVoucherID
}
let resp = await api.getVoucherDetail(param)
if (resp.status != 'OK') {
context.commit("update_error_message", resp.message);
context.commit("update_alert_error", true);
} else {
let data = resp.data
context.commit("update_listing_item_realise", data)
let realised = data.reduce((sum, item) => sum + Number(item.estimate_price), 0);
let detail = context.state.details;
let adjustment = detail.reduce((sum, item) => sum + Number(item.PurchaseRequestDirectAdjustment), 0)
let total = Number(context.state.selected_cashier.PaymentVoucherTotal)
let sisa = (total + adjustment) - realised
context.commit("update_total_akhir", sisa)
}
} catch (error) {
context.commit("update_error_message", error.message);
context.commit("update_alert_error", true);
}
},
async saveVoucherDetail(context, param) {
try {
param.token = one_token()
let resp = await api.saveVoucherDetail(param)
if (resp.status != 'OK') {
context.commit("update_error_message", resp.message);
context.commit("update_alert_error", true);
} else {
context.commit("update_alert_success", true);
context.commit("update_success_message", "Success");
let ID = context.state.selected_cashier.PaymentVoucherID;
context.dispatch("searchdetail", ID)
context.commit("update_dialog_realise_item", false);
context.commit("update_listing_item_realise", [])
}
} catch (error) {
context.commit("update_error_message", error.message);
context.commit("update_alert_error", true);
}
}
},
};

View File

@@ -0,0 +1,11 @@
import cashier from "./modules/cashier.js";
import system from "../../../apps/modules/system/system.js";
export const store = new Vuex.Store({
modules: {
cashier: cashier,
system: system,
},
state: {},
mutations: {},
actions: {},
});

View File

@@ -0,0 +1,192 @@
const URL = "/one-api/fixedasset/item";
export async function getAcAccumDepre(prm) {
try {
var resp = await axios.post(URL + '/getAcAccumDepre', prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function getAcCoa(prm) {
try {
var resp = await axios.post(URL + '/getAcCoa', prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function getItem(prm) {
try {
var resp = await axios.post(URL + '/getItem', prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function getDepartment(prm) {
try {
var resp = await axios.post(URL + '/getDepartment', prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function getPresentase(prm) {
try {
var resp = await axios.post(URL + '/getPresentase', prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function search(prm) {
try {
var resp = await axios.post(URL + "/search", prm);
if (resp.status !== 200) {
return {
status: "ERR",
message: resp.statusText,
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function addData(prm) {
try {
var resp = await axios.post(URL + '/addData', prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function getByID(prm) {
try {
var resp = await axios.post(URL + '/get_by_id', prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function editData(prm) {
try {
var resp = await axios.post(URL + '/editData', prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function deleteData(prm) {
try {
var resp = await axios.post(URL + '/deleteData', prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,69 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="../../../libs/vendor/css/google-fonts.css">
<link rel="stylesheet" href="../../../libs/vendor/css/icomoon-fonts.css">
<link rel="stylesheet" href="../../../libs/vendor/css/vuetify.min.css">
<title>One</title>
</head>
<body>
<div v-cloak id="app">
<v-app id="smartApp">
<one-navbar></one-navbar>
<v-content style="background: #F5E8DF!important">
<v-container fluid fill-height class="pl-1 pr-1 pt-2 pb-2">
<v-layout row wrap>
<v-flex xs12 class="left" fill-height pa-1>
<one-fixedasset-list></one-fixedasset-list>
</v-flex>
</v-layout>
</v-container>
</v-content>
<one-footer> </one-footer>
</v-app>
</div>
<!-- Vendor -->
<script src="../../../libs/vendor/moment.min.js"></script>
<script src="../../../libs/vendor/numeral.min.js"></script>
<script src="../../../libs/vendor/moment-locale-id.js"></script>
<script src="../../../libs/vendor/lodash.js"></script>
<script src="../../../libs/vendor/axios.min.js"></script>
<script src="../../../libs/vendor/vue.js"></script>
<script src="../../../libs/vendor/vuex.js"></script>
<script src="../../../libs/vendor/vuetify.js"></script>
<script src="../../../libs/vendor/httpVueLoader.js"></script>
<script src="../../../libs/one_global.js"></script>
<!-- App Script -->
<script type="module">
import {
store
} from './store.js';
window.store = store;
new Vue({
store,
el: '#app',
methods: {
},
components: {
'one-navbar': httpVueLoader('../../../apps/components/oneNavbarComponent.vue'),
'one-footer': httpVueLoader('../../../apps/components/oneFooter.vue'),
'one-fixedasset-list': httpVueLoader('./components/FixedAsset.vue')
}
})
</script>
<style>
[v-cloak] {
display: none;
}
</style>
</body>
</html>

View File

@@ -0,0 +1,671 @@
import * as api from "../api/fixedasset.js"
export default {
namespaced: true,
state: {
Fa_ClassID: 0,
a_coas: [],
a_msg_info: '',
a_open_dialog_info: false,
a_save_status: 0,
// search table
a_x_search: '',
a_current_page: 1,
a_last_id: -1,
a_total_coa: 0,
// search table
a_selected_a_coa: {},
a_search_status: 0,
a_alert_success: false,
a_msg_success: '',
a_alert_error: false,
a_save_error_message: '',
dialog_add_coa: false,
dialog_edit_coa: false,
e_loading_nat_group: false,
// text classname
a_faname: '',
e_classname: '',
// ac coa
a_loading_coa: false,
a_coa_list: [],
a_coa: {},
a_coa_search: '',
// ac item
a_loading_item: false,
a_item_list: [],
a_item: {},
a_item_search: '',
// ac department
a_loading_department: false,
a_department_list: [],
a_department: {},
a_department_search: '',
// ac presentase
a_loading_presentase: false,
a_presentase_list: [],
a_presentase: {},
a_presentase_search: '',
a_inventaris : '',
a_note : '',
a_fa_account_id: 0,
a_fa_account_name: '',
a_accum_depre_account_id: 0,
a_accum_depre_account_name: '',
a_depre_account_id: 0,
a_depre_account_name: '',
a_qty: 1,
a_acquisition_price: 0,
a_book_value: 0,
// text note
a_note: '',
e_note: '',
a_errors_save: [],
Fa_ClassID: 0,
a_errors_save_coa: [],
xid: 0,
xnumber: '',
errors: [],
a_fa_age: 0,
a_fa_depresiasi_bulan: 0,
branchOptions: [],
regionalOptions: [],
xRegional: "",
xBranch: ""
},
mutations: {
updateBranchOptions(state, val) {
state.branchOptions = val;
},
updateRegionalOptions(state, val) {
state.regionalOptions = val;
},
updateXRegional(state, val) {
state.xRegional = val;
},
updateXBranch(state, val) {
state.xBranch = val;
},
update_a_fa_age(state, val) {
state.a_fa_age = val;
},
update_a_fa_depresiasi_bulan(state, val) {
state.a_fa_depresiasi_bulan = val;
},
update_errors(state, val) {
state.errors = val;
},
update_xid(state, val) {
state.xid = val
},
update_xnumber(state, val) {
state.xnumber = val
},
update_a_errors_save_coa(state, val) {
state.a_errors_save_coa = val
},
update_a_selected_a_coa(state, val) {
state.a_selected_a_coa = val
},
update_e_loading_nat_group(state, val) {
state.e_loading_nat_group = val
},
update_a_errors_save(state, val) {
state.a_errors_save = val
},
update_a_save_error_message(state, val) {
state.a_save_error_message = val
},
update_a_alert_error(state, val) {
state.a_alert_error = val
},
update_a_msg_success(state, val) {
state.a_msg_success = val
},
update_a_msg_info(state, val) {
state.a_msg_info = val
},
update_a_open_dialog_info(state, val) {
state.a_open_dialog_info = val
},
update_a_alert_success(state, val) {
state.a_alert_success = val
},
update_dialog_add_coa(state, val) {
state.dialog_add_coa = val
},
//table
update_a_search_error_message(state, val) {
state.a_search_error_message = val
},
update_a_search_status(state, val) {
state.a_search_status = val
},
update_a_x_search(state, val) {
state.a_x_search = val
},
update_a_current_page(state, val) {
state.a_current_page = val
},
update_a_last_id(state, val) {
state.a_last_id = val
},
update_a_total_coa(state, val) {
state.a_total_coa = val
},
update_a_a_coas(state, val) {
state.a_coas = val
},
// text classname
update_a_faname(state, val) {
state.a_faname = val
},
update_e_classname(state, val) {
state.e_classname = val
},
// ac coa
update_a_loading_coa(state, val) {
state.a_loading_coa = val
},
update_e_loading_coa(state, val) {
state.e_loading_coa = val
},
update_a_coa_list(state, val) {
state.a_coa_list = val
},
update_e_coa_list(state, val) {
state.e_coa_list = val
},
update_a_coa(state, val) {
state.a_coa = val
},
update_e_coa(state, val) {
state.e_coa = val
},
update_a_coa_search(state, val) {
state.a_coa_search = val
},
update_e_coa_search(state, val) {
state.e_coa_search = val
},
// ac item
update_a_loading_item(state, val) {
state.a_loading_item = val
},
update_a_item_list(state, val) {
state.a_item_list = val
},
update_a_item(state, val) {
state.a_item = val
},
update_a_item_search(state, val) {
state.a_item_search = val
},
// ac department
update_a_loading_department(state, val) {
state.a_loading_department = val
},
update_a_department_list(state, val) {
state.a_department_list = val
},
update_a_department(state, val) {
state.a_department = val
},
update_a_department_search(state, val) {
state.a_department_search = val
},
// ac presentase
update_a_loading_presentase(state, val) {
state.a_loading_presentase = val
},
update_a_presentase_list(state, val) {
state.a_presentase_list = val
},
update_a_presentase(state, val) {
state.a_presentase = val
},
update_a_presentase_search(state, val) {
state.a_presentase_search = val
},
update_a_inventaris(state, val) {
state.a_inventaris = val
},
update_a_note(state, val) {
state.a_note = val
},
update_a_fa_account_id(state, val) {
state.a_fa_account_id = val
},
update_a_fa_account_name(state, val) {
state.a_fa_account_name = val
},
update_a_accum_depre_account_id(state, val) {
state.a_accum_depre_account_id = val
},
update_a_accum_depre_account_name(state, val) {
state.a_accum_depre_account_name = val
},
update_a_depre_account_id(state, val) {
state.a_depre_account_id = val
},
update_a_depre_account_name(state, val) {
state.a_depre_account_name = val
},
update_a_qty(state, val) {
state.a_qty = val
},
update_a_acquisition_price(state, val) {
state.a_acquisition_price = val
},
update_a_book_value(state, val) {
state.a_book_value = val
},
// text note
update_a_note(state, val) {
state.a_note = val
},
update_e_note(state, val) {
state.e_note = val
},
update_dialog_add_coa(state, val) {
state.dialog_add_coa = val
},
update_dialog_edit_coa(state, val) {
state.dialog_edit_coa = val
},
update_Fa_ClassID(state, val) {
state.Fa_ClassID = val
},
update_a_save_status(state, val) {
state.a_save_status = val
},
},
actions: {
// search
async search(context, prm) {
context.commit("update_a_search_status", 1)
try {
prm.token = one_token()
let resp = await api.search(prm)
if (resp.status != "OK") {
context.commit("update_a_search_status", 3)
context.commit("update_a_search_error_message", resp.message)
context.commit("update_a_msg_info", resp.message)
context.commit("update_a_open_dialog_info", true)
} else {
context.commit("update_a_search_status", 2)
context.commit("update_a_search_error_message", "")
context.commit("update_a_msg_info", resp.message)
let data = {
records: resp.data.records,
total: resp.data.total
}
context.commit("update_a_a_coas", data.records)
context.commit("update_a_total_coa", data.total)
}
} catch (e) {
context.commit("update_a_search_status", 3)
context.commit("update_a_search_error_message", e.message)
context.commit("update_a_msg_info", e.message)
context.commit("update_a_open_dialog_info", true)
}
},
// get ac coa from api
async open_add_coa(context, payload) {
context.commit("update_a_loading_coa", true)
try {
let prm = {};
prm.token = one_token()
prm.search = payload.search
let resp = await api.getAcCoa(prm)
// console.log('data nat_group ',resp)
if (resp.status != "OK") {
context.commit("update_a_loading_coa", false)
} else {
// console.log('data nat_group ',resp.data)
context.commit("update_a_loading_coa", false)
context.commit("update_a_coa_list", resp.data)
}
} catch (e) {
context.commit("update_a_loading_coa", false)
}
},
async open_add_item(context, payload) {
context.commit("update_a_loading_item", true)
try {
let prm = {};
prm.token = one_token()
prm.search = payload.search
let resp = await api.getItem(prm)
// console.log('data nat_group ',resp)
if (resp.status != "OK") {
context.commit("update_a_loading_item", false)
} else {
// console.log('data nat_group ',resp.data)
context.commit("update_a_loading_item", false)
context.commit("update_a_item_list", resp.data)
}
} catch (e) {
context.commit("update_a_loading_item", false)
}
},
async open_add_department(context, payload) {
context.commit("update_a_loading_department", true)
try {
let prm = {};
prm.token = one_token()
prm.search = payload.search
let resp = await api.getDepartment(prm)
// console.log('data nat_group ',resp)
if (resp.status != "OK") {
context.commit("update_a_loading_department", false)
} else {
// console.log('data nat_group ',resp.data)
context.commit("update_a_loading_department", false)
context.commit("update_a_department_list", resp.data)
}
} catch (e) {
context.commit("update_a_loading_department", false)
}
},
async open_add_presentase(context, payload) {
context.commit("update_a_loading_presentase", true)
try {
let prm = {};
prm.token = one_token()
prm.search = payload.search
let resp = await api.getPresentase(prm)
// console.log('data nat_group ',resp)
if (resp.status != "OK") {
context.commit("update_a_loading_presentase", false)
} else {
// console.log('data nat_group ',resp.data)
context.commit("update_a_loading_presentase", false)
context.commit("update_a_presentase_list", resp.data)
}
} catch (e) {
context.commit("update_a_loading_presentase", false)
}
},
// add data
async add_data(context, prm) {
context.commit("update_a_save_status", 1)
try {
prm.token = one_token()
let resp = await api.addData(prm)
// console.log('data nat_group ',resp)
if (resp.status != "OK") {
context.commit("update_a_save_status", 3)
context.commit("update_a_save_error_message", resp.message)
context.commit("update_a_alert_error", true)
} else {
context.commit("update_a_save_status", 2)
context.commit("update_a_save_error_message", resp.message)
let data = {
total: resp.data.total
}
if (data.total !== -1) {
context.commit("update_a_alert_success", true)
var msg = " Add Data Sukses"
context.commit("update_a_msg_success", msg)
context.commit('update_dialog_add_coa', false)
context.dispatch("search", {
current_page: context.state.a_current_page,
search: context.state.a_x_search,
last_id: -1
})
context.commit("fixedasset/update_dialog_add_coa", false);
context.commit("fixedasset/update_a_faname", "");
context.commit("fixedasset/update_a_coa", {});
context.commit("fixedasset/update_a_deprecorp", "");
context.commit("fixedasset/update_a_coa_accum_depre", {});
context.commit("fixedasset/update_a_note", "");
} else {
context.commit("update_a_errors_save", [])
}
}
} catch (e) {
context.commit("update_a_save_status", 3)
context.commit("update_a_save_error_message", e.message)
context.commit("update_a_alert_error", true)
}
},
// get_by_id
async get_by_id(context, payload) {
context.commit("update_e_loading_nat_group", true)
try {
let prm = {};
prm.token = one_token()
// fa_class
prm.Fa_ClassID = payload.Fa_ClassID
// coa
prm.Fa_ClassCoaID = payload.Fa_ClassCoaID
// accum depre
prm.Fa_ClassAccumDepreCoaID = payload.Fa_ClassAccumDepreCoaID
let resp = await api.getByID(prm)
// console.log('data nat_group ',resp)
if (resp.status != "OK") {
context.commit("update_e_loading_nat_group", false)
} else {
// console.log('data nat_group ',resp.data)
context.commit("update_e_loading_nat_group", true)
// MapNatGroup_ID
context.commit("update_Fa_ClassID", resp.data.record_fa_class[0].Fa_ClassID)
// coa
context.commit("update_e_coa_list", resp.data.records_coa)
context.commit("update_e_coa", {
coaID: resp.data.records_coa[0].coaID,
coaAccountNo: resp.data.records_coa[0].coaAccountNo,
coaDescription: resp.data.records_coa[0].coaDescription,
coaSubDescription: resp.data.records_coa[0].coaSubDescription,
coaAccountType: resp.data.records_coa[0].coaAccountType,
coaSpecialAccountType: resp.data.records_coa[0].coaSpecialAccountType,
coaIsInput: resp.data.records_coa[0].coaIsInput,
coaReportSchedule: resp.data.records_coa[0].coaReportSchedule,
coaCurrencyCode: resp.data.records_coa[0].coaCurrencyCode,
coaCashFlowCategory: resp.data.records_coa[0].coaCashFlowCategory,
coaCreated: resp.data.records_coa[0].coaCreated,
coaLastUpdated: resp.data.records_coa[0].coaLastUpdated,
coaIsActive: resp.data.records_coa[0].coaIsActive,
coaLevel: resp.data.records_coa[0].coaLevel
})
// accum depre
context.commit("update_e_coa_accum_depre_list", resp.data.records_accum_depre)
context.commit("update_e_coa_accum_depre", {
coaID: resp.data.records_accum_depre[0].coaID,
coaAccountNo: resp.data.records_accum_depre[0].coaAccountNo,
coaDescription: resp.data.records_accum_depre[0].coaDescription,
coaSubDescription: resp.data.records_accum_depre[0].coaSubDescription,
coaAccountType: resp.data.records_accum_depre[0].coaAccountType,
coaSpecialAccountType: resp.data.records_accum_depre[0].coaSpecialAccountType,
coaIsInput: resp.data.records_accum_depre[0].coaIsInput,
coaReportSchedule: resp.data.records_accum_depre[0].coaReportSchedule,
coaCurrencyCode: resp.data.records_accum_depre[0].coaCurrencyCode,
coaCashFlowCategory: resp.data.records_accum_depre[0].coaCashFlowCategory,
coaCreated: resp.data.records_accum_depre[0].coaCreated,
coaLastUpdated: resp.data.records_accum_depre[0].coaLastUpdated,
coaIsActive: resp.data.records_accum_depre[0].coaIsActive,
coaLevel: resp.data.records_accum_depre[0].coaLevel
})
// fa classname
context.commit("update_e_classname", resp.data.record_fa_class[0].Fa_ClassName)
// note
context.commit("update_e_note", resp.data.record_fa_class[0].Fa_ClassAccumNote)
// depre corp
context.commit("update_e_deprecorp", resp.data.record_fa_class[0].Fa_ClassDepreCorp)
context.commit("update_dialog_edit_coa", true)
}
} catch (e) {
context.commit("update_e_loading_nat_group", false)
}
},
// get ac coa from api
async open_edit_coa(context, payload) {
context.commit("update_e_loading_coa", true)
try {
let prm = {};
prm.token = one_token()
prm.search = payload.search
let resp = await api.getAcCoa(prm)
// console.log('data nat_group ',resp)
if (resp.status != "OK") {
context.commit("update_e_loading_coa", false)
} else {
// console.log('data nat_group ',resp.data)
context.commit("update_e_loading_coa", false)
context.commit("update_e_coa_list", resp.data)
}
} catch (e) {
context.commit("update_e_loading_coa", false)
}
},
// get ac coa accum depre from api
async open_edit_coa_accum_depre(context, payload) {
context.commit("update_e_loading_coa_accum_depre", true)
try {
let prm = {};
prm.token = one_token()
prm.search = payload.search
let resp = await api.getAcAccumDepre(prm)
// console.log('data nat_group ',resp)
if (resp.status != "OK") {
context.commit("update_e_loading_coa_accum_depre", false)
} else {
// console.log('data nat_group ',resp.data)
context.commit("update_e_loading_coa_accum_depre", false)
context.commit("update_e_coa_accum_depre_list", resp.data)
}
} catch (e) {
context.commit("update_e_loading_coa_accum_depre", false)
}
},
async regional(context) {
let response = await api.getRegional({ token: one_token() });
if (response.status === "OK") {
let data = {
records: response.data.records,
};
context.commit("updateRegionalOptions", data.records);
}
},
async branch(context) {
let response = await api.getBranch({ token: one_token() });
if (response.status === "OK") {
let data = {
records: response.data.records,
};
context.commit("updateBranchOptions", data.records);
}
},
// edit data
async edit_data(context, prm) {
context.commit("update_a_save_status", 1)
try {
prm.token = one_token()
let resp = await api.editData(prm)
// console.log('data nat_group ',resp)
if (resp.status != "OK") {
context.commit("update_a_save_status", 3)
context.commit("update_a_save_error_message", resp.message)
context.commit("update_a_alert_error", true)
} else {
context.commit("update_a_save_status", 2)
context.commit("update_a_save_error_message", resp.message)
let data = {
total: resp.data.total
}
if (data.total !== -1) {
context.commit("update_a_alert_success", true)
var msg = " Edit Data Sukses"
context.commit("update_a_msg_success", msg)
context.commit('update_dialog_add_coa', false)
context.dispatch("search", {
current_page: context.state.a_current_page,
search: context.state.a_x_search,
last_id: -1
})
context.commit("fixedasset/update_dialog_add_coa", false);
context.commit("fixedasset/update_a_faname", "");
context.commit("fixedasset/update_a_coa", {});
context.commit("fixedasset/update_a_deprecorp", "");
context.commit("fixedasset/update_a_coa_accum_depre", {});
context.commit("fixedasset/update_a_note", "");
} else {
context.commit("update_a_errors_save", [])
}
}
} catch (e) {
context.commit("update_a_save_status", 3)
context.commit("update_a_save_error_message", e.message)
context.commit("update_a_alert_error", true)
}
},
// delete data
async delete_data(context, prm) {
context.commit("update_a_save_status", 1)
try {
prm.token = one_token()
let resp = await api.deleteData(prm)
if (resp.status != "OK") {
context.commit("update_a_save_status", 3)
context.commit("update_a_save_error_message", resp.message)
context.commit("update_a_alert_error", true)
} else {
context.commit("update_a_save_status", 2)
context.commit("update_a_save_error_message", resp.message)
let data = {
total: resp.data.total
}
if (data.total !== -1) {
context.commit("update_a_alert_success", true)
var msg = " Coa " + prm.delete_data + " berhasil dihapus"
context.commit("update_a_msg_success", msg)
context.dispatch("search", {
current_page: context.state.a_current_page,
search: context.state.a_x_search,
last_id: -1
})
} else {
context.commit("update_a_errors_save_coa", [])
}
}
} catch (e) {
context.commit("update_a_save_status", 3)
context.commit("update_a_save_error_message", e.message)
context.commit("update_a_alert_error", true)
}
},
},
}

View File

@@ -0,0 +1,12 @@
import system from "../../../apps/modules/system/system.js";
import fixedasset from "./modules/fixedasset.js";
export const store = new Vuex.Store({
modules: {
system: system,
fixedasset:fixedasset,
},
state: {},
mutations: {},
actions: {},
});

View File

@@ -0,0 +1,559 @@
const URL = "/one-api/mockup/itemout/";
export async function search(prm) {
try {
var response = await axios.post(URL + "itemoutv3/search", prm);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function searchDetail(prm) {
try {
var response = await axios.post(
URL + "itemoutv3/searchDetail",
prm
);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function saveRequest(prm) {
try {
var response = await axios.post(
URL + "itemoutv3/saveRequest",
prm
);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function updateRequest(prm) {
try {
var response = await axios.post(
URL + "itemoutv3/updateRequest",
prm
);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function deleteRequest(prm) {
try {
var response = await axios.post(
URL + "itemoutv3/deleteRequest",
prm
);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function saveDetail(prm) {
try {
var response = await axios.post(
URL + "itemoutv3/saveDetail",
prm
);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function updateDetail(prm) {
try {
var response = await axios.post(
URL + "itemoutv3/updateDetail",
prm
);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function deleteDetail(prm) {
try {
var response = await axios.post(
URL + "itemoutv3/deleteDetail",
prm
);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function getWarehouse(prm) {
try {
var response = await axios.post(
URL + "itemoutv3/getWarehouse",
prm
);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function getDepartment(prm) {
try {
var response = await axios.post(
URL + "itemoutv3/getDepartment",
prm
);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function searchItem(prm) {
try {
var resp = await axios.post(URL + 'itemoutv3/searchItem', prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function getUnit(prm) {
try {
var resp = await axios.post(URL + 'itemoutv3/getUnit', prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function orderConfirm(prm) {
try {
var response = await axios.post(
URL + "itemoutv3/orderConfirm",
prm
);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function listrequestitem(prm) {
try {
var response = await axios.post(URL + "itemoutv3/listrequest", prm);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function getDivisionUser(payload) {
try {
var response = await axios.post(URL + "RequestItemOut/getDivisionUser", payload);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function approveRequest(prm) {
try {
var response = await axios.post(URL + "itemoutv3/approveRequest", prm);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function rejectedRequest(prm) {
try {
var response = await axios.post(URL + "itemoutv3/rejectedRequest", prm);
if (response.status !== 200) {
return {
status: "ERR",
message: response.statusText,
};
}
let data = response.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}
export async function getDivisionByUser(prm) {
try {
var resp = await axios.post(URL + 'itemoutv3/getDivisionByUser', prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function getItemRequest(prm) {
try {
var resp = await axios.post(URL + 'itemoutv3/getItemRequest', prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function getDetailItemOut(prm) {
try {
var resp = await axios.post(URL + 'itemoutv3/getDetailItemOut', prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function getItemOuts(prm) {
try {
var resp = await axios.post(URL + 'itemoutv3/getItemOuts', prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function confirmIO(prm) {
try {
var resp = await axios.post(URL + 'itemoutv3/confirmIO', prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function approveIO(prm) {
try {
var resp = await axios.post(URL + 'itemoutv3/approveIO', prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function processIO(prm) {
try {
var resp = await axios.post(URL + 'itemoutv3/processIO', prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function rejectRequest(prm) {
try {
var resp = await axios.post(URL + 'itemoutv3/rejectRequest', prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function getItemBatchListing(params) {
try {
var resp = await axios.post(URL + "itemoutv3/getItemBatchListing", params);
if (resp.status !== 200) {
return {
status: "ERR",
message: resp.message
}
}
let data = resp.data
return data
} catch (error) {
return {
status: "ERR",
message: error.message
}
}
}
export async function getlevel(prm) {
try {
var resp = await axios.post(URL + "itemoutv3/getlevel", prm);
if (resp.status !== 200) {
return {
status: "ERR",
message: resp.statusText,
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message,
};
}
}

View File

@@ -0,0 +1,324 @@
<template>
<v-layout row justify-center>
<v-dialog v-model="dialogDetail" persistent max-width="50vw">
<v-card>
<v-card-title class="headline grey lighten-2" primary-title>
FORM DETAIL
</v-card-title>
<v-card-text class="pt-0 pb-0">
<v-layout wrap>
<v-flex xs12>
<code
class="mb-2 mt-2"
style="font-size: 14px"
>Gudang : {{ this.selectedMainTable.WarehouseName }}</code
>
</v-flex>
<v-flex xs12>
<v-autocomplete label="Item" :items="itemList" v-model="selectedItem"
:search-input.sync="search_item"
auto-select-first no-filter item-text="M_ItemDesc" return-object
no-data-text="Pilih Item" required>
<template slot="item" slot-scope="{ item }">
<v-list-tile-content>
<v-list-tile-title v-text="item.M_ItemDesc"></v-list-tile-title>
<v-list-tile-sub-title
v-text="item.ItemCode"
></v-list-tile-sub-title>
</v-list-tile-content>
</template>
</v-autocomplete>
<p v-if="checkErrorForm('requireItem')" class="error pl-2 pr-2" style="color:#fff">Item harus diisi</p>
</v-flex>
<v-flex xs12>
<v-text-field
label="Stock Qty"
:value="selectedItem.StockQty"
readonly>
</v-text-field>
</v-flex>
<v-flex xs12>
<v-text-field
v-model="xQty"
type="number"
label="Qty"
required
></v-text-field>
<p v-if="checkErrorForm('requireQty')" class="error pl-2 pr-2" style="color:#fff">Qty harus diisi</p>
</v-flex>
<v-flex xs12>
<v-autocomplete label="Item Unit" v-model="selected_item_unit"
:items="item_units" :search-input.sync="search_item_unit"
auto-select-first no-filter item-text="ItemUnitName"
return-object
no-data-text="Pilih Item Unit"
required>
<template slot="item" slot-scope="{ item }">
<v-list-tile-content>
<v-list-tile-title v-text="item.ItemUnitName"></v-list-tile-title>
</v-list-tile-content>
</template>
</v-autocomplete>
<p v-if="checkErrorForm('requireItemUnit')" class="error pl-2 pr-2" style="color:#fff">Item Unit harus diisi</p>
</v-flex>
</v-layout>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="error" flat @click="closeDialogDetail()"> Tutup </v-btn>
<v-btn v-if="act === 'new'" color="primary" dark @click="saveDetail()"
>Simpan</v-btn
>
<v-btn
v-if="act === 'edit'"
color="primary"
dark
@click="updateDetail()"
>Simpan Perubahan</v-btn
>
</v-card-actions>
</v-card>
</v-dialog>
</v-layout>
</template>
<style>
.red-hint .v-messages__message {
color: red !important;
}
</style>
<script>
module.exports = {
name: "AddRequestDetailDialog",
data() {
return {
itemRules: [(v) => !!v || "Item harus diisi"],
itemUnitRules: [(v) => !!v || "Item Unit harus diisi"],
descriptionRules: [(v) => !!v || "Deskripsi harus diisi"],
amountRules: [(v) => (!!v && v > 0) || "Jumlah harus diisi"],
priceRules: [(v) => (!!v && v > 0) || "Harga harus diisi"],
validationDetail: false,
};
},
mounted() {
},
computed: {
selectedMainTable() {
return this.$store.state.requester.selectedMainTable;
},
selectedDetailTable() {
return this.$store.state.requester.selectedDetailTable;
},
xDescriptionDetail: {
get() {
return this.$store.state.requester.xDescriptionDetail;
},
set(val) {
this.$store.commit("requester/updateXDescriptionDetail", val);
},
},
xQty: {
get() {
return this.$store.state.requester.xQty;
},
set(val) {
this.$store.commit("requester/updateXQty", val);
},
},
xPrice: {
get() {
return this.$store.state.requester.xPrice;
},
set(val) {
this.$store.commit("requester/updateXPrice", val);
},
},
xIsCito: {
get() {
return this.$store.state.requester.xIsCito;
},
set(val) {
this.$store.commit("requester/updateXIsCito", val);
},
},
dialogDetail: {
get() {
return this.$store.state.requester.dialogDetail;
},
set(val) {
this.$store.commit("requester/updateDialogDetail", val);
},
},
act() {
return this.$store.state.requester.act;
},
itemList() {
return this.$store.state.requester.itemList;
},
selectedItem: {
get() {
return this.$store.state.requester.selectedItem;
},
set(val) {
this.$store.commit("requester/updateSelectedItem", val);
this.$store.commit("requester/updateXPrice", '');
this.$store.dispatch("requester/getUnit", {search: "", itemID: this.selectedItem.M_ItemID})
this.$store.commit("requester/updateSelectedItemUnit", {});
// if (this.$store.state.requester.item_units.length != 0) {
// } else {
// this.$store.dispatch("requester/getUnit", {search: this.search_item_unit, itemID: this.selectedItem.M_ItemID})
// }
},
},
search_item: {
get() {
return this.$store.state.requester.search_item;
},
set(val) {
this.$store.commit("requester/update_search_item", val);
},
},
item_units() {
return this.$store.state.requester.item_units;
},
selected_item_unit: {
get() {
return this.$store.state.requester.selected_item_unit;
},
set(val) {
this.$store.commit("requester/updateSelectedItemUnit", val);
},
},
search_item_unit: {
get() {
return this.$store.state.requester.search_item_unit;
},
set(val) {
this.$store.commit("requester/updateSearchItemUnit", val);
},
},
total_price() {
return this.$store.state.requester.total_price;
},
},
methods: {
// check error form
checkErrorForm(value) {
var errors = this.$store.state.requester.errorsform
if (errors.includes(value)) {
return true
} else {
return false
}
},
closeDialogDetail() {
this.$store.commit("requester/updateSelectedItem", {});
this.$store.commit("requester/updateXQty", "");
this.$store.commit("requester/updateXPrice", "");
this.$store.commit("requester/updateXIsCito", false);
this.$store.commit("requester/updateDialogDetail", false);
},
saveDetail() {
this.$store.commit("requester/updateErrorsform", [])
var errors = this.$store.state.requester.errorsform
if(_.isEmpty(this.selectedItem)){
errors.push("requireItem")
}
if(_.isEmpty(this.xQty)){
errors.push("requireQty")
}
if(_.isEmpty(this.selected_item_unit)){
errors.push("requireItemUnit")
}
if (errors.length === 0) {
this.$store.commit("requester/updateErrorsform", [])
this.$store.dispatch("requester/saveDetail", {
IOID: this.selectedMainTable.T_ItemOutID,
itemID: this.selectedItem.M_ItemID,
itemDescription: this.selectedItem.M_ItemDesc,
qty: this.xQty,
itemUnitID: this.selected_item_unit.ItemUnitID
});
}
},
updateDetail() {
this.$store.commit("requester/updateErrorsform", [])
var errors = this.$store.state.requester.errorsform
if(_.isEmpty(this.selectedItem)){
errors.push("requireItem")
}
if(_.isEmpty(this.xQty)){
errors.push("requireQty")
}
if(_.isEmpty(this.selected_item_unit)){
errors.push("requireItemUnit")
}
if (errors.length === 0) {
this.$store.commit("requester/updateErrorsform", [])
this.$store.dispatch("requester/updateDetail", {
IOID: this.selectedMainTable.T_ItemOutID,
IODID: this.selectedDetailTable.T_ItemOutDetailID,
itemID: this.selectedItem.M_ItemID,
itemDescription: this.selectedItem.M_ItemDesc,
qty: this.xQty,
itemUnitID: this.selected_item_unit.ItemUnitID
});
}
},
thr_search_item: _.debounce(function () {
this.$store.dispatch("requester/searchItem", {search: this.search_item, warehouseID: this.selectedMainTable.WarehouseID})
}, 1000),
thr_search_item_unit: _.debounce(function () {
this.$store.dispatch("requester/getUnit", {search: this.search_item_unit, itemID: this.selectedItem.M_ItemID})
}, 1000),
},
watch: {
// dialogDetail(val, old) {
// if (val) {
// this.$refs.formDetail.reset();
// this.$refs.formDetail.resetValidation();
// }
// },
xQty(val, old) {
if (val <= 0) {
this.$store.commit("requester/updateXQty", 0);
}
},
xPrice(val, old) {
if (val <= 0) {
this.$store.commit("requester/updateXPrice", 0);
}
},
xAmountRequest(val, old) {
if (val <= 0) {
this.$store.commit("requester/updateXAmountRequest", 0);
}
},
xEstimationPrice(val, old) {
if (val < 0) {
this.$store.commit("requester/updateXEstimationPrice", 0);
}
},
search_item(val, old) {
if (val == old) return;
if (!val) return;
if (val.length < 1) return;
if (this.$store.state.requester.loadingAutocomplete == 1) return;
this.thr_search_item();
},
search_item_unit(val, old) {
if (val == old) return;
if (!val) return;
if (val.length < 1) return;
if (this.$store.state.requester.loadingAutocomplete == 1) return;
this.thr_search_item_unit();
},
},
};
</script>

View File

@@ -0,0 +1,917 @@
<template>
<div>
<v-layout row justify-center>
<v-dialog v-model="dialogRequest" persistent max-width="75%">
<v-card>
<v-card-title class="headline grey lighten-2" primary-title>
FORM PENGELUARAN BARANG
</v-card-title>
<v-card-text class="pt-2 pb-0">
<v-form ref="formRequest" v-model="validationForm" lazy-validtion>
<v-layout row>
<v-flex xs6 pa-2>
<v-menu
v-model="menuDateUse"
:close-on-content-click="false"
transition="scale-transition"
:nudge-right="40"
lazy
offset-y
full-width
max-width="290px"
min-width="290px"
>
<template v-slot:activator="{ on }">
<v-text-field
v-model="dateUseFormatted"
label="Tanggal Transaksi"
readonly
v-on="on"
@blur="dDateUse = deFormatedDate(dateUseFormatted)"
></v-text-field>
</template>
<v-date-picker
no-title
v-model="xDateUse"
@input="menuDateUse = false"
></v-date-picker>
</v-menu>
</v-flex>
<v-flex xs6 pa-2>
<v-autocomplete
v-model="xWarehouse"
label="Gudang"
menu-icon="mdi-chevron-down"
:items="warehouseOptions"
item-text="WarehouseName"
item-value="WarehouseID"
:rules="warehouseRules"
required
></v-autocomplete>
</v-flex>
<v-flex xs6 pa-2>
<v-autocomplete
v-model="selectedDivision"
label="Divisi"
menu-icon="mdi-chevron-down"
:items="divisionOptions"
item-text="DivisionName"
item-value="DivisionID"
:rules="divisionRules"
required
></v-autocomplete>
</v-flex>
<v-flex pa-2 xs6>
<v-text-field
v-model="xNote"
label="Catatan"
></v-text-field>
</v-flex>
</v-layout>
</v-form>
<v-layout row>
<v-flex pa-2 pl-0 xs12>
<v-btn v-if="dialogItem == false" color="primary" @click="dialogItem = true">Pilih Item</v-btn>
<v-btn v-if="dialogItem == true" color="primary" @click="dialogItem = false">Tutup Pilih Item</v-btn>
</v-flex>
</v-layout>
<div v-if="dialogItem == true">
<v-card class="mt-2">
<v-layout row>
<v-flex class="mt-2" pa-2 pb-0 xs3>
<v-text-field
v-model="searchItem"
label="Cari..."
placeholder="Ketikkan item"
style="max-width: 250px"
hide-details
></v-text-field>
</v-flex>
<v-flex class="mt-2" pa-2 pb-0 xs2>
<v-btn
dark
color="success"
style="min-width: 40px; height: 40px; margin: 0"
@click="itemSearch()"
>
<v-icon>search</v-icon>
</v-btn>
</v-flex>
</v-layout>
<v-layout row >
<v-flex xs12 pl-2 pr-2 pt-2 pb-2>
<v-data-table
:headers="headers"
:items="items"
:loading="loadingItem"
hide-actions
class="elevation-1"
>
<template slot="items" slot-scope="props">
<td
class="text-xs-left pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)"
>
<div
style="
display: flex;
flex-direction: column;
align-items: center;
"
>
{{ props.item.rioNumber }}
</div>
</td>
<td
class="text-xs-left pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)"
>
<div
style="
display: flex;
flex-direction: column;
align-items: center;
"
>
{{ props.item.itemCode }}
<v-chip small style="border-radius: 5px; flex-grow: 0">
{{ props.item.itemDesc }}
</v-chip>
</div>
</td>
<td
class="text-xs-center pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)"
>
{{ props.item.unitName }}
</td>
<td
class="text-xs-center pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)"
>
{{ props.item.StockQty }}
</td>
<td
class="text-xs-center pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)"
>
{{ props.item.rioDQty }}
</td>
<td
class="text-xs-center pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)"
>
<v-btn v-if="checkSelected(props.item) == false"style="min-width: 35px; height: 35px; margin: 0" small color="success" @click="addItem(props.item)"><v-icon small>check</v-icon></v-btn>
</td>
</template>
</v-data-table>
</v-flex>
</v-layout>
<v-divider></v-divider>
<v-layout row>
<v-flex xs6>
<v-pagination
style="margin-top: 10px; margin-bottom: 10px"
v-model="itemCurrentPage"
:length="itemTotalPage"
:total-visible="7"
></v-pagination>
</v-flex>
<v-flex class="pt-2 text-xs-right" xs6>
<v-btn color="primary" @click="dialogItem = false">Tutup Pilih Item</v-btn>
</v-flex>
</v-layout>
</v-card>
</div>
<v-divider></v-divider>
<v-card elevation="0" flat class=" mt-2">
<v-layout row style="max-height: 600px; overflow: auto">
<v-flex xs12 pl-2 pr-2 pt-2 pb-2>
<v-data-table
:headers="headersItems"
:items="selectedItems"
hide-actions
class="elevation-1"
>
<template slot="items" slot-scope="props">
<td
class="text-xs-left pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)"
>
<div
style="
display: flex;
flex-direction: column;
align-items: center;
"
>
{{ props.item.rioNumber }}
<!-- <span v-if="props.item.ioDetailConfirm == 'Y'">
<v-tooltip bottom>
<template v-slot:activator="{ on, attrs }">
<v-icon v-bind="attrs" v-on="on" class="ml-1" color="blue" small>check_circle</v-icon>
</template>
<span>Sudah di konfirmasi</span>
</v-tooltip>
</span> -->
</div>
</td>
<td
class="text-xs-left pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)"
>
<div
style="
display: flex;
flex-direction: column;
align-items: center;
"
>
{{ props.item.itemCode }}
<v-chip small style="border-radius: 5px; flex-grow: 0">
{{ props.item.itemDesc }}
</v-chip>
</div>
</td>
<td
class="text-xs-center pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)"
>
<p v-for="obj in props.item.ItemRequest" class="body-1 mb-0">
Batch: {{ obj.StockBatchNo }}, Jumlah: {{ obj.QtyReq }}, {{ obj.WarehouseName }}
</p>
</td>
<td
class="text-xs-center pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)"
>
{{ props.item.StockQty }}
</td>
<td
class="text-xs-center pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)"
>
{{ props.item.rioDQty }}
</td>
<td
class="text-xs-center pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)"
@blur="validateReceiveQty(props.item)"
>
{{ getRemaining(props.item) }} / {{ props.item.rioDReceiveQty }} {{ props.item.unitName }}
<p v-show="emptycheck.includes(props.item.rioDID)" style="color: red;" class="ma-0 pa-0">Jumlah melebihi request qty</p>
<p v-show="emptycheckvalue.includes(props.item.rioDID)" style="color: red;" class="ma-0 pa-0">Jumlah item harus diisi</p>
</td>
<!-- <td
class="text-xs-center pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)"
>
<v-text-field
v-model=""
type="number"
@input="validateReceiveQty(props.item)"
></v-text-field>
<p v-show="emptycheck.includes(props.item.rioDID)" style="color: red;" class="ma-0 pa-0">Jumlah melebihi request qty</p>
<p v-show="emptycheckvalue.includes(props.item.rioDID)" style="color: red;" class="ma-0 pa-0">Jumlah harus diisi</p>
</td> -->
<td
class="text-xs-center pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)"
>
<v-btn
style="min-width: 35px; height: 35px; margin: 0;"
small
color="orange" title="Pilih Batch Item"
@click="updateBatchNo(props.item)"
>
<v-icon small color="white">edit</v-icon>
</v-btn>
<v-btn style="min-width: 35px; height: 35px; margin: 0" small color="error" dark @click="deleteItem(props.item)"><v-icon small>close</v-icon></v-btn>
</td>
</template>
</v-data-table>
</v-flex>
</v-layout>
</v-card>
</v-card-text>
<v-card-actions>
<v-btn
v-if="act === 'edit'"
color="blue"
:disabled="loadingSave"
dark
@click="saveConfirm()"
>Konfirmasi</v-btn
>
<v-spacer></v-spacer>
<v-btn color="error" flat @click="closeDialogRequest()">
Tutup
</v-btn>
<v-btn
v-if="act === 'new'"
color="primary"
:disabled="loadingSave"
dark
@click="saveRequest()"
>Simpan</v-btn
>
<v-btn
v-if="act === 'edit'"
color="primary"
:disabled="loadingSave"
dark
@click="updateRequest()"
>Simpan Perubahan</v-btn
>
</v-card-actions>
</v-card>
</v-dialog>
</v-layout>
<one-dialog-batch></one-dialog-batch>
</div>
</template>
<script>
module.exports = {
name: "AddPurchaseRequestDialog",
components: {
"one-dialog-batch": httpVueLoader("./dialogBatch.vue")
},
data() {
return {
warehouseRules: [(v) => !!v || "Gudang harus diisi"],
divisionRules: [(v) => !!v || "Division harus diisi"],
validationForm: false,
headers: [
{
text: "NO. RIO",
align: "center",
sortable: false,
value: "itemName",
width: "20%",
class: "success lighten-3 white--text",
},
{
text: "ITEM",
align: "center",
sortable: false,
value: "itemName",
width: "35%",
class: "success lighten-3 white--text",
},
{
text: "SATUAN",
align: "center",
sortable: false,
value: "unitName",
width: "20%",
class: "success lighten-3 white--text",
},
{
text: "STOCK",
align: "center",
sortable: false,
value: "itemName",
width: "10%",
class: "success lighten-3 white--text",
},
{
text: "REQUEST QTY",
align: "center",
sortable: false,
value: "itemName",
width: "15%",
class: "success lighten-3 white--text",
},
{
text: "AKSI",
align: "center",
sortable: false,
value: "action",
width: "10%",
class: "success lighten-3 white--text",
},
],
headersItems: [
{
text: "NO. RIO",
align: "center",
sortable: false,
value: "action",
width: "10%",
class: "pa-2 pl-2 blue lighten-3 white--text",
},
{
text: "ITEM",
align: "center",
sortable: false,
value: "action",
width: "20%",
class: "pa-2 pl-2 blue lighten-3 white--text",
},
{
text: "ITEM GUDANG",
align: "center",
sortable: false,
value: "action",
width: "20%",
class: "pa-2 pl-2 blue lighten-3 white--text",
},
{
text: "STOCK",
align: "center",
sortable: false,
value: "action",
width: "10%",
class: "pa-2 pl-2 blue lighten-3 white--text",
},
{
text: "REQ QTY",
align: "center",
sortable: false,
value: "action",
width: "10%",
class: "pa-2 pl-2 blue lighten-3 white--text",
},
{
text: "JUMLAH (SISA REQUEST/ITEM OUT)",
align: "center",
sortable: false,
value: "action",
width: "20%",
class: "pa-2 pl-2 blue lighten-3 white--text",
},
{
text: "AKSI",
align: "center",
sortable: false,
value: "action",
width: "10%",
class: "pa-2 pl-2 blue lighten-3 white--text",
}
]
};
},
mounted() {
},
computed: {
user() {
return this.$store.state.requester.user;
},
dialogRequest: {
get() {
return this.$store.state.requester.dialogRequest;
},
set(val) {
this.$store.commit("requester/updateDialogRequest", val);
},
},
menuDateUse: {
get() {
return this.$store.state.requester.menuDateUse;
},
set(val) {
this.$store.commit("requester/updateMenuDateUse", val);
},
},
dateUseFormatted() {
return this.formatDate(this.xDateUse);
},
dDateUse: {
get() {
return this.$store.state.requester.dDateUse;
},
set(val) {
this.$store.commit("requester/updateDDateUse", val);
},
},
xDateUse: {
get() {
return this.$store.state.requester.xDateUse;
},
set(val) {
this.$store.commit("requester/updateXDateUse", val);
},
},
xNote: {
get() {
return this.$store.state.requester.xNote;
},
set(val) {
this.$store.commit("requester/updateXNote", val);
},
},
xWarehouse: {
get() {
return this.$store.state.requester.xWarehouse;
},
set(val) {
this.$store.commit("requester/updateXWarehouse", val);
this.$store.dispatch("requester/getItemRequest", {
search: this.searchItem,
warehouseID: this.xWarehouse.WarehouseID ? this.xWarehouse.WarehouseID : this.xWarehouse,
divisionID: this.selectedDivision.DivisionID ? this.selectedDivision.DivisionID : this.selectedDivision
});
},
},
xDepartment: {
get() {
return this.$store.state.requester.xDepartment;
},
set(val) {
this.$store.commit("requester/updateXDepartment", val);
},
},
warehouseOptions() {
return this.$store.state.requester.warehouseOptions;
},
departmentOptions() {
return this.$store.state.requester.departmentOptions;
},
regionalOptions() {
return this.$store.state.requester.regionalOptions;
},
branchOptions() {
return this.$store.state.requester.branchOptions;
},
xTotalPrice: {
get() {
return this.$store.state.requester.xTotalPrice;
},
set(val) {
this.$store.commit("requester/updateXTotalPrice", val);
},
},
xIOID() {
return this.$store.state.requester.xIOID;
},
act() {
return this.$store.state.requester.act;
},
divisionOptions() {
return this.$store.state.requester.divisionOptions;
},
selectedDivision: {
get() {
return this.$store.state.requester.selectedDivision;
},
set(val) {
this.$store.commit("requester/updateSelectedDivision", val);
this.$store.dispatch("requester/getItemRequest", {
search: this.searchItem,
warehouseID: this.xWarehouse.WarehouseID ? this.xWarehouse.WarehouseID : this.xWarehouse,
divisionID: this.selectedDivision.DivisionID ? this.selectedDivision.DivisionID : this.selectedDivision
});
},
},
dialogItem: {
get() {
return this.$store.state.requester.dialogItem;
},
set(val) {
this.$store.commit("requester/updateDialogItem", val);
},
},
searchItem: {
get() {
return this.$store.state.requester.searchItem;
},
set(val) {
this.$store.commit("requester/updateSearchItem", val);
},
},
loadingItem: {
get() {
return this.$store.state.requester.loadingItem;
},
set(val) {
this.$store.commit("requester/updateLoadingItem", val);
},
},
items() {
return this.$store.state.requester.items
},
itemTotalPage: {
get() {
return this.$store.state.requester.itemTotalPage;
},
set(val) {
this.$store.commit("requester/updateItemTotalPage", val);
},
},
itemCurrentPage: {
get() {
return this.$store.state.requester.itemCurrentPage;
},
set(val) {
this.$store.commit("requester/updateItemCurrentPage", val);
this.$store.dispatch("requester/getItemRequest", {
search: this.searchItem,
warehouseID: this.xWarehouse.WarehouseID ? this.xWarehouse.WarehouseID : "",
divisionID: this.selectedDivision.DivisionID ? this.selectedDivision.DivisionID : ""
});
},
},
selectedItems: {
get() {
return this.$store.state.requester.selectedItems;
},
set(val) {
this.$store.commit("requester/updateSelectedItems", val);
}
},
loadingSave: {
get() {
return this.$store.state.requester.loadingSave;
},
set(val) {
this.$store.commit("requester/updateLoadingSave", val);
}
},
emptycheck: {
get() {
return this.$store.state.requester.emptycheck;
},
set(val) {
this.$store.commit("requester/updateEmptycheck", val);
}
},
emptycheckvalue: {
get() {
return this.$store.state.requester.emptycheckvalue;
},
set(val) {
this.$store.commit("requester/updateEmptycheckvalue", val);
}
},
},
methods: {
isSelected(p) {
return (
p.rioDID ==
this.$store.state.requester.selectedItem
.rioDID
);
},
selectMe(sc) {
this.$store.commit("requester/updateSelectedItem", sc);
},
formatDate(date) {
if (!date) return null;
const [year, month, day] = date.split("-");
return `${day}-${month}-${year}`;
},
deFormatedDate(date) {
if (!date) return null;
const [day, month, year] = date.split("-");
return `${year}-${month.padStart(2, "0")}-${day.padStart(2, "0")}`;
},
closeDialogRequest() {
this.$store.commit("requester/updateEmptycheck", []);
this.$store.commit("requester/updateEmptycheckvalue", []);
this.$store.commit(
"requester/updateXDateUse",
moment(new Date()).format("YYYY-MM-DD")
);
this.$store.commit("requester/updateXWarehouse", "");
this.$store.commit("requester/updateXDepartment", "");
this.$refs.formRequest.resetValidation();
this.$store.commit("requester/updateDialogRequest", false);
this.$store.commit("requester/updateTempBatchNumber", {
records: [],
total: 0
});
},
saveRequest() {
let empty = [];
let emptycheckvalue = [];
let tempSelectedItems = this.selectedItems;
if (tempSelectedItems.length == 0) {
this.$store.commit("requester/updateErrMessage", `[Error] data item belum dipilih`);
this.$store.commit("requester/updateAlertError", true);
return;
}
tempSelectedItems.forEach(e => {
let totalRequestQty = parseInt(e.rioDQty) || 0;
// let alreadyReceivedQty = parseInt(e.rioDReceiveQtyBeforeEdit) || 0;
let currentInputQty = parseInt(e.rioDReceiveQty) || 0;
// let remainingQty = totalRequestQty - alreadyReceivedQty; // sisa yg boleh diinput
// Kalau input user lebih besar dari sisa yang seharusnya
if (currentInputQty > totalRequestQty) {
empty.push(e.rioDID);
return;
}
// Kalau input user kosong atau 0
if (currentInputQty <= 0) {
emptycheckvalue.push(e.rioDID);
return;
}
});
if (empty.length === 0 && emptycheckvalue.length === 0) {
this.emptycheck = empty;
this.emptycheckvalue = emptycheckvalue;
this.$store.commit("requester/updateLoadingSave", true);
let prm = {
date: this.xDateUse,
note: this.xNote,
warehouseID: this.xWarehouse.WarehouseID ? this.xWarehouse.WarehouseID : this.xWarehouse,
divisionID: this.selectedDivision.DivisionID ? this.selectedDivision.DivisionID : this.selectedDivision,
items: this.selectedItems
};
// console.log('prm', prm)
this.$store.dispatch("requester/saveRequest", prm);
} else {
this.emptycheck = empty;
this.emptycheckvalue = emptycheckvalue;
}
},
updateRequest() {
let empty = [];
let emptycheckvalue = [];
let tempSelectedItems = this.selectedItems;
if (tempSelectedItems.length == 0) {
this.$store.commit("requester/updateErrMessage", `[Error] data item belum dipilih`);
this.$store.commit("requester/updateAlertError", true);
return;
}
// Mengecek jika jumlah yang diterima tidak melebihi jumlah yang diminta dan jika jumlah yang diterima adalah 0
tempSelectedItems.forEach(e => {
let qty = parseInt(e.rioDQty); // Jumlah yang diminta
let qtyReceive = parseInt(e.rioDReceiveQty); // Jumlah yang diterima
if (qtyReceive > qty) {
empty.push(e.rioDID); // Menandai item jika qtyReceive melebihi qty yang diminta
return;
}
if (qtyReceive === 0) {
emptycheckvalue.push(e.rioDID); // Menandai item jika qtyReceive adalah 0
return;
}
});
// Jika tidak ada item yang memiliki masalah pada qtyReceive
if (empty.length === 0 && emptycheckvalue.length === 0) {
this.emptycheck = empty; // Menyimpan item yang qtyReceive-nya melebihi qty
this.emptycheckvalue = emptycheckvalue; // Menyimpan item yang qtyReceive-nya 0
this.$store.commit("requester/updateLoadingSave", true);
let prm = {
date: this.xDateUse,
note: this.xNote,
warehouseID: this.xWarehouse.WarehouseID ? this.xWarehouse.WarehouseID : this.xWarehouse,
divisionID: this.selectedDivision.DivisionID ? this.selectedDivision.DivisionID : this.selectedDivision,
IOID: this.xIOID,
items: this.selectedItems
};
// console.log(prm);
this.$store.dispatch("requester/updateRequest", prm);
} else {
this.emptycheck = empty;
this.emptycheckvalue = emptycheckvalue;
}
},
saveConfirm() {
this.$store.commit("requester/updateLoadingSave", true);
let prm = {
ioID: this.xIOID,
}
this.$store.dispatch("requester/confirmIO", prm);
},
itemSearch() {
this.$store.dispatch("requester/getItemRequest", {
search: this.searchItem,
warehouseID: this.xWarehouse.WarehouseID ? this.xWarehouse.WarehouseID : "",
divisionID: this.selectedDivision
});
},
checkSelected(item) {
let selectedItems = this.selectedItems;
let rtn = false
if(selectedItems.length == 0) {
// console.log(item.rioDID,"selectedItems.length == 0");
rtn = false;
}
selectedItems.forEach(itemloop => {
if(itemloop.rioDID == item.rioDID) {
// console.log(item.rioDID,"itemloop.rioDID == item.rioDID");
rtn = true;
}
});
// console.log(item.rioDID,"return false");
return rtn;
},
addItem(item) {
let selectedItems = this.selectedItems;
let index = selectedItems.findIndex(itemloop => itemloop.rioDID == item.rioDID);
if(index == -1) {
item.rioDReceiveQtyBeforeEdit = parseInt(item.rioDReceiveQty) || 0;
selectedItems.push(item);
}
this.$store.commit("requester/updateSelectedItems", selectedItems);
},
deleteItem(item) {
let selectedItems = this.selectedItems;
let index = selectedItems.findIndex(itemloop => itemloop.rioDID == item.rioDID);
if (index != -1) {
selectedItems.splice(index, 1);
}
// Reset receiveQty ke nilai awal sebelum edit
// item.rioDReceiveQty = item.rioDReceiveQtyBeforeEdit || 0;
// Bersihkan warning
this.emptycheck = this.emptycheck.filter(id => id !== item.rioDID);
this.emptycheckvalue = this.emptycheckvalue.filter(id => id !== item.rioDID);
// Commit perubahan
this.$store.commit("requester/updateSelectedItems", selectedItems);
},
validateReceiveQtyolds(item) {
let totalRequestQty = parseInt(item.rioDQty) || 0;
let alreadyReceivedQty = parseInt(item.rioDReceiveQtyBeforeEdit) || 0;
let inputReceiveQty = parseInt(item.rioDReceiveQty) || 0;
// Hitung jumlah kumulatif
// let cumulativeReceiveQty = alreadyReceivedQty + inputReceiveQty;
if (inputReceiveQty > totalRequestQty) {
// let allowedQty = totalRequestQty - alreadyReceivedQty; // Sisa yang boleh diterima
// item.rioDReceiveQty = allowedQty; // Set input sesuai maksimal sisa
if (!this.emptycheck.includes(item.rioDID)) {
this.emptycheck.push(item.rioDID);
}
} else {
this.emptycheck = this.emptycheck.filter(id => id !== item.rioDID);
}
// Kalau kosong atau 0, kasih warning juga
if (inputReceiveQty <= 0) {
if (!this.emptycheckvalue.includes(item.rioDID)) {
this.emptycheckvalue.push(item.rioDID);
}
} else {
this.emptycheckvalue = this.emptycheckvalue.filter(id => id !== item.rioDID);
}
},
getRemaining(item) {
const totalRequestQty = parseInt(item.rioDQty) || 0;
const alreadyReceivedQty = parseInt(item.rioDReceiveQtyBeforeEdit) || 0;
const currentInputQty = parseInt(item.rioDReceiveQty) || 0;
return totalRequestQty - currentInputQty;
},
updateBatchNo(val) {
let params = {
itemid: val.rioDItemID,
unitid: val.rioDItemUnitID,
batchno: ""
}
this.$store.commit("requester/update_dialog_batchitem", true);
this.$store.commit("requester/update_buffer_detailitem", val);
this.$store.dispatch("requester/getBatchItemDetail", params);
if (val.ItemRequest.length > 0) {
this.$store.commit("requester/update_form_batchitem", val.ItemRequest)
}
}
},
watch: {
}
};
</script>

View File

@@ -0,0 +1,307 @@
<template>
<div>
<v-dialog v-model="dialog_batchitem" persistent width="30vw">
<v-card>
<v-card-title class="headline grey lighten-2" primary-title>
Pengeluaran Item
</v-card-title>
<v-card-text>
<v-layout row wrap>
<v-flex xs12 class="mb-2">
<v-autocomplete
v-model="form_batchitem" multiple label="Pilih Batch Item" item-text="StockBatchNo"
chips outline return-object :items="list_batchitemform.records" hide-details
>
<template v-slot:selection="data">
<v-chip
:selected="data.selected"
close class="chip--select-multi"
@input="removeChips(data.item)"
>
{{ data.item.StockBatchNo }}
</v-chip>
</template>
<template v-slot:item="data">
<v-list-tile-content>
<v-list-tile-title>
Batch {{ data.item.StockBatchNo }}
</v-list-tile-title>
<v-list-tile-sub-title>
Expired: {{ data.item.StockED }}
</v-list-tile-sub-title>
</v-list-tile-content>
</template>
</v-autocomplete>
</v-flex>
<v-flex xs12 v-for="(item, index) in form_batchitem" :key="item.StockStockNumber" class="mt-2">
<v-layout row wrap>
<v-flex xs6 class="pr-2">
<p class="body-2 mb-0">Nomor batch: {{ item.StockBatchNo }}</p>
<p class="body-2 mb-0">Expired: {{ item.StockED }}</p>
<p class="body-2 mb-0">{{ item.WarehouseName }}</p>
</v-flex>
<v-flex xs3 class="pr-1">
<p class="body-2 mb-0">Stock:</p>
<p class="body-2 mb-0">{{ item.StockQty }} {{ item.ItemUnitName }}</p>
</v-flex>
<v-flex xs3 class="pl-1">
<p class="text-xs-center">Isi Qty: </p>
<v-text-field
single-line
type="number" min="0" step="1"
label="Jumlah" v-model="item.QtyReq"
outline hide-details
></v-text-field>
</v-flex>
</v-layout>
<v-divider v-if="index + 1 < form_batchitem.length" :key="`divider-${index}`" class="mt-2"></v-divider>
</v-flex>
</v-layout>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="error" @click="batalItem()">BATAL</v-btn>
<v-btn color="primary" @click="simpanItem()">SIMPAN</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</div>
</template>
<script>
module.exports = {
components: {},
mounted() {},
data() {
return {
}
},
computed: {
dialog_batchitem: {
get() {
return this.$store.state.requester.dialog_batchitem
},
set(val) {
this.$store.commit("requester/update_dialog_batchitem", val)
}
},
buffer_detailitem: {
get() {
return this.$store.state.requester.buffer_detailitem
},
set(val) {
this.$store.commit("requester/update_buffer_detailitem", val)
}
},
list_batchitemform: {
get() {
return this.$store.state.requester.list_batchitemform
},
set(val) {
this.$store.commit("requester/update_list_batchitemform", val)
}
},
form_batchitem: {
get() {
return this.$store.state.requester.form_batchitem
},
set(val) {
this.$store.commit("requester/update_form_batchitem", val)
}
},
selectedItems: {
get() {
return this.$store.state.requester.selectedItems;
},
set(val) {
this.$store.commit("requester/updateSelectedItems", val);
}
},
emptycheck: {
get() {
return this.$store.state.requester.emptycheck;
},
set(val) {
this.$store.commit("requester/updateEmptycheck", val);
}
},
},
methods: {
batalItem() {
this.buffer_detailitem = {}
this.list_batchitemform = {}
this.form_batchitem = []
this.dialog_batchitem = false
},
simpanItem_old() {
let current_detail = this.selectedItems
let current_item = this.buffer_detailitem
let new_batchitem = this.form_batchitem
let qty = 0
let isError = false
new_batchitem.forEach(element => {
let req = Number(element.QtyReq)
let stock = Number(element.StockQty)
if (!req || req <= 0 || req > stock) {
isError = true
this.$store.commit("requester/updateErrMessage", `[Error] jumlah tidak boleh <0 atau melebihi stock (${stock})`);
this.$store.commit("requester/updateAlertError", true);
return
}
qty = qty + req
});
if (isError) {
return
}
current_detail.forEach(element => {
if (element.rioDID == current_item.rioDID) {
element.ItemRequest = new_batchitem
element.QtyFilled = qty
element.rioDReceiveQty = qty
}
});
this.selectedItems = current_detail
this.form_batchitem = []
this.list_batchitemform = {}
this.buffer_detailitem = {}
this.dialog_batchitem = false
// validasi qty receive jika melebihi qty request
this.validateReceiveQty(current_item)
},
simpanItem(){
let current_detail = this.selectedItems
let current_item = this.buffer_detailitem
let new_batchitem = this.form_batchitem
// console.log('before current_detail', current_detail)
// console.log('current_item', current_item)
// console.log('new_batchitem', new_batchitem)
let qty = 0
let isError = false
// Validasi terlebih dahulu
new_batchitem.forEach(element => {
let req = Number(element.QtyReq)
let stock = Number(element.StockQty)
if (!req || req <= 0 || req > stock) {
isError = true
this.$store.commit("requester/updateErrMessage", `[Error] jumlah tidak boleh <0 atau melebihi stock (${stock})`);
this.$store.commit("requester/updateAlertError", true);
return
}
qty = qty + req
});
if (isError) {
return
}
// Update StockQty di list_batchitemform berdasarkan BatchNo
if (this.list_batchitemform && this.list_batchitemform.records) {
let updatedBatchRecords = [...this.list_batchitemform.records];
new_batchitem.forEach(batchItem => {
// Cari record yang sesuai berdasarkan StockID atau BatchNo
let recordIndex = updatedBatchRecords.findIndex(record =>
record.StockBatchNo === batchItem.StockBatchNo &&
record.StockItemID === batchItem.StockItemID &&
record.StockItemUnitID === batchItem.StockItemUnitID
);
if (recordIndex !== -1) {
// Kurangi StockQty dengan QtyReq
let currentStock = Number(updatedBatchRecords[recordIndex].StockQty);
let qtyReq = Number(batchItem.QtyReq);
let newStock = currentStock - qtyReq;
// Update StockQty
updatedBatchRecords[recordIndex].StockQty = String(newStock);
// Atau hapus record jika StockQty menjadi 0
// if (newStock <= 0) {
// updatedBatchRecords.splice(recordIndex, 1);
// updatedBatchRecords.total = updatedBatchRecords.length;
// }
}
});
let tempBatch = {
records: updatedBatchRecords,
total: updatedBatchRecords.length
};
this.$store.commit("requester/updateTempBatchNumber", tempBatch)
}
// Update current_detail dengan ItemRequest baru
current_detail.forEach(element => {
if (element.rioDID == current_item.rioDID) {
// Jika sudah ada ItemRequest sebelumnya, gabungkan dengan yang baru
if (element.ItemRequest && element.ItemRequest.length > 0) {
// Merge atau update ItemRequest yang sudah ada
new_batchitem.forEach(newItem => {
let existingIndex = element.ItemRequest.findIndex(existing =>
existing.StockBatchNo === newItem.StockBatchNo
);
if (existingIndex !== -1) {
// Update QtyReq jika batch yang sama sudah ada
let existingQty = Number(element.ItemRequest[existingIndex].QtyReq);
let newQty = Number(newItem.QtyReq);
element.ItemRequest[existingIndex].QtyReq = String(existingQty + newQty);
} else {
// Tambahkan batch baru
element.ItemRequest.push(newItem);
}
});
} else {
// Jika belum ada ItemRequest, set yang baru
element.ItemRequest = new_batchitem;
}
element.QtyFilled = qty;
element.rioDReceiveQty = qty;
}
});
this.selectedItems = current_detail
this.form_batchitem = []
// this.list_batchitemform = {}
this.buffer_detailitem = {}
this.dialog_batchitem = false
// console.log('after current_detail', current_detail)
// validasi qty receive jika melebihi qty request
this.validateReceiveQty(current_item)
},
removeChips(data) {
let tempo = this.form_batchitem.filter(item => item.StockBatchNo !== data.StockBatchNo)
this.form_batchitem = tempo
},
validateReceiveQty(item) {
let totalRequestQty = parseInt(item.rioDQty) || 0;
let inputReceiveQty = parseInt(item.rioDReceiveQty) || 0;
if (inputReceiveQty > totalRequestQty) {
if (!this.emptycheck.includes(item.rioDID)) {
this.emptycheck.push(item.rioDID);
}
} else {
this.emptycheck = this.emptycheck.filter(id => id !== item.rioDID);
}
},
},
}
</script>

View File

@@ -0,0 +1,288 @@
<template>
<v-layout row justify-center>
<v-dialog v-model="dialogApprove" persistent max-width="75%">
<v-card>
<v-card-title class="headline grey lighten-2" primary-title>
APPROVE
</v-card-title>
<v-card-text class="pt-2 pb-0">
<v-layout row wrap>
<v-flex xs2>
Nomor
</v-flex>
<v-flex xs10>
: {{ selectedMainTable.T_ItemOutNumber }}
</v-flex>
</v-layout>
<v-layout row wrap>
<v-flex xs2>
Tanggal Transaksi
</v-flex>
<v-flex xs10>
: {{ deFormatedDate(selectedMainTable.T_ItemOutDate) }}
</v-flex>
</v-layout>
<v-layout row wrap>
<v-flex xs2>
Gudang
</v-flex>
<v-flex xs10>
: {{ selectedMainTable.WarehouseName }}
</v-flex>
</v-layout>
<v-layout row wrap>
<v-flex xs2>
Divisi
</v-flex>
<v-flex xs10>
: {{ selectedMainTable.DivisionName }}
</v-flex>
</v-layout>
<v-layout row wrap>
<v-flex xs2>
Status
</v-flex>
<v-flex xs10>
: {{ selectedMainTable.T_ItemOutStatus }}
</v-flex>
</v-layout>
<v-layout row wrap>
<v-flex xs2>
Catatan
</v-flex>
<v-flex xs10>
: {{ selectedMainTable.T_ItemOutNote }}
</v-flex>
</v-layout>
<v-card flat class=" mt-2">
<v-layout row style="max-height: 600px; overflow: auto">
<v-flex xs12 pl-2 pr-2 pt-2 pb-2>
<v-data-table
:headers="headersItems"
:items="detailItemouts"
hide-actions
class="elevation-1"
>
<template slot="items" slot-scope="props">
<td
class="text-xs-left pa-2"
>
<div
style="
display: flex;
flex-direction: column;
align-items: center;
"
>
{{ props.item.T_ItemOutNumber }}
</div>
</td>
<td
class="text-xs-left pa-2"
>
<div
style="
display: flex;
flex-direction: column;
align-items: center;
"
>
<v-chip small style="border-radius: 5px; flex-grow: 0">
{{ props.item.M_ItemDesc }}
</v-chip>
</div>
</td>
<td
class="text-xs-center pa-2"
>
{{ props.item.ItemUnitName }}
</td>
<td
class="text-xs-center pa-2"
>
{{ props.item.StockQty }}
</td>
<td
class="text-xs-center pa-2"
>
{{ props.item.RequestItemOutDetailQty }}
</td>
<td
class="text-xs-center pa-2"
>
{{ props.item.remainingRequestQty }}
</td>
<td
class="text-xs-center pa-2"
>
{{ props.item.T_ItemOutDetailQty }}
</td>
</template>
</v-data-table>
</v-flex>
</v-layout>
</v-card>
</v-card-text>
<v-card-actions>
<!-- <v-btn
color="red"
:disabled="loadingSave"
dark
@click="saveReject()"
>Reject</v-btn
> -->
<v-spacer></v-spacer>
<v-btn color="error" flat @click="closeDialogApprove()">
Tutup
</v-btn>
<v-btn
color="green"
:disabled="loadingSave"
dark
@click="saveApprove()"
>Approve</v-btn
>
</v-card-actions>
</v-card>
</v-dialog>
</v-layout>
</template>
<script>
module.exports = {
name: "AddPurchaseRequestDialog",
data() {
return {
headersItems: [
{
text: "NO",
align: "center",
sortable: false,
value: "action",
width: "15%",
class: "pa-2 pl-2 blue lighten-3 white--text",
},
{
text: "ITEM",
align: "center",
sortable: false,
value: "action",
width: "25%",
class: "pa-2 pl-2 blue lighten-3 white--text",
},
{
text: "SATUAN",
align: "center",
sortable: false,
value: "action",
width: "20%",
class: "pa-2 pl-2 blue lighten-3 white--text",
},
{
text: "STOCK",
align: "center",
sortable: false,
value: "action",
width: "10%",
class: "pa-2 pl-2 blue lighten-3 white--text",
},
{
text: "REQUEST QTY",
align: "center",
sortable: false,
value: "action",
width: "10%",
class: "pa-2 pl-2 blue lighten-3 white--text",
},
{
text: "SISA REQUEST",
align: "center",
sortable: false,
value: "action",
width: "10%",
class: "pa-2 pl-2 blue lighten-3 white--text",
},
{
text: "ITEM OUT",
align: "center",
sortable: false,
value: "action",
width: "10%",
class: "pa-2 pl-2 blue lighten-3 white--text",
}
]
};
},
mounted() {
},
computed: {
dialogApprove: {
get() {
return this.$store.state.requester.dialogApprove;
},
set(val) {
this.$store.commit("requester/updateDialogApprove", val);
},
},
selectedMainTable: {
get() {
return this.$store.state.requester.selectedMainTable;
},
set(val) {
this.$store.commit("requester/updateSelectedMainTable", val);
},
},
loadingSave: {
get() {
return this.$store.state.requester.loadingSave;
},
set(val) {
this.$store.commit("requester/updateLoadingSave", val);
},
},
detailItemouts() {
return this.$store.state.requester.detailItemouts;
}
},
methods: {
deFormatedDate(date) {
if (!date) return null;
const [day, month, year] = date.split("-");
return `${year}-${month.padStart(2, "0")}-${day.padStart(2, "0")}`;
},
closeDialogApprove() {
this.$store.commit("requester/updateDialogApprove", false);
},
saveApprove() {
this.$store.commit("requester/updateLoadingSave", true);
let prm = {
ioID: this.$store.state.requester.xIOID
}
// console.log(prm)
this.$store.dispatch("requester/approveIO", prm);
},
saveReject() {
this.$store.commit("requester/updateLoadingSave", true);
let prm = {
IOID: this.$store.state.requester.xIOID,
}
// console.log(prm)
this.$store.dispatch("requester/rejectRequest", prm);
}
},
watch: {
}
};
</script>

View File

@@ -0,0 +1,272 @@
<template>
<v-layout row justify-center>
<v-dialog v-model="dialogConfirm" persistent max-width="75%">
<v-card>
<v-card-title class="headline grey lighten-2" primary-title>
KONFIRMASI
</v-card-title>
<v-card-text class="pt-2 pb-0">
<v-layout row wrap>
<v-flex xs2>
Nomor
</v-flex>
<v-flex xs10>
: {{ selectedMainTable.T_ItemOutNumber }}
</v-flex>
</v-layout>
<v-layout row wrap>
<v-flex xs2>
Tanggal Transaksi
</v-flex>
<v-flex xs10>
: {{ deFormatedDate(selectedMainTable.T_ItemOutDate) }}
</v-flex>
</v-layout>
<v-layout row wrap>
<v-flex xs2>
Gudang
</v-flex>
<v-flex xs10>
: {{ selectedMainTable.WarehouseName }}
</v-flex>
</v-layout>
<v-layout row wrap>
<v-flex xs2>
Divisi
</v-flex>
<v-flex xs10>
: {{ selectedMainTable.DivisionName }}
</v-flex>
</v-layout>
<v-layout row wrap>
<v-flex xs2>
Status
</v-flex>
<v-flex xs10>
: {{ selectedMainTable.T_ItemOutStatus }}
</v-flex>
</v-layout>
<v-layout row wrap>
<v-flex xs2>
Catatan
</v-flex>
<v-flex xs10>
: {{ selectedMainTable.T_ItemOutNote }}
</v-flex>
</v-layout>
<v-card flat class=" mt-2">
<v-layout row style="max-height: 600px; overflow: auto">
<v-flex xs12 pl-2 pr-2 pt-2 pb-2>
<v-data-table
:headers="headersItems"
:items="detailItemouts"
hide-actions
class="elevation-1"
>
<template slot="items" slot-scope="props">
<td
class="text-xs-left pa-2"
>
<div
style="
display: flex;
flex-direction: column;
align-items: center;
"
>
{{ props.item.T_ItemOutNumber }}
</div>
</td>
<td
class="text-xs-left pa-2"
>
<div
style="
display: flex;
flex-direction: column;
align-items: center;
"
>
<v-chip small style="border-radius: 5px; flex-grow: 0">
{{ props.item.M_ItemDesc }}
</v-chip>
</div>
</td>
<td
class="text-xs-center pa-2"
>
{{ props.item.ItemUnitName }}
</td>
<td
class="text-xs-center pa-2"
>
{{ props.item.StockQty }}
</td>
<td
class="text-xs-center pa-2"
>
{{ props.item.RequestItemOutDetailQty }}
</td>
<td
class="text-xs-center pa-2"
>
{{ props.item.remainingRequestQty }}
</td>
<td
class="text-xs-center pa-2"
>
{{ props.item.T_ItemOutDetailQty }}
</td>
</template>
</v-data-table>
</v-flex>
</v-layout>
</v-card>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="error" flat @click="closeDialogConfirm()">
Tutup
</v-btn>
<v-btn
color="blue"
:disabled="loadingSave"
dark
@click="saveConfirm()"
>Konfirmasi</v-btn
>
</v-card-actions>
</v-card>
</v-dialog>
</v-layout>
</template>
<script>
module.exports = {
name: "AddPurchaseRequestDialog",
data() {
return {
headersItems: [
{
text: "NO",
align: "center",
sortable: false,
value: "action",
width: "15%",
class: "pa-2 pl-2 blue lighten-3 white--text",
},
{
text: "ITEM",
align: "center",
sortable: false,
value: "action",
width: "25%",
class: "pa-2 pl-2 blue lighten-3 white--text",
},
{
text: "SATUAN",
align: "center",
sortable: false,
value: "action",
width: "20%",
class: "pa-2 pl-2 blue lighten-3 white--text",
},
{
text: "STOCK",
align: "center",
sortable: false,
value: "action",
width: "10%",
class: "pa-2 pl-2 blue lighten-3 white--text",
},
{
text: "REQUEST QTY",
align: "center",
sortable: false,
value: "action",
width: "10%",
class: "pa-2 pl-2 blue lighten-3 white--text",
},
{
text: "SISA REQUEST",
align: "center",
sortable: false,
value: "action",
width: "10%",
class: "pa-2 pl-2 blue lighten-3 white--text",
},
{
text: "ITEM OUT",
align: "center",
sortable: false,
value: "action",
width: "10%",
class: "pa-2 pl-2 blue lighten-3 white--text",
}
]
};
},
mounted() {
},
computed: {
dialogConfirm: {
get() {
return this.$store.state.requester.dialogConfirm;
},
set(val) {
this.$store.commit("requester/updateDialogConfirm", val);
},
},
selectedMainTable: {
get() {
return this.$store.state.requester.selectedMainTable;
},
set(val) {
this.$store.commit("requester/updateSelectedMainTable", val);
},
},
loadingSave: {
get() {
return this.$store.state.requester.loadingSave;
},
set(val) {
this.$store.commit("requester/updateLoadingSave", val);
},
},
detailItemouts() {
return this.$store.state.requester.detailItemouts;
}
},
methods: {
deFormatedDate(date) {
if (!date) return null;
const [day, month, year] = date.split("-");
return `${year}-${month.padStart(2, "0")}-${day.padStart(2, "0")}`;
},
closeDialogConfirm() {
this.$store.commit("requester/updateDialogConfirm", false);
},
saveConfirm() {
this.$store.commit("requester/updateLoadingSave", true);
let prm = {
ioID: this.$store.state.requester.xIOID,
}
this.$store.dispatch("requester/confirmIO", prm);
},
},
watch: {
}
};
</script>

View File

@@ -0,0 +1,237 @@
<template>
<v-layout row justify-center>
<v-dialog v-model="dialogPreview" persistent max-width="75%">
<v-card>
<v-card-title class="headline grey lighten-2" primary-title>
PREVIEW
</v-card-title>
<v-card-text class="pt-2 pb-0">
<v-layout row wrap>
<v-flex xs2>
Nomor
</v-flex>
<v-flex xs10>
: {{ selectedMainTable.T_ItemOutNumber }}
</v-flex>
</v-layout>
<v-layout row wrap>
<v-flex xs2>
Tanggal Transaksi
</v-flex>
<v-flex xs10>
: {{ deFormatedDate(selectedMainTable.T_ItemOutDate) }}
</v-flex>
</v-layout>
<v-layout row wrap>
<v-flex xs2>
Gudang
</v-flex>
<v-flex xs10>
: {{ selectedMainTable.WarehouseName }}
</v-flex>
</v-layout>
<v-layout row wrap>
<v-flex xs2>
Divisi
</v-flex>
<v-flex xs10>
: {{ selectedMainTable.DivisionName }}
</v-flex>
</v-layout>
<v-layout row wrap>
<v-flex xs2>
Status
</v-flex>
<v-flex xs10>
: {{ selectedMainTable.T_ItemOutStatus }}
</v-flex>
</v-layout>
<v-layout row wrap>
<v-flex xs2>
Catatan
</v-flex>
<v-flex xs10>
: {{ selectedMainTable.T_ItemOutNote }}
</v-flex>
</v-layout>
<v-card flat class=" mt-2">
<v-layout row style="max-height: 600px; overflow: auto">
<v-flex xs12 pl-2 pr-2 pt-2 pb-2>
<v-data-table
:headers="headersItems"
:items="detailItemouts"
hide-actions
class="elevation-1"
>
<template slot="items" slot-scope="props">
<td
class="text-xs-left pa-2"
>
<div
style="
display: flex;
flex-direction: column;
align-items: center;
"
>
{{ props.item.T_ItemOutNumber }}
</div>
</td>
<td
class="text-xs-left pa-2"
>
<div
style="
display: flex;
flex-direction: column;
align-items: center;
"
>
<v-chip small style="border-radius: 5px; flex-grow: 0">
{{ props.item.M_ItemDesc }}
</v-chip>
</div>
</td>
<td
class="text-xs-center pa-2"
>
{{ props.item.ItemUnitName }}
</td>
<td
class="text-xs-center pa-2"
>
{{ props.item.StockQty }}
</td>
<td
class="text-xs-center pa-2"
>
{{ props.item.RequestItemOutDetailQty }}
</td>
<td
class="text-xs-center pa-2"
>
{{ props.item.T_ItemOutDetailQty }}
</td>
</template>
</v-data-table>
</v-flex>
</v-layout>
</v-card>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="error" flat @click="closeDialogPreview()">
Tutup
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-layout>
</template>
<script>
module.exports = {
name: "AddPurchaseRequestDialog",
data() {
return {
headersItems: [
{
text: "NO",
align: "center",
sortable: false,
value: "action",
width: "15%",
class: "pa-2 pl-2 blue lighten-3 white--text",
},
{
text: "ITEM",
align: "center",
sortable: false,
value: "action",
width: "30%",
class: "pa-2 pl-2 blue lighten-3 white--text",
},
{
text: "SATUAN",
align: "center",
sortable: false,
value: "action",
width: "25%",
class: "pa-2 pl-2 blue lighten-3 white--text",
},
{
text: "STOCK",
align: "center",
sortable: false,
value: "action",
width: "10%",
class: "pa-2 pl-2 blue lighten-3 white--text",
},
{
text: "REQUEST QTY",
align: "center",
sortable: false,
value: "action",
width: "10%",
class: "pa-2 pl-2 blue lighten-3 white--text",
},
{
text: "ITEM OUT",
align: "center",
sortable: false,
value: "action",
width: "10%",
class: "pa-2 pl-2 blue lighten-3 white--text",
}
]
};
},
mounted() {
},
computed: {
dialogPreview: {
get() {
return this.$store.state.requester.dialogPreview;
},
set(val) {
this.$store.commit("requester/updateDialogPreview", val);
},
},
selectedMainTable: {
get() {
return this.$store.state.requester.selectedMainTable;
},
set(val) {
this.$store.commit("requester/updateSelectedMainTable", val);
},
},
detailItemouts() {
return this.$store.state.requester.detailItemouts;
}
},
methods: {
deFormatedDate(date) {
if (!date) return null;
const [day, month, year] = date.split("-");
return `${year}-${month.padStart(2, "0")}-${day.padStart(2, "0")}`;
},
closeDialogPreview() {
this.$store.commit("requester/updateDialogPreview", false);
}
},
watch: {
}
};
</script>

View File

@@ -0,0 +1,274 @@
<template>
<v-layout row justify-center>
<v-dialog v-model="dialogProcess" persistent max-width="75%">
<v-card>
<v-card-title class="headline grey lighten-2" primary-title>
PROSES TRANSAKSI
</v-card-title>
<v-card-text class="pt-2 pb-0">
<v-layout row wrap>
<v-flex xs2>
Nomor
</v-flex>
<v-flex xs10>
: {{ selectedMainTable.T_ItemOutNumber }}
</v-flex>
</v-layout>
<v-layout row wrap>
<v-flex xs2>
Tanggal Transaksi
</v-flex>
<v-flex xs10>
: {{ deFormatedDate(selectedMainTable.T_ItemOutDate) }}
</v-flex>
</v-layout>
<v-layout row wrap>
<v-flex xs2>
Gudang
</v-flex>
<v-flex xs10>
: {{ selectedMainTable.WarehouseName }}
</v-flex>
</v-layout>
<v-layout row wrap>
<v-flex xs2>
Divisi
</v-flex>
<v-flex xs10>
: {{ selectedMainTable.DivisionName }}
</v-flex>
</v-layout>
<v-layout row wrap>
<v-flex xs2>
Status
</v-flex>
<v-flex xs10>
: {{ selectedMainTable.T_ItemOutStatus }}
</v-flex>
</v-layout>
<v-layout row wrap>
<v-flex xs2>
Catatan
</v-flex>
<v-flex xs10>
: {{ selectedMainTable.T_ItemOutNote }}
</v-flex>
</v-layout>
<v-card flat class=" mt-2">
<v-layout row style="max-height: 600px; overflow: auto">
<v-flex xs12 pl-2 pr-2 pt-2 pb-2>
<v-data-table
:headers="headersItems"
:items="detailItemouts"
hide-actions
class="elevation-1"
>
<template slot="items" slot-scope="props">
<td
class="text-xs-left pa-2"
>
<div
style="
display: flex;
flex-direction: column;
align-items: center;
"
>
{{ props.item.T_ItemOutNumber }}
</div>
</td>
<td
class="text-xs-left pa-2"
>
<div
style="
display: flex;
flex-direction: column;
align-items: center;
"
>
<v-chip small style="border-radius: 5px; flex-grow: 0">
{{ props.item.M_ItemDesc }}
</v-chip>
</div>
</td>
<td
class="text-xs-center pa-2"
>
{{ props.item.ItemUnitName }}
</td>
<td
class="text-xs-center pa-2"
>
{{ props.item.StockQty }}
</td>
<td
class="text-xs-center pa-2"
>
{{ props.item.RequestItemOutDetailQty }}
</td>
<td
class="text-xs-center pa-2"
>
{{ props.item.remainingRequestQty }}
</td>
<td
class="text-xs-center pa-2"
>
{{ props.item.T_ItemOutDetailQty }}
</td>
</template>
</v-data-table>
</v-flex>
</v-layout>
</v-card>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="error" flat @click="closeDialogProcess()">
Tutup
</v-btn>
<v-btn
color="green"
:disabled="loadingSave"
dark
@click="saveProcess()"
>Process</v-btn
>
</v-card-actions>
</v-card>
</v-dialog>
</v-layout>
</template>
<script>
module.exports = {
name: "AddPurchaseRequestDialog",
data() {
return {
headersItems: [
{
text: "NO",
align: "center",
sortable: false,
value: "action",
width: "15%",
class: "pa-2 pl-2 blue lighten-3 white--text",
},
{
text: "ITEM",
align: "center",
sortable: false,
value: "action",
width: "25%",
class: "pa-2 pl-2 blue lighten-3 white--text",
},
{
text: "SATUAN",
align: "center",
sortable: false,
value: "action",
width: "20%",
class: "pa-2 pl-2 blue lighten-3 white--text",
},
{
text: "STOCK",
align: "center",
sortable: false,
value: "action",
width: "10%",
class: "pa-2 pl-2 blue lighten-3 white--text",
},
{
text: "REQUEST QTY",
align: "center",
sortable: false,
value: "action",
width: "10%",
class: "pa-2 pl-2 blue lighten-3 white--text",
},
{
text: "SISA REQUEST",
align: "center",
sortable: false,
value: "action",
width: "10%",
class: "pa-2 pl-2 blue lighten-3 white--text",
},
{
text: "ITEM OUT",
align: "center",
sortable: false,
value: "action",
width: "10%",
class: "pa-2 pl-2 blue lighten-3 white--text",
}
]
};
},
mounted() {
},
computed: {
dialogProcess: {
get() {
return this.$store.state.requester.dialogProcess;
},
set(val) {
this.$store.commit("requester/updateDialogProcess", val);
},
},
selectedMainTable: {
get() {
return this.$store.state.requester.selectedMainTable;
},
set(val) {
this.$store.commit("requester/updateSelectedMainTable", val);
},
},
loadingSave: {
get() {
return this.$store.state.requester.loadingSave;
},
set(val) {
this.$store.commit("requester/updateLoadingSave", val);
},
},
detailItemouts() {
return this.$store.state.requester.detailItemouts;
}
},
methods: {
deFormatedDate(date) {
if (!date) return null;
const [day, month, year] = date.split("-");
return `${year}-${month.padStart(2, "0")}-${day.padStart(2, "0")}`;
},
closeDialogProcess() {
this.$store.commit("requester/updateDialogProcess", false);
},
saveProcess() {
this.$store.commit("requester/updateLoadingSave", true);
let prm = {
ioID: this.$store.state.requester.xIOID,
items: this.$store.state.requester.detailItemouts
}
// console.log(prm)
this.$store.dispatch("requester/processIO", prm);
}
},
watch: {
}
};
</script>

View File

@@ -0,0 +1,888 @@
<template>
<div style="width: 100%">
<v-snackbar
v-model="snackbar.state"
:color="snackbar.type"
:timeout="3000"
multi-line
top
>
{{ snackbar.message }}
<v-btn flat @click="snackbar.state = false">
Close
</v-btn>
</v-snackbar>
<template>
<v-dialog v-model="dialogapprove" max-width="30%">
<v-card>
<v-card-title class="headline grey lighten-2 pt-2 pb-2" primary-title>
Peringatan !
</v-card-title>
<v-card-text class="pt-2 pb-2">
<v-layout row>
<v-flex xs12 d-flex>
<v-layout row>
<v-flex pb-1 xs12>
<v-layout row>
<v-flex pt-2 pr-2 xs12>
{{ msgapprove }}
</v-flex>
</v-layout>
</v-flex>
</v-layout>
</v-flex>
</v-layout>
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="error" flat @click="dialogapprove = false">
Tutup
</v-btn>
<v-btn
color="primary"
@click="orderApprove()"
>
Ya
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<template>
<v-dialog v-model="dialogreject" max-width="30%">
<v-card>
<v-card-title class="headline grey lighten-2 pt-2 pb-2" primary-title>
Peringatan !
</v-card-title>
<v-card-text class="pt-2 pb-2">
<v-layout row>
<v-flex xs12 d-flex>
<v-layout row>
<v-flex pb-1 xs12>
<v-layout row>
<v-flex pt-2 pr-2 xs12>
{{ msgreject }}
</v-flex>
</v-layout>
</v-flex>
</v-layout>
</v-flex>
</v-layout>
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="error" flat @click="dialogreject = false">
Tutup
</v-btn>
<v-btn
color="primary"
@click="orderRejected()"
>
Ya
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<!-- ERROR DIALOG -->
<!-- <v-dialog v-model="dialog_error" max-width="500px">
<v-card>
<v-card-title>
<span>ERROR !</span>
<v-spacer></v-spacer>
</v-card-title>
<v-divider></v-divider>
<div class="ma-3 red--text">{{ msgError }}</div>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="primary" flat @click="dialog_error = false"
>Tutup</v-btn
>
</v-card-actions>
</v-card>
</v-dialog> -->
<!-- END ERROR DIALOG -->
<v-toolbar color="primary" dark>
<v-toolbar-title class="white--text"
>LISTING REQUEST PENGELUARAN BARANG</v-toolbar-title
>
</v-toolbar>
<v-card class="pa-2">
<div class="d-flex justify-start align-center" style="gap: 1rem">
<v-menu
v-model="menuStartDate"
:close-on-content-click="false"
transition="scale-transition"
:nudge-right="40"
lazy
offset-y
max-width="290px"
min-width="290px"
>
<template v-slot:activator="{ on }">
<v-text-field
v-model="startDateFormatted"
label="Tanggal Awal"
readonly
style="max-width: 250px"
outline
hide-details
v-on="on"
@blur="dStartDate = deFormatedDate(startDateFormatted)"
></v-text-field>
</template>
<v-date-picker
no-title
v-model="fStartDate"
@input="menuStartDate = false"
></v-date-picker>
</v-menu>
<v-menu
v-model="menuEndDate"
:close-on-content-click="false"
transition="scale-transition"
:nudge-right="40"
lazy
offset-y
max-width="290px"
min-width="290px"
>
<template v-slot:activator="{ on }">
<v-text-field
v-model="endDateFormatted"
label="Tanggal Akhir"
readonly
style="max-width: 250px"
outline
hide-details
v-on="on"
@blur="dEndDate = deFormatedDate(endDateFormatted)"
></v-text-field>
</template>
<v-date-picker
no-title
v-model="fEndDate"
@input="menuEndDate = false"
></v-date-picker>
</v-menu>
<v-autocomplete
v-model="fStatus"
menu-icon="mdi-chevron-down"
:items="statusOptions"
item-text="title"
return-object
label="Status"
style="max-width: 250px"
outline
hide-details
></v-autocomplete>
<v-text-field
v-model="fSearch"
label="Cari..."
placeholder="NO. RIO"
style="max-width: 250px"
outline
hide-details
></v-text-field>
<v-btn
dark
color="primary"
style="min-width: 50px; height: 50px; margin: 0"
@click="listSearch()"
>
<v-icon>search</v-icon>
</v-btn>
</div>
</v-card>
<v-card class="pa-2 mt-2">
<v-layout row style="max-height: 600px; overflow: auto">
<v-flex xs12 pl-2 pr-2 pt-2 pb-2>
<v-data-table
:headers="headers"
:items="listRequest"
:loading="loadingStatus"
hide-actions
class="elevation-1"
>
<template v-slot:headers="props">
<tr>
<th
v-for="header in props.headers" :class="header.class"
:key="header.text" :width="header.width">
{{ header.text }}
</th>
<th width="5%" class="blue lighten-3 white--text">
<v-checkbox
:loading="loadingStatus"
:input-value="headerCheckboxValueAll()"
primary hide-details
:indeterminate="headerCheckboxValuePartial()"
@click.stop="checkItemAll"
></v-checkbox>
</th>
</tr>
</template>
<template v-slot:items="props">
<td
class="text-xs-center pa-2"
>
<div
style="
display: flex;
flex-direction: column;
align-items: center;
"
>
<p class="mb-0 font-weight-bold" style="color:#000000">{{ props.item.rioNumber }}</p>
{{ deFormatedDate(props.item.rioDate) }}
</div>
</td>
<td
class="text-xs-left pa-2"
>
{{ props.item.M_ItemDesc }}
</td>
<td
class="text-xs-left pa-2"
>
{{ props.item.StockQty }}
</td>
<td
class="text-xs-left pa-2"
>
{{ props.item.rioDQty }}
</td>
<td
class="text-xs-left pa-2"
>
<v-chip
small
:text-color="
props.item.rioDStatus === 'Draft'
? 'black'
: 'white'
"
:color="
getChipStatusColor(
props.item.rioDStatus
)
"
>
{{ props.item.rioDStatus }}
</v-chip>
</td>
<td>
<span v-if="props.item.rioStatus === 'Send Request'">
<v-checkbox
:input-value="checkBoxValue(props.item)"
primary hide-details
@change="changeCheckBox(props.item)"
></v-checkbox>
</span>
</td>
<!-- <template
v-if="props.item.rioDStatus == 'Send Request'"
>
<td
class="text-xs-center pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)"
>
<v-btn
dark
v-if="requestExist(props.item)"
@click="addRequest(props.item)"
style="min-width: 25px; height: 30px"
small
color="success"
>
<v-icon small>check</v-icon>
</v-btn>
<v-btn
dark
v-if="!requestExist(props.item)"
@click="removeRequest(props.item)"
style="min-width: 25px; height: 30px"
small
color="red"
>
<v-icon small>close</v-icon>
</v-btn>
</td>
</template>
<template v-else>
<td
class="text-xs-center pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)">
</td>
</template> -->
</template>
</v-data-table>
</v-flex>
</v-layout>
<div style="width: 100%" class="d-flex justify-end">
<template
v-if="selectedItems.length > 0 &&
selectedItems.every(item => item.rioStatus === 'Send Request')"
>
<v-btn
color="red"
outline
dark
style="max-width: 200px"
class="ml-5"
:disabled="!listRequest.length"
@click="openRejected(selectedItems)
"
>
Reject
</v-btn>
</template>
<template
v-if="selectedItems.length == 0 ? false : true"
>
<v-btn
color="primary"
dark
style="max-width: 200px"
class="ml-2"
:disabled="!listRequest.length"
@click="openApprove(selectedItems)
"
>
Approve
</v-btn>
</template>
</div>
<v-divider></v-divider>
<v-pagination
style="margin-top: 10px; margin-bottom: 10px"
v-model="currentPage"
:length="totalPage"
></v-pagination>
</v-card>
<template>
<one-dialog-info :status="opendialoginfo" :msg="msginfo"
@close-dialog-info="opendialoginfo = false"></one-dialog-info>
</template>
</div>
</template>
<style scoped>
.date-type-table {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.table.v-table tbody td,
table.v-table tbody th {
height: 40px;
}
.table.v-table thead tr {
height: 40px;
}
.scroll-container {
scroll-padding: 50px 0 0 50px;
}
</style>
<script>
module.exports = {
components: {
"add-item-out-dialog": httpVueLoader(
"./addItemOutDialog.vue"
),
"add-item-detail-dialog": httpVueLoader("./addItemDetailDialog.vue"),
"one-dialog-alert": httpVueLoader("../../common/oneDialogAlert.vue"),
"one-dialog-error": httpVueLoader("../../common/oneDialogError.vue"),
"one-dialog-info": httpVueLoader("../../common/oneDialogInfo.vue"),
},
data() {
return {
msgAlertDeleteRequest: "",
dialogAlertDeleteRequest: false,
dialogAlertDeleteDetail: false,
xDescription: "",
headers: [
{
text: "NO RIO",
align: "center",
sortable: false,
value: "no",
width: "15%",
class: "blue lighten-3 white--text",
},
{
text: "ITEM",
align: "left",
sortable: false,
value: "date",
width: "35%",
class: "blue lighten-3 white--text",
},
{
text: "STOCK",
align: "left",
sortable: false,
value: "warehouse",
width: "10%",
class: "blue lighten-3 white--text",
},
{
text: "REQUEST QTY",
align: "left",
sortable: false,
value: "departement",
width: "10%",
class: "blue lighten-3 white--text",
},
{
text: "STATUS",
align: "left",
sortable: false,
value: "status",
width: "15%",
class: "blue lighten-3 white--text",
},
]
};
},
mounted() {
this.$store.dispatch("listrequest/listrequestitem");
this.$store.dispatch("listrequest/getDivisionUser");
},
computed: {
listRequest() {
return this.$store.state.listrequest.request;
},
loadingStatus() {
return this.$store.state.listrequest.loadingStatus === 1;
},
totalPage: {
get() {
return this.$store.state.listrequest.totalPage;
},
set(val) {
this.$store.commit("listrequest/update_totalPage", val);
},
},
currentPage: {
get() {
return this.$store.state.listrequest.currentPage;
},
set(val) {
this.$store.commit("listrequest/update_currentPage", val);
this.$store.commit("listrequest/update_lastId", -1);
this.$store.dispatch("listrequest/listrequestitem");
},
},
menuStartDate: {
get() {
return this.$store.state.listrequest.menuStartDate;
},
set(val) {
this.$store.commit("listrequest/update_menuStartDate", val);
},
},
menuEndDate: {
get() {
return this.$store.state.listrequest.menuEndDate;
},
set(val) {
this.$store.commit("listrequest/update_menuEndDate", val);
},
},
startDateFormatted() {
return this.formatDate(this.fStartDate);
},
endDateFormatted() {
return this.formatDate(this.fEndDate);
},
dStartDate: {
get() {
return this.$store.state.listrequest.dStartDate;
},
set(val) {
this.$store.commit("listrequest/update_dStartDate", val);
},
},
dEndDate: {
get() {
return this.$store.state.listrequest.dEndDate;
},
set(val) {
this.$store.commit("listrequest/update_dEndDate", val);
},
},
fStartDate: {
get() {
return this.$store.state.listrequest.fStartDate;
},
set(val) {
this.$store.commit("listrequest/update_fStartDate", val);
},
},
fEndDate: {
get() {
return this.$store.state.listrequest.fEndDate;
},
set(val) {
this.$store.commit("listrequest/update_fEndDate", val);
},
},
fStatus: {
get() {
return this.$store.state.listrequest.fStatus;
},
set(val) {
this.$store.commit("listrequest/update_fStatus", val);
},
},
statusOptions() {
return this.$store.state.listrequest.statusOptions;
},
fSearch: {
get() {
return this.$store.state.listrequest.fSearch;
},
set(val) {
this.$store.commit("listrequest/update_fSearch", val);
},
},
selectedRequest: {
get() {
return this.$store.state.listrequest.selectedRequest;
},
set(val) {
this.$store.commit("listrequest/update_selectedRequest", val);
},
},
selectedItems: {
get() {
return this.$store.state.listrequest.selectedItems;
},
set(val) {
this.$store.commit("listrequest/update_selectedItems", val);
},
},
opendialoginfo: {
get() {
return this.$store.state.listrequest.opendialoginfo;
},
set(val) {
this.$store.commit("listrequest/update_opendialoginfo", val);
},
},
msginfo: {
get() {
return this.$store.state.listrequest.msginfo;
},
set(val) {
this.$store.commit("listrequest/update_msginfo", val);
},
},
snackbar: {
get() {
return this.$store.state.listrequest.snackbar;
},
set(val) {
this.$store.commit("listrequest/update_snackbar", val);
},
},
dialogapprove: {
get() {
return this.$store.state.listrequest.dialogapprove;
},
set(val) {
this.$store.commit("listrequest/update_dialogapprove", val);
},
},
msgapprove: {
get() {
return this.$store.state.listrequest.msgapprove;
},
set(val) {
this.$store.commit("listrequest/update_msgapprove", val);
},
},
dialogreject: {
get() {
return this.$store.state.listrequest.dialogreject;
},
set(val) {
this.$store.commit("listrequest/update_dialogreject", val);
},
},
msgreject: {
get() {
return this.$store.state.listrequest.msgreject;
},
set(val) {
this.$store.commit("listrequest/update_msgreject", val);
},
},
approveDivisionUserID: {
get() {
return this.$store.state.listrequest.approveDivisionUserID;
},
set(val) {
this.$store.commit("listrequest/updateApproveDivisionUserID", val);
},
},
approveDivision: {
get() {
return this.$store.state.listrequest.approveDivision;
},
set(val) {
this.$store.commit("listrequest/updateApproveDivision", val);
},
}
},
methods: {
isSelected(p) {
return (
p.rioDID ==
this.$store.state.listrequest.selectedRequest
.rioDID
);
},
selectMe(spr) {
this.$store.commit("listrequest/update_selectedRequest", spr);
},
formatDate(date) {
if (!date) return null;
const [year, month, day] = date.split("-");
return `${day}-${month}-${year}`;
},
deFormatedDate(date) {
if (!date) return null;
const [day, month, year] = date.split("-");
return `${year}-${month.padStart(2, "0")}-${day.padStart(2, "0")}`;
},
getChipStatusColor(status) {
switch (status) {
case "Send Request":
return "warning";
case "Process":
return "success";
case "Rejected":
return "error";
case "Completed":
return "info";
default:
return "";
}
},
listSearch() {
this.$store.dispatch("listrequest/listrequestitem");
this.$store.commit("listrequest/update_selectedRequest", {});
},
requestExist(request) {
var selectedItems = this.selectedItems;
var idx = _.findIndex(selectedItems, function (o) {
return parseInt(o.rioDID) === parseInt(request.rioDID);
});
if (idx === -1) {
return true;
} else {
return false;
}
},
checkItemAll() {
// Salin selectedItems ke dalam array baru
let raw = JSON.stringify(this.selectedItems);
let arr = [...JSON.parse(raw)];
// Cek apakah checkbox utama (select all) sedang dicentang
let ckAll = this.headerCheckboxValueAll();
// Iterasi semua item yang tersedia
for (let i = 0; i < this.listRequest.length; i++) {
const element = this.listRequest[i];
// Hanya proses item dengan status 'Send Request'
if (element.rioStatus !== 'Send Request') continue;
let foundItem = arr.find((e) => e.rioDID === element.rioDID);
const index = arr.findIndex((e) => e.rioDID === element.rioDID);
if (ckAll) {
// Hapus item dari selected jika sesuai kondisi
arr.splice(index, 1);
} else {
// Tambahkan item ke selected jika sesuai kondisi dan belum ada
if (!foundItem) {
arr.push(element);
}
}
}
// Update pilihan
this.selectedItems = arr;
console.log('arr', arr)
},
headerCheckboxValueAll() {
// debugger;
let total = 0;
let selected = 0;
for (let i = 0; i < this.listRequest.length; i++) {
const element = this.listRequest[i];
if (element.rioStatus !== 'Send Request') continue;
total++;
let foundItem = this.selectedItems.find(
(e) => e.rioDID === element.rioDID
);
if (foundItem) {
selected++;
}
}
return total > 0 && selected === total;
},
headerCheckboxValuePartial() {
let total = 0;
let selected = 0;
for (let i = 0; i < this.listRequest.length; i++) {
const element = this.listRequest[i];
if (element.rioStatus !== 'Send Request') continue;
total++;
let foundItem = this.selectedItems.find(
(e) => e.rioDID === element.rioDID
);
if (foundItem) {
selected++;
}
}
return selected > 0 && selected < total;
},
changeCheckBox(val) {
// debugger;
let raw = JSON.stringify(this.selectedItems);
let arr = [...JSON.parse(raw)];
if (arr.length == 0) {
arr.push(val);
} else {
let foundItem = arr.find((e) => e.rioDID === val.rioDID);
const index = arr.findIndex((e) => e.rioDID === val.rioDID);
if (foundItem) {
arr.splice(index, 1);
} else {
arr.push(val);
}
}
this.selectedItems = arr;
},
checkBoxValue(val) {
let foundItem = this.selectedItems.find((e) => e.rioDID === val.rioDID);
if (foundItem) {
return true;
} else {
return false;
}
},
addRequest(request) {
if (!request.StockID) {
let msge = "Item belum ada di stock";
this.msginfo = msge;
this.opendialoginfo = true;
return;
}
if (!request.StockQty || request.StockQty === 0 || request.StockQty == "0") {
let msgg = "Item tidak bisa dikeluarkan karena stock kosong";
this.msginfo = msgg;
this.opendialoginfo = true;
return;
}
const exists = this.selectedItems.some(item => item.rioDID === request.rioDID);
console.log('exists', exists)
if (!exists) {
this.selectedItems.push(request);
// console.log("add request", this.selectedItems);
}
},
removeRequest(request) {
let selectedItems = this.selectedItems;
let idx = _.findIndex(selectedItems, function (o) {
return parseInt(o.rioDID) === parseInt(request.rioDID);
});
selectedItems.splice(idx, 1);
console.log("hapus request", this.selectedItems)
},
openApprove(request) {
if (request.some(item => item.rioDivisionID !== this.approveDivisionUserID)) {
this.msginfo = "Tidak bisa approve, Anda login manager tapi tidak sesuai divisi";
this.opendialoginfo = true;
return;
}
// Cek jika ada item yang belum punya StockID
const noStockID = request.find(item => !item.StockID);
// gabung number
const allRioNumbers = request.map(item => item.rioNumber).join(', ');
if (noStockID) {
this.msginfo = "Item belum ada di stock " + "(" + allRioNumbers + ")";
this.opendialoginfo = true;
return;
}
// Cek jika ada item dengan stock kosong atau 0
const stockKosong = request.find(item => !item.StockQty || item.StockQty === 0 || item.StockQty === "0");
if (stockKosong) {
this.msginfo = "Item tidak bisa dikeluarkan karena stock kosong " + "(" + allRioNumbers + ")";
this.opendialoginfo = true;
return;
}
let msg = "Yakin, mau approve ?";
this.msgapprove = msg;
this.dialogapprove = true;
},
orderApprove() {
let prm = {
arrRequest: this.selectedItems
}
this.$store.dispatch("listrequest/approveRequest", prm);
},
openRejected(request) {
let msg = "Yakin, mau reject ?";
this.msgreject = msg;
this.dialogreject = true;
},
orderRejected() {
let prm = {
arrRequest: this.selectedItems
}
this.$store.dispatch("listrequest/rejectedRequest", prm);
}
},
watch: {
}
};
</script>

View File

@@ -0,0 +1,956 @@
<template>
<div style="width: 100%">
<!-- SNACKBAR -->
<v-snackbar
v-model="snackbar"
:timeout="5000"
:multi-line="false"
:vertical="false"
:top="true"
>
{{ msgSnackbar }}
<v-btn flat @click="updateAlertSuccess(false)"> Tutup </v-btn>
</v-snackbar>
<!-- ERROR DIALOG -->
<v-dialog v-model="dialog_error" max-width="500px">
<v-card>
<v-card-title>
<span>ERROR !</span>
<v-spacer></v-spacer>
</v-card-title>
<v-divider></v-divider>
<div class="ma-3 red--text">{{ msgError }}</div>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="primary" flat @click="dialog_error = false"
>Tutup</v-btn
>
</v-card-actions>
</v-card>
</v-dialog>
<!-- END ERROR DIALOG -->
<!-- ERROR DIALOG -->
<v-dialog v-model="dialogerrordata" max-width="500px">
<v-card>
<v-card-title>
<span>ERROR !</span>
<v-spacer></v-spacer>
</v-card-title>
<v-divider></v-divider>
<div class="ma-3 red--text">{{ msgErrors }}</div>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="primary" flat @click="dialogerrordata = false"
>Tutup</v-btn
>
</v-card-actions>
</v-card>
</v-dialog>
<!-- END ERROR DIALOG -->
<v-toolbar color="primary" dark>
<v-toolbar-title class="white--text"
>TRANSAKSI PENGELUARAN BARANG</v-toolbar-title
>
<v-spacer></v-spacer>
<v-btn icon @click="openDialogRequest()">
<v-icon>add_box</v-icon>
</v-btn>
</v-toolbar>
<v-card class="pa-2">
<v-layout row wrap class="px-2 py-2">
<v-flex xs3>
<v-menu
v-model="menuStartDate"
:close-on-content-click="false"
transition="scale-transition"
:nudge-right="40"
lazy
offset-y
max-width="290px"
min-width="290px"
>
<template v-slot:activator="{ on }">
<v-text-field
v-model="startDateFormatted"
label="Tanggal Awal"
class="mr-2"
readonly
outline
hide-details
v-on="on"
@blur="dStartDate = deFormatedDate(startDateFormatted)"
></v-text-field>
</template>
<v-date-picker
no-title
v-model="fStartDate"
@input="menuStartDate = false"
></v-date-picker>
</v-menu>
</v-flex>
<v-flex xs3>
<v-menu
v-model="menuEndDate"
:close-on-content-click="false"
transition="scale-transition"
:nudge-right="40"
lazy
offset-y
max-width="290px"
min-width="290px"
>
<template v-slot:activator="{ on }">
<v-text-field
v-model="endDateFormatted"
label="Tanggal Akhir"
class="mr-2"
readonly
outline
hide-details
v-on="on"
@blur="dEndDate = deFormatedDate(endDateFormatted)"
></v-text-field>
</template>
<v-date-picker
no-title
v-model="fEndDate"
@input="menuEndDate = false"
></v-date-picker>
</v-menu>
</v-flex>
<v-flex xs2>
<v-autocomplete
v-model="fStatus"
menu-icon="mdi-chevron-down"
:items="statusOptions"
item-text="title"
return-object
label="Status"
class="mr-2"
outline
hide-details
></v-autocomplete>
</v-flex>
<v-flex xs2>
<v-text-field
v-model="fSearch"
label="Cari..."
placeholder="NO."
class="mr-2"
outline
hide-details
></v-text-field>
</v-flex>
<v-btn
dark
color="primary"
style="min-width: 50px; height: 50px; margin: 0"
@click="mainTableSearch()"
>
<v-icon>search</v-icon>
</v-btn>
</v-layout>
</v-card>
<v-card class="pa-2 mt-2">
<v-layout row style="max-height: 600px; overflow: auto">
<v-flex xs12 pl-2 pr-2 pt-2 pb-2>
<v-data-table
:headers="headers"
:items="mainTable"
:loading="mainTableLoading"
hide-actions
class="elevation-1"
>
<template slot="items" slot-scope="props">
<td
class="text-xs-center pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)"
>
<div
style="
display: flex;
flex-direction: column;
align-items: center;
"
>
<p class="mb-0 font-weight-bold" style="color:#000000">{{ props.item.T_ItemOutNumber }}</p>
</div>
</td>
<td
class="text-xs-left pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)"
>
{{ deFormatedDate(props.item.T_ItemOutDate) }}
</td>
<td
class="text-xs-left pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)"
>
{{ props.item.T_ItemOutNote }}
</td>
<td
class="text-xs-left pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)"
>
{{ props.item.DivisionName }}
</td>
<td
class="text-xs-left pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)"
>
<v-chip
small
:text-color="
props.item.T_ItemOutStatus === 'Draft'
? 'black'
: 'white'
"
:color="
getChipStatusColor(
props.item.T_ItemOutStatus
)
"
>
{{ props.item.T_ItemOutStatus }}
</v-chip>
</td>
<td
class="text-xs-center pa-2"
v-bind:class="{
'amber lighten-4': isSelected(props.item),
}"
@click="selectMe(props.item)"
>
<span v-if="props.item.T_ItemOutStatus == 'Draft'">
<v-btn
:disabled="mainTableLoading || approveLevelID == '2' || props.item.T_ItemOutApproveID != null"
v-if="props.item.T_ItemOutIsConfirm == 'Y'"
round depressed color="primary" small :outline="props.item.T_ItemOutApproveID == null"
@click="openApprove(props.item, )"
>
Approve (Manager)
</v-btn>
<v-btn
style="min-width: 25px; height: 25px; margin: 0;"
v-if="props.item.T_ItemOutApproveID != null && approveLevelID == '2'"
small
color="blue" title="Proses transaksi"
@click="openProcess(props.item)"
>
<v-icon small color="white">check_circle</v-icon>
</v-btn>
<v-btn
v-if="props.item.T_ItemOutIsConfirm == 'N' && approveLevelID == '2' && props.item.T_ItemOutApproveID == null"
style="min-width: 25px; height: 25px; margin: 0;"
small
color="primary" title="Konfirmasi"
@click="openConfirm(props.item)"
>
<v-icon small color="white">check_circle_outline</v-icon>
</v-btn>
<!-- <v-btn
v-if="props.item.T_ItemOutIsConfirm == 'N' && approveLevelID == '2' && props.item.T_ItemOutApproveID == null"
style="min-width: 25px; height: 25px; margin: 0;"
small
color="black" title="Edit"
@click="updateRequest(props.item)"
>
<v-icon small color="white">edit</v-icon>
</v-btn>
<v-btn
v-if="props.item.T_ItemOutIsConfirm == 'N' && approveLevelID == '2' && props.item.T_ItemOutApproveID == null"
style="min-width: 25px; height: 25px; margin: 0;"
small
color="red" title="Hapus"
@click="deleteRequest(props.item)"
>
<v-icon small color="white">delete</v-icon>
</v-btn> -->
</span>
<span v-if="props.item.T_ItemOutStatus == 'Process' || props.item.T_ItemOutStatus == 'Rejected'">
<v-btn
style="min-width: 25px; height: 25px; margin: 0;"
small
color="green" title="Preview"
@click="openPreview(props.item)"
>
<v-icon small color="white">receipt</v-icon>
</v-btn>
</span>
</td>
</template>
</v-data-table>
</v-flex>
</v-layout>
<v-divider></v-divider>
<v-pagination
style="margin-top: 10px; margin-bottom: 10px"
v-model="mainTableCurrentPage"
:length="mainTableTotalPage"
></v-pagination>
</v-card>
<v-dialog v-model="dialogAlertDeleteRequest" max-width="30%">
<v-card>
<v-card-title class="headline grey lighten-2 pt-2 pb-2" primary-title>
Peringatan !
</v-card-title>
<v-card-text class="pt-2 pb-2">
<v-layout row>
<v-flex xs12 d-flex>
<v-layout row>
<v-flex pb-1 xs12>
<v-layout row>
<v-flex pt-2 pr-2 xs12>
{{ msgAlertDeleteRequest }}
</v-flex>
</v-layout>
</v-flex>
</v-layout>
</v-flex>
</v-layout>
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="primary" flat @click="dialogAlertDeleteRequest = false">
Tutup
</v-btn>
<v-btn color="primary" flat @click="closeAndDeleteRequest()">
Yakin lah
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
<v-dialog v-model="dialogAlertDeleteDetail" max-width="30%">
<v-card>
<v-card-title class="headline grey lighten-2 pt-2 pb-2" primary-title>
Peringatan !
</v-card-title>
<v-card-text class="pt-2 pb-2">
<v-layout row>
<v-flex xs12 d-flex>
<v-layout row>
<v-flex pb-1 xs12>
<v-layout row>
<v-flex pt-2 pr-2 xs12>
{{ msgAlertDeleteRequest }}
</v-flex>
</v-layout>
</v-flex>
</v-layout>
</v-flex>
</v-layout>
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="primary" flat @click="dialogAlertDeleteDetail = false">
Tutup
</v-btn>
<v-btn color="primary" flat @click="closeAndDeleteDetail()">
Yakin lah
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
<add-item-out-dialog></add-item-out-dialog>
<add-item-detail-dialog></add-item-detail-dialog>
<dialog-item-approve></dialog-item-approve>
<dialog-item-process></dialog-item-process>
<dialog-item-preview></dialog-item-preview>
<dialog-item-confirm></dialog-item-confirm>
</div>
</template>
<style scoped>
.date-type-table {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.table.v-table tbody td,
table.v-table tbody th {
height: 40px;
}
.table.v-table thead tr {
height: 40px;
}
.scroll-container {
scroll-padding: 50px 0 0 50px;
}
</style>
<script>
module.exports = {
components: {
"add-item-out-dialog": httpVueLoader(
"./addItemOutDialog.vue"
),
"add-item-detail-dialog": httpVueLoader("./addItemDetailDialog.vue"),
"dialog-item-approve": httpVueLoader("./dialogItemApprove.vue"),
"dialog-item-process": httpVueLoader("./dialogItemProcess.vue"),
"dialog-item-preview": httpVueLoader("./dialogItemPreview.vue"),
"dialog-item-confirm": httpVueLoader("./dialogItemConfirm.vue"),
"one-dialog-alert": httpVueLoader("../../common/oneDialogAlert.vue"),
"one-dialog-error": httpVueLoader("../../common/oneDialogError.vue"),
},
data() {
return {
msgAlertDeleteRequest: "",
dialogAlertDeleteRequest: false,
dialogAlertDeleteDetail: false,
xDescription: "",
xRIOID: 0,
xRIODID: 0,
headers: [
{
text: "NO",
align: "center",
sortable: false,
value: "no",
width: "15%",
class: "blue lighten-3 white--text",
},
{
text: "TANGGAL",
align: "left",
sortable: false,
value: "date",
width: "15%",
class: "blue lighten-3 white--text",
},
{
text: "CATATAN",
align: "left",
sortable: false,
value: "warehouse",
width: "25%",
class: "blue lighten-3 white--text",
},
{
text: "DIVISI",
align: "left",
sortable: false,
value: "warehouse",
width: "15%",
class: "blue lighten-3 white--text",
},
{
text: "STATUS",
align: "left",
sortable: false,
value: "status",
width: "15%",
class: "blue lighten-3 white--text",
},
{
text: "AKSI",
align: "center",
sortable: false,
value: "action",
width: "15%",
class: "blue lighten-3 white--text",
},
],
};
},
mounted() {
this.$store.dispatch("requester/getlevel");
this.$store.dispatch("requester/search");
},
computed: {
msgSnackbar() {
return this.$store.state.requester.successMessage;
},
snackbar: {
get() {
return this.$store.state.requester.alertSuccess;
},
set(val) {
this.$store.commit("requester/updateAlertSuccess", val);
},
},
dialog_error: {
get() {
return this.$store.state.requester.alertError;
},
set(val) {
this.$store.commit("requester/updateAlertError", val);
},
},
dialogerrordata: {
get() {
return this.$store.state.requester.dialogErrors;
},
set(val) {
this.$store.commit("requester/updateDialogErrors", val);
},
},
msgError() {
return this.$store.state.requester.errMessage;
},
msgErrors() {
return this.$store.state.requester.errors;
},
mainTable() {
return this.$store.state.requester.mainTable;
},
detailTable() {
return this.$store.state.requester.detailTable;
},
mainTableLoading() {
return this.$store.state.requester.mainTableLoadingStatus === 1;
},
detailTableLoading() {
return this.$store.state.requester.detailTableLoadingStatus === 1;
},
mainTableTotalPage: {
get() {
return this.$store.state.requester.countMainTable;
},
set(val) {
this.$store.commit("requester/updateCountMainTable", val);
},
},
mainTableCurrentPage: {
get() {
return this.$store.state.requester.mainTableCurrentPage;
},
set(val) {
this.$store.commit("requester/updateMainTableCurrentPage", val);
this.$store.commit("requester/updateMainTableLastId", -1);
this.$store.dispatch("requester/search");
},
},
selectedMainTable: {
get() {
return this.$store.state.requester.selectedMainTable;
},
set(val) {
this.$store.commit("updateSelectedMainTable", val);
},
},
menuStartDate: {
get() {
return this.$store.state.requester.menuStartDate;
},
set(val) {
this.$store.commit("requester/updateMenuStartDate", val);
},
},
menuEndDate: {
get() {
return this.$store.state.requester.menuEndDate;
},
set(val) {
this.$store.commit("requester/updateMenuEndDate", val);
},
},
startDateFormatted() {
return this.formatDate(this.fStartDate);
},
endDateFormatted() {
return this.formatDate(this.fEndDate);
},
dStartDate: {
get() {
return this.$store.state.requester.dStartDate;
},
set(val) {
this.$store.commit("requester/updateDStartDate", val);
},
},
dEndDate: {
get() {
return this.$store.state.requester.dEndDate;
},
set(val) {
this.$store.commit("requester/updateDEndDate", val);
},
},
fStartDate: {
get() {
return this.$store.state.requester.fStartDate;
},
set(val) {
this.$store.commit("requester/updateFStartDate", val);
},
},
fEndDate: {
get() {
return this.$store.state.requester.fEndDate;
},
set(val) {
this.$store.commit("requester/updateFEndDate", val);
},
},
fStatus: {
get() {
return this.$store.state.requester.fStatus;
},
set(val) {
this.$store.commit("requester/updateFStatus", val);
},
},
statusOptions() {
return this.$store.state.requester.statusOptions;
},
fSearch: {
get() {
return this.$store.state.requester.fSearch;
},
set(val) {
this.$store.commit("requester/updateFSearch", val);
},
},
xNumber: {
get() {
return this.$store.state.requester.xNumber;
},
set(val) {
this.$store.commit("requester/updateXNumber", val);
},
},
xIOID: {
get() {
return this.$store.state.requester.xIOID;
},
set(val) {
this.$store.commit("requester/updateXIOID", val);
},
},
xIODID: {
get() {
return this.$store.state.requester.xIODID;
},
set(val) {
this.$store.commit("requester/updateXIODID", val);
},
},
xDescriptionDetail() {
return this.$store.state.requester.xDescriptionDetail;
},
selectedItems: {
get() {
return this.$store.state.requester.selectedItems;
},
set(val) {
this.$store.commit("requester/updateSelectedItems", val);
}
},
approveLevelID: {
get() {
return this.$store.state.requester.approveLevelID;
},
set(val) {
this.$store.commit("requester/updateApproveLevelID", val);
},
},
},
methods: {
convertMoney(money){
return one_money(money)
},
isSelected(p) {
return (
p.T_ItemOutID ==
this.$store.state.requester.selectedMainTable.T_ItemOutID
);
},
selectMe(spr) {
this.$store.commit("requester/updateSelectedMainTable", spr);
},
formatDate(date) {
if (!date) return null;
const [year, month, day] = date.split("-");
return `${day}-${month}-${year}`;
},
deFormatedDate(date) {
if (!date) return null;
const [day, month, year] = date.split("-");
return `${year}-${month.padStart(2, "0")}-${day.padStart(2, "0")}`;
},
getChipStatusColor(status) {
switch (status) {
case "Process":
return "success";
case "Rejected":
return "error";
default:
return "";
}
},
getChipStatusDetailColor(status) {
switch (status) {
case "Pending":
return "warning";
case "Process":
return "success";
case "Read":
return "info";
case "Process":
return "warning";
default:
return "";
}
},
mainTableSearch() {
this.$store.dispatch("requester/search");
this.$store.commit("requester/updateSelectedMainTable", {});
this.$store.commit("requester/updateDetailTable", []);
},
resetItemTable() {
this.$store.commit("requester/updateSelectedItems", []);
this.$store.commit("requester/updateItems", []);
this.$store.commit("requester/updateSearchItem", "");
this.$store.commit("requester/updateXWarehouse", "");
this.$store.commit("requester/updateLoadingItem", false);
},
openDialogRequest() {
this.resetItemTable()
this.$store.dispatch("requester/getWarehouse").then(() => {
const warehouseId = this.$store.state.requester.xWarehouse.WarehouseID;
const divisonId = this.$store.state.requester.selectedDivision.DivisionID;
this.$store.dispatch("requester/getItemRequest", {
search: "",
warehouseID: warehouseId,
divisionID: divisonId
});
})
this.$store.dispatch("requester/getDivisionByUser",{
act: 'new',
DivisionID: ''
}).then(() => {
const warehouseId = this.$store.state.requester.xWarehouse.WarehouseID;
const divisonId = this.$store.state.requester.selectedDivision.DivisionID;
this.$store.dispatch("requester/getItemRequest", {
search: "",
warehouseID: warehouseId,
divisionID: divisonId
});
})
this.$store.commit(
"requester/updateXDateUse",
moment(new Date()).format("YYYY-MM-DD")
);
this.$store.commit("requester/updateXNote", "");
this.$store.commit("requester/updateAct", "new");
this.$store.commit("requester/updateMainTableLastId", -1);
this.$store.commit("requester/updateDialogRequest", true);
},
isbranch() {
if (this.$store.state.requester.user.M_BranchID != 0) {
return this.$store.state.requester.user.M_BranchCode
} else {
return ''
}
},
updateRequest(val) {
this.$store.dispatch("requester/getWarehouse").then(() => {
const warehouseId = this.$store.state.requester.xWarehouse.WarehouseID;
const divisonId = this.$store.state.requester.selectedDivision.DivisionID;
this.$store.dispatch("requester/getItemRequest", {
search: "",
warehouseID: warehouseId,
divisionID: divisonId
});
})
this.$store.dispatch("requester/getDivisionByUser", {
act: 'edit',
DivisionID: val.DivisionID
}).then(() => {
const warehouseId = this.$store.state.requester.xWarehouse.WarehouseID;
const divisonId = this.$store.state.requester.selectedDivision.DivisionID;
this.$store.dispatch("requester/getItemRequest", {
search: "",
warehouseID: warehouseId,
divisionID: divisonId
});
})
this.$store.commit(
"requester/updateXDateUse",
val.T_ItemOutDate
);
this.$store.commit(
"requester/updateXNote",
val.T_ItemOutNote
);
this.$store.commit(
"requester/updateXWarehouse",
val.WarehouseID
);
this.$store.dispatch("requester/getDetailItemOut",{
itemoutID: val.T_ItemOutID
});
this.$store.commit("requester/updateXIOID", val.T_ItemOutID);
this.$store.commit("requester/updateAct", "edit");
this.$store.commit("requester/updateDialogRequest", true);
},
deleteRequest(data) {
console.log(data);
this.xIOID = data.T_ItemOutID;
this.xNumber = data.T_ItemOutNumber;
this.xRIOID = data.T_ItemOutDetailRequestItemOutID,
this.xRIODID = data.T_ItemOutDetailRequestItemOutDetailID,
this.$store.dispatch("requester/getDetailItemOut",{
itemoutID: data.T_ItemOutID
});
this.msgAlertDeleteRequest = `Yakin, mau hapus pengeluaran barang dengan nomor [${data.T_ItemOutNumber}] ?`;
this.dialogAlertDeleteRequest = true;
},
closeAndDeleteRequest() {
this.$store.dispatch("requester/deleteRequest", {
IOID: this.xIOID,
Number: this.xNumber,
RIOID: this.xRIOID,
RIODID: this.xRIODID
// items: this.selectedItems
});
this.dialogAlertDeleteRequest = false;
},
openDialogDetail() {
this.$store.commit("requester/updateSelectedItem", {});
this.$store.commit("requester/updateSelectedItemUnit", {});
this.$store.commit("requester/updateItemUnits", [])
this.$store.commit("requester/updateXQty", "");
this.$store.commit("requester/updateXPrice", "");
this.$store.commit("requester/updateXIsCito", false);
this.$store.commit("requester/updateAct", "new");
this.$store.commit("requester/updateDialogDetail", true);
this.$store.commit("requester/updateErrorsform", [])
this.$store.commit("requester/updateTempBatchNumber", {
records: [],
total: 0
});
},
updateDetail(val) {
this.$store.commit("requester/updateErrorsform", [])
this.$store.commit(
"requester/updateItemList", [{
M_ItemID: val.M_ItemID,
M_ItemDesc: val.M_ItemDesc
}]);
this.$store.commit(
"requester/updateSelectedItem", {
M_ItemID: val.M_ItemID,
M_ItemDesc: val.M_ItemDesc
});
this.$store.commit(
"requester/updateXQty",
val.T_ItemOutDetailQty
);
this.$store.commit(
"requester/updateItemUnits", [{
ItemUnitID: val.ItemUnitID,
ItemUnitName: val.ItemUnitName
}]
);
this.$store.commit(
"requester/updateSelectedItemUnit", {
ItemUnitID: val.ItemUnitID,
ItemUnitName: val.ItemUnitName
}
);
this.$store.commit("requester/updateSelectedDetailTable", val);
this.$store.commit("requester/updateAct", "edit");
this.$store.commit("requester/updateDialogDetail", true);
},
deleteDetail(data) {
this.xIODID = data.T_ItemOutDetailID;
this.xDescription = data.M_ItemDesc;
this.msgAlertDeleteRequest = `Yakin, mau hapus Request [${data.M_ItemDesc}] ?`;
this.dialogAlertDeleteDetail = true;
},
closeAndDeleteDetail() {
this.$store.dispatch("requester/deleteDetail", {
IODID: this.xIODID,
itemDescription: this.xDescription
});
this.dialogAlertDeleteDetail = false;
},
orderConfirm(id, status) {
if (status === "Draft") {
this.$store.dispatch("requester/orderConfirm", {
itemoutID: id,
});
}
},
thrSearchDate: _.debounce(function () {
this.$store.dispatch("requester/search")
}, 1000),
thrSearch: _.debounce(function () {
this.$store.dispatch("requester/search")
}, 1000),
openConfirm(val) {
this.$store.commit("requester/updateDialogConfirm", true);
this.xIOID = val.T_ItemOutID;
this.$store.dispatch("requester/getItemOuts", {
ioID: val.T_ItemOutID
});
},
openApprove(val) {
this.$store.commit("requester/updateDialogApprove", true);
this.xIOID = val.T_ItemOutID;
this.$store.dispatch("requester/getItemOuts", {
ioID: val.T_ItemOutID
});
},
openProcess(val) {
this.$store.commit("requester/updateDialogProcess", true);
this.xIOID = val.T_ItemOutID;
this.$store.dispatch("requester/getItemOuts", {
ioID: val.T_ItemOutID
});
},
openPreview(val) {
this.$store.commit("requester/updateDialogPreview", true);
this.xIOID = val.T_ItemOutID;
this.$store.dispatch("requester/getItemOuts", {
ioID: val.T_ItemOutID
});
}
},
watch: {
// fStartDate(val, old) {
// this.fStartDate = val
// this.thrSearchDate()
// },
// fEndDate(val, old) {
// this.fEndDate = val
// this.thrSearchDate()
// },
// fSearch(val, old) {
// this.fSearch = val
// this.thrSearch()
// }
}
};
</script>

View File

@@ -0,0 +1,71 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="../../../libs/vendor/css/google-fonts.css">
<link rel="stylesheet" href="../../../libs/vendor/css/icomoon-fonts.css">
<link rel="stylesheet" href="../../../libs/vendor/css/vuetify.min.css">
<title>One</title>
</head>
<body>
<div v-cloak id="app">
<v-app id="smartApp">
<one-navbar></one-navbar>
<v-content style="background: #F5E8DF!important">
<v-container fluid fill-height class="pl-1 pr-1 pt-2 pb-2">
<v-layout row wrap>
<!-- <v-flex xs6 class="left" fill-height pa-1>
<request-item-out-list></request-item-out-list>
</v-flex> -->
<v-flex xs12 class="center" fill-height pa-1>
<request-listing></request-listing>
</v-flex>
</v-layout>
</v-container>
</v-content>
<one-footer></one-footer>
</v-app>
</div>
<!-- Vendor -->
<script src="../../../libs/vendor/moment.min.js"></script>
<script src="../../../libs/vendor/numeral.min.js"></script>
<script src="../../../libs/vendor/moment-locale-id.js"></script>
<script src="../../../libs/vendor/lodash.js"></script>
<script src="../../../libs/vendor/axios.min.js"></script>
<script src="../../../libs/vendor/vue.js"></script>
<script src="../../../libs/vendor/vuex.js"></script>
<script src="../../../libs/vendor/vuetify.js"></script>
<script src="../../../libs/vendor/httpVueLoader.js"></script>
<script src="../../../libs/one_global.js"></script>
<!-- App Script -->
<script type="module">
import {
store
} from './store.js';
window.store = store;
new Vue({
store,
el: "#app",
methods: {},
components: {
'one-navbar': httpVueLoader('../../../apps/components/oneNavbarComponent.vue'),
'one-footer': httpVueLoader('../../../apps/components/oneFooter.vue'),
'request-listing': httpVueLoader('./components/requestListing.vue'),
// 'request-item-out-list': httpVueLoader('./components/requestItemOut.vue'),
}
})
</script>
<style>
[v-cloak] {
display: none
}
</style>
</body>
</html>

View File

@@ -0,0 +1,266 @@
// 1 => LOADING
// 2 => DONE
// 3 => ERROR
import * as api from "../api/api-requester.js";
export default {
namespaced: true,
state: {
request: [],
selectedRequest: [],
totalPage: 0,
currentPage: 1,
dStartDate: new Date().toISOString().substring(0, 10),
dEndDate: new Date().toISOString().substring(0, 10),
fStartDate: moment(new Date()).format("YYYY-MM-DD"),
fEndDate: moment(new Date()).format("YYYY-MM-DD"),
menuStartDate: false,
menuEndDate: false,
statusOptions: [
{ value: '', title: "All" },
{ value: 'Draft', title: "Draft" },
{ value: 'Send Request', title: "Send Request" },
{ value: 'Process', title: "Process" },
{ value: 'Rejected', title: "Rejected" },
{ value: 'Partial', title: "Partial" },
{ value: 'Completed', title: "Completed" },
],
fStatus: {value: "", title: "All"},
fSearch: "",
lastId: -1,
loadingStatus: 0,
errorMessage: "",
selectedItems: [],
selectedItem: {},
opendialoginfo: false,
msginfo: "",
loadingSave: false,
errMessage: "",
alertError: false,
snackbar: {
state: false,
type: 'success',
message: '',
},
dialogapprove: false,
msgapprove: '',
dialogreject: false,
msgreject: '',
approveDivisionUserID: 0,
approveDivision: '',
},
mutations: {
update_request(state, val) {
state.request = val
},
update_selectedRequest(state, val) {
state.selectedRequest = val
},
update_totalPage(state, val) {
state.totalPage = val
},
update_currentPage(state, val) {
state.currentPage = val
},
update_dStartDate(state, val) {
state.dStartDate = val
},
update_dEndDate(state, val) {
state.dEndDate = val
},
update_fStartDate(state, val) {
state.fStartDate = val
},
update_fEndDate(state, val) {
state.fEndDate = val
},
update_menuStartDate(state, val) {
state.menuStartDate = val
},
update_menuEndDate(state, val) {
state.menuEndDate = val
},
update_statusOptions(state, val) {
state.statusOptions = val
},
update_fStatus(state, val) {
state.fStatus = val
},
update_fSearch(state, val) {
state.fSearch = val
},
update_lastId(state, val) {
state.lastId = val
},
update_loadingStatus(state, val) {
state.loadingStatus = val
},
update_errorMessage(state, val) {
state.errorMessage = val
},
update_selectedItems(state, val) {
state.selectedItems = val
},
update_selectedItem(state, val) {
state.selectedItem = val
},
update_opendialoginfo(state, val) {
state.opendialoginfo = val
},
update_msginfo(state, val) {
state.msginfo = val
},
update_loadingSave(state, val) {
state.loadingSave = val
},
update_errMessage(state, val) {
state.errMessage = val
},
update_alertError(state, val) {
state.alertError = val
},
update_snackbar(state, val) {
state.snackbar = val
},
update_dialogapprove(state, val) {
state.dialogapprove = val
},
update_msgapprove(state, val) {
state.msgapprove = val
},
update_dialogreject(state, val) {
state.dialogreject = val
},
update_msgreject(state, val) {
state.msgreject = val
},
updateApproveDivisionUserID(state, val) {
state.approveDivisionUserID = val;
},
updateApproveDivision(state, val) {
state.approveDivision = val;
}
},
actions: {
async listrequestitem(context) {
context.commit("update_loadingStatus", 1);
try {
var prm = {
token: one_token(),
current_page: context.state.currentPage,
startDate: context.state.fStartDate,
endDate: context.state.fEndDate,
status: context.state.fStatus.value,
search: context.state.fSearch
};
let response = await api.listrequestitem(prm);
if (response.status != "OK") {
context.commit("update_loadingStatus", 3);
context.commit("update_errorMessage", response.message);
} else {
context.commit("update_loadingStatus", 2);
context.commit("update_errorMessage", "");
let data = {
records: response.data.records,
total: response.data.totalPage,
};
context.commit("update_request", data.records);
context.commit("update_totalPage", data.total);
}
} catch (e) {
context.commit("update_loadingStatus", 3);
context.commit("update_errorMessage", e.message);
}
},
async getDivisionUser(context) {
try {
var payload = {
token: one_token()
};
let response = await api.getDivisionUser(payload);
if (response.status != "OK") {
context.commit("update_errorMessage", response.message);
} else {
context.commit("update_errorMessage", "");
let data = {
records: response.data.records,
};
context.commit("updateApproveDivision", data.records[0].DivisionName);
context.commit("updateApproveDivisionUserID", data.records[0].M_UserDivisionDivisionID);
}
} catch (e) {
context.commit("update_errorMessage", e.message);
}
},
async approveRequest(context, prm) {
context.commit("update_loadingSave", true);
try {
prm.token = one_token();
let response = await api.approveRequest(prm);
if (response.status != "OK") {
context.commit("update_loadingSave", false);
context.commit("update_errMessage", response.message);
context.commit("update_alertError", true);
} else {
context.commit("update_loadingSave", false);
context.commit("update_snackbar", {
state: true,
type: 'success',
message: 'Request berhasil diapprove',
})
context.commit("update_dialogapprove", false);
context.commit("update_selectedItems", []);
context.commit("update_selectedItem", {});
context.dispatch("listrequestitem");
}
} catch (e) {
context.commit("update_loadingSave", false);
context.commit("update_errMessage", e.message);
context.commit("update_alertError", true);
}
},
async rejectedRequest(context, prm) {
context.commit("update_loadingSave", true);
try {
prm.token = one_token();
let response = await api.rejectedRequest(prm);
if (response.status != "OK") {
context.commit("update_loadingSave", false);
context.commit("update_errMessage", response.message);
context.commit("update_alertError", true);
} else {
context.commit("update_loadingSave", false);
context.commit("update_snackbar", {
state: true,
type: 'success',
message: 'Request berhasil ditolak',
})
context.commit("update_dialogreject", false);
context.commit("update_selectedItems", []);
context.commit("update_selectedItem", {});
context.dispatch("listrequestitem");
}
} catch (e) {
context.commit("update_loadingSave", false);
context.commit("update_errMessage", e.message);
context.commit("update_alertError", true);
}
},
},
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,13 @@
import listrequest from "./modules/listrequest.js";
import requester from "./modules/requester.js";
import system from "../../../apps/modules/system/system.js";
export const store = new Vuex.Store({
modules: {
listrequest: listrequest,
requester: requester,
system: system,
},
state: {},
mutations: {},
actions: {},
});

View File

@@ -0,0 +1,166 @@
const URL = "/one-api/mockup/itemout/";
export async function getDivisionByUser(payload) {
try {
var resp = await axios.post(URL + 'itemusagev3/getDivisionByUser', payload);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function search(payload) {
try {
var resp = await axios.post(URL + 'itemusagev3/search', payload);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function getUnit(payload) {
try {
var resp = await axios.post(URL + 'itemusagev3/getUnit', payload);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function saveItemUsage(payload) {
try {
var resp = await axios.post(URL + 'itemusagev3/saveItemUsage', payload);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
// item used
export async function getItemUsed(payload) {
try {
var resp = await axios.post(URL + 'itemusagev3/getItemUsed', payload);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function updateItemUsed(payload) {
try {
var resp = await axios.post(URL + 'itemusagev3/updateItemUsed', payload);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function deleteItemUsed(payload) {
try {
var resp = await axios.post(URL + 'itemusagev3/deleteItemUsed', payload);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function confirmItemUsed(payload) {
try {
var resp = await axios.post(URL + 'itemusagev3/confirmItemUsed', payload);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function getUnitByItemId(payload) {
try {
var resp = await axios.post(URL + 'itemusagev3/getUnitByItemId', payload);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}

View File

@@ -0,0 +1,310 @@
<template>
<v-layout row justify-center>
<v-dialog v-model="dialogUnit" persistent max-width="25%">
<v-card>
<v-card-title class="title grey lighten-2" primary-title>
Ganti Satuan {{ selectedItemUsage.M_ItemDesc ? selectedItemUsage.M_ItemDesc : "" }}
</v-card-title>
<v-card-text>
<v-layout row>
<v-flex xs12>
<v-select
:loading="loadingUnit"
v-model="selectedUnit"
return-object
:items="unitOptions"
label="Pilih Satuan"
item-text="ItemUnitName"
></v-select>
</v-flex>
</v-layout>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="error" flat @click="dialogUnit = false">
Tutup
</v-btn>
<v-btn color="primary" flat @click="saveUnit()">Ganti</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
<v-dialog v-model="dialogform" persistent max-width="75%">
<v-card>
<v-card-title class="headline grey lighten-2" primary-title>
Detail Pemakaian
</v-card-title>
<v-card-text class="pt-2 pb-0">
<v-layout row wrap>
<v-flex xs12 pa-2>
<p class="mb-0"><strong>Item:</strong> {{ selectedItemUsage.M_ItemDesc }}</p>
<p class="mb-0"><strong>Unit:</strong> {{ selectedItemUsage.ItemUnitName }}</p>
<p class="mb-0"><strong>Jumlah Stock:</strong> {{ selectedItemUsage.TotalStockQtyReq }}</p>
</v-flex>
</v-layout>
<v-card flat class=" mt-2">
<v-layout row style="max-height: 600px; overflow: auto">
<v-flex xs12 pl-2 pr-2 pt-2 pb-2>
<v-data-table
:headers="headersItems"
:items="itemRequestList"
hide-actions
class="elevation-1"
>
<template slot="items" slot-scope="props">
<td
class="text-xs-left pa-2"
>
{{ props.item.StockBatchNo }}
</td>
<td
class="text-xs-left pa-2"
>
{{ props.item.ItemUnitName }}
</td>
<td
class="text-xs-center pa-2"
>
{{ props.item.QtyReq }}
</td>
<td
class="text-xs-center pa-2"
>
<v-text-field
v-model="props.item.amountUsed"
label="Jumlah"
single-line
hide-details
outline
type="number" min="0" step="1">
</v-text-field>
<p v-show="emptycheck.includes(props.item.StockID)" style="color: red;" class="ma-0 pa-0">Jumlah melebihi stock request</p>
</td>
<td
class="text-xs-center pa-2"
>
<v-btn depressed small color="primary" @click="openDialogUnit(props.item)">{{ props.item.ItemUnitName }}</v-btn>
</td>
</template>
</v-data-table>
</v-flex>
</v-layout>
</v-card>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="error" flat @click="closeDialogForm()">
Tutup
</v-btn>
<v-btn
color="green"
dark
@click="btnSaveUsed()"
>Simpan</v-btn
>
</v-card-actions>
</v-card>
</v-dialog>
</v-layout>
</template>
<script>
module.exports = {
name: "AddPurchaseRequestDialog",
data() {
return {
itemUnitChange:{},
headersItems: [
{
text: "NUMBER BATCH",
align: "center",
sortable: false,
value: "action",
width: "20%",
class: "pa-2 pl-2 blue lighten-3 white--text",
},
{
text: "UNIT",
align: "center",
sortable: false,
value: "action",
width: "25%",
class: "pa-2 pl-2 blue lighten-3 white--text",
},
{
text: "STOCK",
align: "center",
sortable: false,
value: "action",
width: "15%",
class: "pa-2 pl-2 blue lighten-3 white--text",
},
{
text: "JUMLAH DIGUNAKAN",
align: "center",
sortable: false,
value: "action",
width: "15%",
class: "pa-2 pl-2 blue lighten-3 white--text",
},
{
text: "UNIT DIGUNAKAN",
align: "center",
sortable: false,
value: "action",
width: "25%",
class: "pa-2 pl-2 blue lighten-3 white--text",
}
]
};
},
mounted() {
},
computed: {
loadingUnit() {
return this.$store.state.usage.loadingUnit;
},
dialogUnit: {
get() {
return this.$store.state.usage.dialogUnit;
},
set(val) {
this.$store.commit("usage/updateDialogUnit", val);
},
},
selectedUnit: {
get() {
return this.$store.state.usage.selectedUnit;
},
set(val) {
this.$store.commit("usage/updateSelectedUnit", val);
},
},
unitOptions: {
get() {
return this.$store.state.usage.unitOptions;
},
set(val) {
this.$store.commit("usage/updateUnitOptions", val);
},
},
dialogform: {
get() {
return this.$store.state.usage.dialogform;
},
set(val) {
this.$store.commit("usage/updateDialogform", val);
},
},
itemRequestList: {
get() {
return this.$store.state.usage.itemRequestList;
},
set(val) {
this.$store.commit("usage/updateItemRequestList", val);
},
},
emptycheck: {
get() {
return this.$store.state.usage.emptycheck;
},
set(val) {
this.$store.commit("usage/updateEmptycheck", val);
},
},
selectedItemUsage: {
get() {
return this.$store.state.usage.selectedItemUsage;
},
set(val) {
this.$store.commit("usage/updateSelectedItemUsage", val);
}
},
itemUsageList: {
get() {
return this.$store.state.usage.itemUsageList;
},
set(val) {
this.$store.commit("usage/updateItemUsageList", val);
}
},
},
methods: {
saveUnit() {
let items = this.itemRequestList;
let index = items.findIndex(itemloop => itemloop.ItemUsageDetailID == this.itemUnitChange.ItemUsageDetailID);
let selectedUnit = this.selectedUnit;
items[index].StockItemUnitID = selectedUnit.StockItemUnitID;
items[index].ItemUnitCode = selectedUnit.ItemUnitCode;
items[index].ItemUnitName = selectedUnit.ItemUnitName;
this.$store.commit("usage/updateItemRequestList", items);
this.$store.commit("usage/updateDialogUnit", false);
},
openDialogUnit(item) {
this.itemUnitChange = item
this.$store.dispatch("usage/getUnitByItemId", {
itemId: item.StockItemID,
selectedUnit: {StockItemUnitID: item.StockItemUnitID, ItemUnitCode: item.ItemUnitCode, ItemUnitName: item.ItemUnitName}
});
},
closeDialogForm() {
this.$store.commit("usage/updateDialogform", false);
this.$store.commit("usage/updateItemRequestList", []);
this.$store.dispatch("usage/search", {
currentPage: this.$store.state.usage.currentPage,
divisionID: this.$store.state.usage.selectedDivision == undefined ? 0 : this.$store.state.usage.selectedDivision.DivisionID,
search: this.$store.state.usage.xsearch
});
this.$store.commit("usage/update_last_id", this.$store.state.usage.selectedItemUsage.ItemUsageID);
this.emptycheck = [];
},
btnSaveUsed() {
let emptycheck = [];
this.itemRequestList.forEach(element => {
if(element.amountUsed > element.QtyReq){
emptycheck.push(element.StockID);
}
});
if(emptycheck.length > 0){
this.emptycheck = emptycheck;
return;
}
let itemRequestList = this.itemRequestList
let tempItemRequestList = []
let totalAmountUsed = 0
itemRequestList.forEach(element => {
totalAmountUsed += Number(element.amountUsed);
if ( element.amountUsed != "" && element.amountUsed != 0 && element.amountUsed != '0') {
tempItemRequestList.push(element);
}
});
if (totalAmountUsed == 0) {
alert("Jumlah digunakan harus diisi salah satu");
return;
}
let param = {
ItemUsageID: this.selectedItemUsage.ItemUsageID,
ItemRequest: tempItemRequestList,
currentPage: this.$store.state.used.currentPage,
search: this.$store.state.used.search,
statusConfirm: this.$store.state.used.statusConfirm,
currentPageUsage: this.$store.state.usage.currentPage,
divisionID: this.$store.state.usage.selectedDivision == undefined ? 0 : this.$store.state.usage.selectedDivision.DivisionID,
searchUsage: this.$store.state.usage.xsearch
};
this.$store.dispatch("usage/saveItemUsage", param)
}
},
watch: {
}
};
</script>

View File

@@ -0,0 +1,168 @@
<template>
<v-layout row justify-center>
<v-dialog v-model="showDialog" persistent max-width="600px">
<v-card>
<v-card-title class="headline grey lighten-2" primary-title>
Detail Pemakaian
</v-card-title>
<v-card-text class="pt-2 pb-0">
<v-layout>
<v-flex xs12 pa-2>
<p class="mb-0"><strong>Item:</strong> {{ selectedItem.M_ItemDesc }}</p>
<p class="mb-0"><strong>Unit Asal:</strong> {{ selectedItem.ItemUnitName }}</p>
<p class="mb-0"><strong>Qty:</strong> {{ selectedItem.ItemUsageQty }}</p>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs12 pa-2>
<v-text-field
v-model="usedQty"
label="Jumlah Digunakan"
hide-details
outline
type="number">
</v-text-field>
<p v-if="checkErrorForm('requireUsageQty')" class="error pl-2 pr-2" style="color:#fff">Jumlah digunakan masih kosong</p>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs12 pa-2>
<v-autocomplete
v-model="selectedItemUnit"
:items="unitList"
item-text="ToUnitName"
item-value="ToUnitID"
:loading="loadingAutocomplete"
return-object
label="Unit Digunakan"
outline
hide-details
></v-autocomplete>
<p v-if="checkErrorForm('requireUnit')" class="error pl-2 pr-2" style="color:#fff">Unit harus dipilih</p>
</v-flex>
</v-layout>
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn text @click="closeDialog">Batal</v-btn>
<v-btn color="primary" @click="saveItem">Simpan</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-layout>
</template>
<style scoped>
.date-type-table {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.table.v-table tbody td,
table.v-table tbody th {
height: 40px;
}
.table.v-table thead tr {
height: 40px;
}
.scroll-container {
scroll-padding: 50px 0 0 50px;
}
</style>
<script>
module.exports = {
components: {
},
data() {
return {
};
},
mounted() {
},
computed: {
showDialog: {
get() {
return this.$store.state.usage.dialogUsage;
},
set(val) {
this.$store.commit("usage/updateDialogUsage", val);
}
},
selectedItem() {
return this.$store.state.usage.selectedItemUsage;
},
unitList() {
return this.$store.state.usage.unitList;
},
selectedItemUnit: {
get() {
return this.$store.state.usage.selectedItemUnit;
},
set(val) {
this.$store.commit("usage/updateSelectedItemUnit", val);
}
},
loadingAutocomplete() {
return this.$store.state.usage.loadingAutocomplete === 1;
},
usedQty: {
get() {
return this.$store.state.usage.usedQty;
},
set(val) {
this.$store.commit("usage/updateUsedQty", val);
}
}
},
methods: {
closeDialog() {
this.showDialog = false;
this.$store.commit("usage/updateSelectedItemUnit", {});
this.usedQty = 0;
this.$store.commit("usage/updateErrors", []);
},
checkErrorForm(val) {
let errors = this.$store.state.usage.errors;
if (errors.includes(val)) {
return true;
} else {
return false;
}
},
saveItem() {
this.$store.commit("usage/updateErrors", []);
var errors = this.$store.state.usage.errors;
if (_.isEmpty(this.usedQty) || this.usedQty <= 0) {
errors.push("requireUsageQty");
}
if (_.isEmpty(this.selectedItemUnit) || !this.selectedItemUnit.ToUnitID) {
errors.push("requireUnit");
}
if (errors.length === 0) {
let prm = {
itemUsageID: this.selectedItem.ItemUsageID,
itemID: this.selectedItem.M_ItemID,
usedQty: this.usedQty,
fromUnitID: this.selectedItemUnit.FromUnitID,
toUnitID: this.selectedItemUnit.ToUnitID,
usedPrice: this.selectedItem.ItemUsagePrice,
currentPage: this.$store.state.used.currentPage,
search: this.$store.state.used.search,
statusConfirm: this.$store.state.used.statusConfirm
};
this.$store.dispatch("usage/saveItemUsage", prm)
}
}
},
};
</script>

View File

@@ -0,0 +1,331 @@
<template>
<div style="width: 100%">
<v-snackbar
v-model="snackbar.state"
:color="snackbar.type"
:timeout="3000"
multi-line
top
>
{{ snackbar.message }}
<v-btn flat @click="snackbar.state = false">
Close
</v-btn>
</v-snackbar>
<!-- ERROR DIALOG -->
<v-dialog v-model="dialog_error" max-width="500px">
<v-card>
<v-card-title>
<span>ERROR !</span>
<v-spacer></v-spacer>
</v-card-title>
<v-divider></v-divider>
<div class="ma-3 red--text">{{ msgError }}</div>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="primary" flat @click="dialog_error = false"
>Tutup</v-btn
>
</v-card-actions>
</v-card>
</v-dialog>
<!-- END ERROR DIALOG -->
<v-toolbar color="primary" dark>
<v-toolbar-title class="white--text"
>PEMAKAIAN ITEM PER DIVISI</v-toolbar-title
>
<v-spacer></v-spacer>
</v-toolbar>
<v-card class="pa-2">
<v-layout row>
<v-flex pl-2 xs4>
<v-autocomplete
v-model="selectedDivision"
menu-icon="mdi-chevron-down"
:items="divisionOptions"
item-text="DivisionName"
item-value="DivisionID"
:loading="loadingAutocomplete"
return-object
label="Divisi"
outline
hide-details
></v-autocomplete>
</v-flex>
<v-flex xs4 pl-2>
<v-text-field
label="Cari..."
placeholder="ITEM"
outline
hide-details
v-model="xsearch"
></v-text-field>
</v-flex>
</v-layout>
</v-card>
<v-card class="pa-2 mt-2">
<v-layout row style="max-height: 600px; overflow: auto">
<v-flex xs12 pl-2 pr-2 pt-2 pb-2>
<v-data-table
:headers="headers"
:items="itemUsageList"
:loading="loading"
hide-actions
class="elevation-1"
>
<template slot="items" slot-scope="props">
<td
class="text-xs-center pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)"
>
{{ props.item.DivisionName }}
</td>
<td
class="text-xs-left pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)"
>
<span class="font-weight-bold" style="color:#000000">{{ props.item.M_ItemCode }}</span> {{ props.item.M_ItemDesc }}
</td>
<td
class="text-xs-center pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
>
<v-btn
color="info"
@click="openDialogDetail(props.item)"
>
Detail
</v-btn>
</td>
</template>
</v-data-table>
</v-flex>
</v-layout>
<v-divider></v-divider>
<v-pagination
style="margin-top: 10px; margin-bottom: 10px"
v-model="currentPage"
:length="totalPage"
></v-pagination>
</v-card>
<dialog-detail-usage-item></dialog-detail-usage-item>
</div>
</template>
<style scoped>
.date-type-table {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.table.v-table tbody td,
table.v-table tbody th {
height: 40px;
}
.table.v-table thead tr {
height: 40px;
}
.scroll-container {
scroll-padding: 50px 0 0 50px;
}
</style>
<script>
module.exports = {
components: {
"one-dialog-alert": httpVueLoader("../../common/oneDialogAlert.vue"),
"one-dialog-error": httpVueLoader("../../common/oneDialogError.vue"),
"dialog-detail-usage-item": httpVueLoader("./dialogDetailUsageItem.vue"),
},
data() {
return {
headers: [
{
text: "DIVISI",
align: "center",
sortable: false,
value: "no",
width: "30%",
class: "blue lighten-3 white--text",
},
{
text: "ITEM",
align: "center",
sortable: false,
value: "requestDate",
width: "60%",
class: "blue lighten-3 white--text",
},
{
text: "AKSI",
align: "center",
sortable: false,
value: "keterangan",
width: "10%",
class: "blue lighten-3 white--text",
}
],
};
},
mounted() {
this.$store.dispatch("usage/getDivisionByUser")
.then(() => {
this.$store.dispatch("usage/search", {
currentPage: this.$store.state.usage.currentPage,
divisionID: this.$store.state.usage.selectedDivision == undefined ? 0 : this.$store.state.usage.selectedDivision.DivisionID,
search: this.$store.state.usage.xsearch
});
})
.catch(error => {
console.error("Error fetching:", error);
});
},
computed: {
itemUsageList() {
return this.$store.state.usage.itemUsageList;
},
loading() {
return this.$store.state.usage.loadingStatus === 1;
},
snackbar: {
get() {
return this.$store.state.usage.snackbar;
},
set(val) {
this.$store.commit("usage/updateSnackbar", val);
},
},
dialog_error: {
get() {
return this.$store.state.usage.alertError;
},
set(val) {
this.$store.commit("usage/updateAlertError", val);
},
},
msgError() {
return this.$store.state.usage.errMessage;
},
selectedDivision: {
get() {
return this.$store.state.usage.selectedDivision;
},
set(val) {
this.$store.commit("usage/updateSelectedDivision", val);
this.$store.commit("usage/update_last_id", -1);
this.$store.dispatch("usage/search", {
currentPage: this.$store.state.usage.currentPage,
divisionID: val == undefined ? 0 : val.DivisionID,
search: this.$store.state.usage.xsearch,
});
}
},
divisionOptions: {
get() {
return this.$store.state.usage.divisionOptions;
},
set(val) {
this.$store.commit("usage/updateDivisionOptions", val);
this.$store.commit("usage/update_last_id", -1);
}
},
currentPage: {
get() {
return this.$store.state.usage.currentPage;
},
set(val) {
this.$store.commit("usage/updateCurrentPage", val);
this.$store.commit("usage/update_last_id", -1);
this.$store.dispatch("usage/search", {
currentPage: val,
divisionID: this.$store.state.usage.selectedDivision == undefined ? 0 : this.$store.state.usage.selectedDivision.DivisionID,
search: this.$store.state.usage.xsearch,
last_id: -1
});
}
},
totalPage: {
get() {
return this.$store.state.usage.totalPage;
},
set(val) {
this.$store.commit("usage/updateTotalPage", val);
}
},
loadingAutocomplete() {
return this.$store.state.usage.loadingAutocomplete === 1;
},
selectedItemUsage: {
get() {
return this.$store.state.usage.selectedItemUsage;
},
set(val) {
this.$store.commit("usage/updateSelectedItemUsage", val);
}
},
xsearch: {
get() {
return this.$store.state.usage.xsearch;
},
set(val) {
this.$store.commit("usage/updateXsearch", val);
this.$store.commit("usage/update_last_id", -1);
this.$store.dispatch("usage/search", {
currentPage: this.$store.state.usage.currentPage,
divisionID: this.$store.state.usage.selectedDivision == undefined ? 0 : this.$store.state.usage.selectedDivision.DivisionID,
search: val,
last_id: -1
});
}
}
},
methods: {
isSelected(item) {
return this.$store.state.usage.selectedItemUsage.ItemUsageID === item.ItemUsageID;
},
selectMe(item) {
this.$store.commit("usage/updateSelectedItemUsage", item);
},
convertMoney(money){
return one_money(money)
},
openDialogDetail(item){
this.$store.commit("usage/updateDialogform", true);
this.$store.commit("usage/updateItemRequestList", item.ItemRequest);
this.$store.commit("usage/updateSelectedItemUsage", item);
let prm = {
itemUnitID: item.ItemUnitID
}
this.$store.dispatch("usage/getUnit", prm);
},
thr_search: _.debounce(function () {
this.$store.dispatch("used/getItemUsed", {
itemUsageID: this.$store.state.usage.selectedItemUsage.ItemUsageID,
currentPage: this.$store.state.used.currentPage,
search: this.$store.state.used.search,
statusConfirm: this.$store.state.used.statusConfirm,
startdate: this.$store.state.used.fStartDate,
enddate: this.$store.state.used.fEndDate
});
}, 700),
},
watch: {
selectedItemUsage(val, old) {
this.thr_search()
}
}
};
</script>

View File

@@ -0,0 +1,690 @@
<template>
<div style="width: 100%">
<v-snackbar
v-model="snackbar.state"
:color="snackbar.type"
:timeout="3000"
multi-line
top
>
{{ snackbar.message }}
<v-btn flat @click="snackbar.state = false">
Close
</v-btn>
</v-snackbar>
<!-- ERROR DIALOG -->
<v-dialog v-model="dialog_error" max-width="500px">
<v-card>
<v-card-title>
<span>ERROR !</span>
<v-spacer></v-spacer>
</v-card-title>
<v-divider></v-divider>
<div class="ma-3 red--text">{{ msgError }}</div>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="primary" flat @click="dialog_error = false"
>Tutup</v-btn
>
</v-card-actions>
</v-card>
</v-dialog>
<!-- END ERROR DIALOG -->
<v-toolbar color="primary" dark>
<v-toolbar-title class="white--text"
>DAFTAR ITEM DIGUNAKAN</v-toolbar-title
>
<v-spacer></v-spacer>
</v-toolbar>
<v-card class="pa-2">
<div class="d-flex justify-start align-center" style="gap: 0.5rem">
<v-menu
v-model="menuStartDate"
:close-on-content-click="false"
transition="scale-transition"
:nudge-right="40"
lazy
offset-y
max-width="290px"
min-width="290px"
>
<template v-slot:activator="{ on }">
<v-text-field
v-model="startDateFormatted"
label="Tanggal Awal"
readonly
style="max-width: 250px"
outline
hide-details
class="mb-0"
v-on="on"
@blur="dStartDate = deFormatedDate(startDateFormatted)"
></v-text-field>
</template>
<v-date-picker
no-title
v-model="fStartDate"
@input="menuStartDate = false"
></v-date-picker>
</v-menu>
<v-menu
v-model="menuEndDate"
:close-on-content-click="false"
transition="scale-transition"
:nudge-right="40"
lazy
offset-y
max-width="290px"
min-width="290px"
>
<template v-slot:activator="{ on }">
<v-text-field
v-model="endDateFormatted"
label="Tanggal Akhir"
readonly
style="max-width: 250px"
outline
hide-details
class="mb-0"
v-on="on"
@blur="dEndDate = deFormatedDate(endDateFormatted)"
></v-text-field>
</template>
<v-date-picker
no-title
v-model="fEndDate"
@input="menuEndDate = false"
></v-date-picker>
</v-menu>
<v-select
v-model="statusConfirm"
:items="statusConfirmOptions"
label=""
item-text="text"
item-value="value"
outline
hide-details
></v-select>
</div>
</v-card>
<v-card class="pa-2 mt-2">
<v-layout row style="max-height: 600px; overflow: auto">
<v-flex xs12 pl-2 pr-2 pt-2 pb-2>
<v-data-table
:headers="headers"
:items="itemUsedList"
:loading="loading"
hide-actions
class="elevation-1"
>
<template slot="items" slot-scope="props">
<td
class="text-xs-left pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)"
>
<p class="mb-0">{{ formatDate(props.item.ItemUsedDate)}}</p>
<p class="mb-0 font-weight-bold">{{ props.item.ItemUsedNumber }}</p>
</td>
<td
class="text-xs-left pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)"
>
<span class="font-weight-bold" style="color:#000000">{{ props.item.M_ItemCode }}</span> {{ props.item.M_ItemDesc }}
</td>
<td
class="text-xs-left pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)"
>
<p class="mb-0"><strong>Qty : </strong> {{ props.item.ItemUsedQty }}</p>
<p class="mb-0"><strong>Unit : </strong> {{ props.item.ItemUnitName }}</p>
</td>
<td
class="text-xs-center pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)"
>
{{ props.item.M_UserUsername }}
</td>
<td
class="text-xs-left pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)"
>
<span v-if="props.item.ItemUsedIsConfirm === 'N'">
<v-btn
style="min-width: 25px; height: 25px; margin: 0;"
color="blue"
small title="Konfirmasi"
@click="openConfirm(props.item)"
>
<v-icon small color="white">check_circle</v-icon>
</v-btn>
<!-- <v-btn
style="min-width: 25px; height: 25px; margin: 0;"
color="black"
small title="Edit"
@click="openDialogEdit(props.item)"
>
<v-icon small color="white">edit</v-icon>
</v-btn>
<v-btn
style="min-width: 25px; height: 25px; margin: 0;"
color="red"
small title="Hapus"
@click="openDialogDelete(props.item)"
>
<v-icon small color="white">delete</v-icon>
</v-btn> -->
</span>
<span v-else-if="props.item.ItemUsedIsConfirm === 'Y'">
<span class="text-xs-center">Sudah Dikonfirmasi</span>
</span>
</td>
</template>
</v-data-table>
</v-flex>
</v-layout>
<v-divider></v-divider>
<v-pagination
style="margin-top: 10px; margin-bottom: 10px"
v-model="currentPage"
:length="totalPage"
></v-pagination>
</v-card>
<template>
<v-layout row justify-center>
<v-dialog v-model="dialogUsed" persistent max-width="600px">
<v-card>
<v-card-title class="headline grey lighten-2" primary-title>
Edit Pemakaian
</v-card-title>
<v-card-text class="pt-2 pb-0">
<v-layout>
<v-flex xs12 pa-2>
<p class="mb-0"><strong>Item:</strong> {{ selectedItemUsed.M_ItemDesc }}</p>
<p class="mb-0"><strong>Unit:</strong> {{ selectedItemUsed.ItemUnitName }}</p>
<p class="mb-0"><strong>Qty:</strong> {{ selectedItemUsed.ItemUsedQty }}</p>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs12 pa-2>
<v-text-field
v-model="selectedusedqty"
label="Jumlah Digunakan"
hide-details
outline
type="number">
</v-text-field>
<p v-if="checkErrorForm('requireUsageQty')" class="error pl-2 pr-2" style="color:#fff">Jumlah digunakan masih kosong</p>
</v-flex>
</v-layout>
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn text @click="closeDialog">Batal</v-btn>
<v-btn color="primary" @click="saveItem">Simpan</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-layout>
</template>
<template>
<v-dialog v-model="dialogConfirmation" persistent width="500">
<v-card>
<v-card-title class="headline grey lighten-2" primary-title>
KONFIRMASI
</v-card-title>
<v-card-text>
Apakah anda yakin untuk konfirmasi ?
<div class="mt-2">
<p class="mb-0"><strong>Item:</strong> {{ selectedItemUsed.M_ItemDesc }}</p>
<p class="mb-0"><strong>Batch No:</strong> {{ selectedItemUsed.ItemUsedBatchNo }}</p>
<p class="mb-0"><strong>Unit:</strong> {{ selectedItemUsed.ItemUnitName }}</p>
<p class="mb-0"><strong>Qty:</strong> {{ selectedItemUsed.ItemUsedQty }}</p>
</div>
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn
color="red"
flat
@click="dialogConfirmation = false"
>
Tidak
</v-btn>
<v-btn
color="green"
flat
@click="requestConfirm()"
>
Ya
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<template>
<v-dialog v-model="dialogDelete" persistent width="500">
<v-card>
<v-card-title class="headline grey lighten-2" primary-title>
PERHATIAN
</v-card-title>
<v-card-text>
Apakah anda yakin untuk menghapus
<span style="font-weight: bold;">{{
selectedItemUsed.M_ItemDesc
}}</span>
??
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn
color="red"
flat
@click="dialogDelete = false"
>
Tidak
</v-btn>
<v-btn
color="green"
flat
@click="deleteUsed()"
>
Ya
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
</div>
</template>
<style scoped>
.date-type-table {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.table.v-table tbody td,
table.v-table tbody th {
height: 40px;
}
.table.v-table thead tr {
height: 40px;
}
.scroll-container {
scroll-padding: 50px 0 0 50px;
}
</style>
<script>
module.exports = {
components: {
"one-dialog-alert": httpVueLoader("../../common/oneDialogAlert.vue"),
"one-dialog-error": httpVueLoader("../../common/oneDialogError.vue"),
},
data() {
return {
headers: [
{
text: "TANGGAL/NO",
align: "center",
sortable: false,
value: "no",
width: "15%",
class: "blue lighten-3 white--text",
},
{
text: "ITEM",
align: "center",
sortable: false,
value: "no",
width: "40%",
class: "blue lighten-3 white--text",
},
{
text: "QTY/UNIT",
align: "center",
sortable: false,
value: "requestDate",
width: "20%",
class: "blue lighten-3 white--text",
},
{
text: "USER",
align: "center",
sortable: false,
value: "status",
width: "15%",
class: "blue lighten-3 white--text",
},
{
text: "AKSI",
align: "left",
sortable: false,
value: "status",
width: "10%",
class: "blue lighten-3 white--text",
}
],
};
},
mounted() {
},
computed: {
itemUsedList() {
return this.$store.state.used.itemUsedList;
},
loading() {
return this.$store.state.used.loadingStatus === 1;
},
dialog_error: {
get() {
return this.$store.state.used.alertError;
},
set(val) {
this.$store.commit("used/updateAlertError", val);
},
},
msgError() {
return this.$store.state.used.errMessage;
},
currentPage: {
get() {
return this.$store.state.used.currentPage;
},
set(val) {
this.$store.commit("used/updateCurrentPage", val);
this.$store.dispatch("used/getItemUsed", {
itemUsageID: this.$store.state.usage.selectedItemUsage.ItemUsageID,
currentPage: val,
search: this.$store.state.used.search,
statusConfirm: this.$store.state.used.statusConfirm,
startdate: this.$store.state.used.fStartDate,
enddate: this.$store.state.used.fEndDate
});
},
},
totalPage: {
get() {
return this.$store.state.used.totalPageUsed;
},
set(val) {
this.$store.commit("used/updateTotalPageUsed", val);
},
},
selectedusedqty: {
get() {
return this.$store.state.used.selectedUsedQty;
},
set(val) {
this.$store.commit("used/updateSelectedUsedQty", val);
},
},
selectedItemUsed: {
get() {
return this.$store.state.used.selectedItemUsed;
},
set(val) {
this.$store.commit("used/updateSelectedItemUsed", val);
},
},
dialogUsed: {
get() {
return this.$store.state.used.dialogUsed;
},
set(val) {
this.$store.commit("used/updateDialogUsed", val);
},
},
snackbar: {
get() {
return this.$store.state.used.snackbar;
},
set(val) {
this.$store.commit("used/updateSnackbar", val);
},
},
dialogDelete: {
get() {
return this.$store.state.used.dialogDelete;
},
set(val) {
this.$store.commit("used/updateDialogDelete", val);
},
},
dialogConfirmation: {
get() {
return this.$store.state.used.dialogConfirmation;
},
set(val) {
this.$store.commit("used/updateDialogConfirmation", val);
},
},
xsearch: {
get() {
return this.$store.state.used.search;
},
set(val) {
this.$store.commit("used/updateSearch", val);
this.$store.dispatch("used/getItemUsed", {
itemUsageID: this.$store.state.usage.selectedItemUsage.ItemUsageID,
currentPage: this.$store.state.used.currentPage,
search: val,
statusConfirm: this.$store.state.used.statusConfirm,
startdate: this.$store.state.used.fStartDate,
enddate: this.$store.state.used.fEndDate
});
},
},
statusConfirmOptions() {
return this.$store.state.used.statusConfirmOptions;
},
statusConfirm: {
get() {
return this.$store.state.used.statusConfirm;
},
set(val) {
this.$store.commit("used/updateStatusConfirm", val);
this.$store.dispatch("used/getItemUsed", {
itemUsageID: this.$store.state.usage.selectedItemUsage.ItemUsageID,
currentPage: this.$store.state.used.currentPage,
search: this.$store.state.used.search,
statusConfirm: val,
startdate: this.$store.state.used.fStartDate,
enddate: this.$store.state.used.fEndDate
});
},
},
menuStartDate: {
get() {
return this.$store.state.used.menuStartDate;
},
set(val) {
this.$store.commit("used/updateMenuStartDate", val);
},
},
menuEndDate: {
get() {
return this.$store.state.used.menuEndDate;
},
set(val) {
this.$store.commit("used/updateMenuEndDate", val);
},
},
startDateFormatted() {
return this.formatDate(this.fStartDate);
},
endDateFormatted() {
return this.formatDate(this.fEndDate);
},
fStartDate: {
get() {
return this.$store.state.used.fStartDate;
},
set(val) {
this.$store.commit("used/updateFStartDate", val);
this.$store.dispatch("used/getItemUsed", {
itemUsageID: this.$store.state.usage.selectedItemUsage.ItemUsageID,
currentPage: this.$store.state.used.currentPage,
search: this.$store.state.used.search,
statusConfirm: this.$store.state.used.statusConfirm,
startdate: val,
enddate: this.$store.state.used.fEndDate
});
},
},
fEndDate: {
get() {
return this.$store.state.used.fEndDate;
},
set(val) {
this.$store.commit("used/updateFEndDate", val);
this.$store.dispatch("used/getItemUsed", {
itemUsageID: this.$store.state.usage.selectedItemUsage.ItemUsageID,
currentPage: this.$store.state.used.currentPage,
search: this.$store.state.used.search,
statusConfirm: this.$store.state.used.statusConfirm,
startdate: this.$store.state.used.fStartDate,
enddate: val
});
},
},
dStartDate: {
get() {
return this.$store.state.used.dStartDate;
},
set(val) {
this.$store.commit("used/updateDStartDate", val);
},
},
dEndDate: {
get() {
return this.$store.state.used.dEndDate;
},
set(val) {
this.$store.commit("used/updateDEndDate", val);
},
},
},
methods: {
formatDate(date) {
if (!date) return null
const [year, month, day] = date.split('-')
return `${day}-${month}-${year}`
},
deFormatedDate(date) {
if (!date) return null;
const [day, month, year] = date.split("-");
return `${year}-${month.padStart(2, "0")}-${day.padStart(2, "0")}`;
},
isSelected(item) {
return this.$store.state.used.selectedItemUsed.ItemUsedID === item.ItemUsedID;
},
selectMe(item) {
this.$store.commit("used/updateSelectedItemUsed", item);
},
convertMoney(money){
return one_money(money)
},
openDialogEdit(item) {
this.$store.commit("used/updateSelectedItemUsed", item);
this.selectedusedqty = item.ItemUsedQty;
this.dialogUsed = true;
},
closeDialog() {
this.dialogUsed = false;
this.selectedusedqty = 0;
this.$store.commit("used/updateSelectedItemUsed", {});
this.$store.commit("used/updateErrors", []);
},
checkErrorForm(val) {
let errors = this.$store.state.used.errors;
if (errors.includes(val)) {
return true;
} else {
return false;
}
},
saveItem() {
this.$store.commit("used/updateErrors", []);
var errors = this.$store.state.used.errors;
if (this.selectedusedqty <= 0) {
errors.push("requireUsageQty");
this.$store.commit("used/updateErrors", errors);
return;
}
let prm = {
ItemUsedQty: this.selectedusedqty,
itemUsedID: this.selectedItemUsed.ItemUsedID,
itemUsageID: this.$store.state.usage.selectedItemUsage.ItemUsageID,
currentPage: this.$store.state.used.currentPage,
search: this.$store.state.used.search,
statusConfirm: this.$store.state.used.statusConfirm,
startdate: this.$store.state.used.fStartDate,
enddate: this.$store.state.used.fEndDate
};
this.$store.dispatch("used/updateItemUsed", prm);
},
openDialogDelete(item) {
this.$store.commit("used/updateSelectedItemUsed", item);
this.dialogDelete = true;
},
deleteUsed() {
let prm = {
itemUsedID: this.selectedItemUsed.ItemUsedID,
itemUsageID: this.$store.state.usage.selectedItemUsage.ItemUsageID,
currentPage: this.$store.state.used.currentPage,
search: this.$store.state.used.search,
statusConfirm: this.$store.state.used.statusConfirm,
startdate: this.$store.state.used.fStartDate,
enddate: this.$store.state.used.fEndDate
};
this.$store.dispatch("used/deleteItemUsed", prm);
},
openConfirm(item) {
this.$store.commit("used/updateSelectedItemUsed", item);
this.dialogConfirmation = true;
},
requestConfirm() {
let prm = {
itemUsedID: this.selectedItemUsed.ItemUsedID,
itemUsageID: this.$store.state.usage.selectedItemUsage.ItemUsageID,
currentPage: this.$store.state.used.currentPage,
search: this.$store.state.used.search,
statusConfirm: this.$store.state.used.statusConfirm,
startdate: this.$store.state.used.fStartDate,
enddate: this.$store.state.used.fEndDate
};
this.$store.dispatch("used/confirmItemUsed", prm);
}
},
};
</script>

View File

@@ -0,0 +1,119 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="../../../libs/vendor/css/google-fonts.css">
<link rel="stylesheet" href="../../../libs/vendor/css/icomoon-fonts.css">
<link rel="stylesheet" href="../../../libs/vendor/css/vuetify.min.css">
<title>One</title>
</head>
<body>
<v-dialog
v-model="alertError"
width="350">
<v-card>
<v-card-title
class="headline error lighten-2"
primary-title>
Error
</v-card-title>
<v-card-text>
{{errMessage}}
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn
color="primary"
flat
@click="alertError = false">
Tutup
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
<div v-cloak id="app">
<v-app id="smartApp">
<one-navbar></one-navbar>
<v-container style="background: #F5E8DF!important" fluid fill-height class="pl-1 pr-1 pt-2 pb-2 mt-4">
<v-layout row wrap>
<v-flex xs6 class="left" fill-height pa-1>
<item-usage-listing></item-usage-listing>
</v-flex>
<v-flex xs6 class="right" fill-height pa-1>
<item-used-listing></item-used-listing>
</v-flex>
</v-layout>
</v-container>
<one-footer></one-footer>
</v-app>
</div>
<!-- Vendor -->
<script src="../../../libs/vendor/moment.min.js"></script>
<script src="../../../libs/vendor/numeral.min.js"></script>
<script src="../../../libs/vendor/moment-locale-id.js"></script>
<script src="../../../libs/vendor/lodash.js"></script>
<script src="../../../libs/vendor/axios.min.js"></script>
<script src="../../../libs/vendor/vue.js"></script>
<script src="../../../libs/vendor/vuex.js"></script>
<script src="../../../libs/vendor/vuetify.js"></script>
<script src="../../../libs/vendor/httpVueLoader.js"></script>
<script src="../../../libs/one_global.js"></script>
<!-- App Script -->
<script type="module">
import {
store
} from './store.js';
window.store = store;
new Vue({
store,
el: "#app",
methods: {},
components: {
'one-navbar': httpVueLoader('../../../apps/components/oneNavbarComponent.vue'),
'one-footer': httpVueLoader('../../../apps/components/oneFooter.vue'),
'item-usage-listing': httpVueLoader('./components/itemUsageList.vue'),
'item-used-listing': httpVueLoader('./components/itemUsedList.vue')
},
computed: {
alertError: {
get() {
return this.$store.state.usage.alertError;
},
set(val) {
this.$store.commit("usage/updateAlertError", val);
}
},
errMessage: {
get() {
return this.$store.state.usage.errMessage;
},
set(val) {
this.$store.commit("usage/updateErrMessage", val);
}
}
}
})
</script>
<style>
[v-cloak] {
display: none
}
</style>
</body>
</html>

View File

@@ -0,0 +1,290 @@
// 1 => LOADING
// 2 => DONE
// 3 => ERROR
import * as api from "../api/api.js";
export default {
namespaced: true,
state: {
errMessage: "",
alertError: false,
snackbar: {
state: false,
type: 'success',
message: '',
},
loadingAutocomplete: false,
divisionOptions: [],
selectedDivision: {},
user: one_user(),
currentPage: 1,
loadingStatus: 1, // 1 => LOADING, 2 => DONE, 3 => ERROR
itemUsageList: [],
selectedItemUsage: {},
totalPage: 0,
dialogUsage: false,
unitList: [],
selectedItemUnit: {},
usedQty: 0,
errors: [],
last_id: -1,
xsearch: "",
dialogform: false,
itemRequestList: [],
emptycheck: [],
dialogUnit: false,
selectedUnit: {},
unitOptions: [],
loadingUnit: false,
},
mutations: {
updateErrMessage(state, val) {
state.errMessage = val;
},
updateAlertError(state, val) {
state.alertError = val;
},
updateSnackbar(state, val) {
state.snackbar = val;
},
updateLoadingAutocomplete(state, val) {
state.loadingAutocomplete = val;
},
updateDivisionOptions(state, val) {
state.divisionOptions = val;
},
updateSelectedDivision(state, val) {
state.selectedDivision = val;
},
updateUser(state, val) {
state.user = val;
},
updateCurrentPage(state, val) {
state.currentPage = val;
},
updateLoadingStatus(state, val) {
state.loadingStatus = val;
},
updateItemUsageList(state, val) {
state.itemUsageList = val;
},
updateSelectedItemUsage(state, val) {
state.selectedItemUsage = val;
},
updateTotalPage(state, val) {
state.totalPage = val;
},
updateDialogUsage(state, val) {
state.dialogUsage = val;
},
updateUnitList(state, val) {
state.unitList = val;
},
updateSelectedItemUnit(state, val) {
state.selectedItemUnit = val;
},
updateUsedQty(state, val) {
state.usedQty = val;
},
updateErrors(state, val) {
state.errors = val;
},
update_last_id(state, val) {
state.last_id = val
},
updateXsearch(state, val) {
state.xsearch = val
},
updateDialogform(state, val) {
state.dialogform = val
},
updateItemRequestList(state, val) {
state.itemRequestList = val
},
updateEmptycheck(state, val) {
state.emptycheck = val
},
updateLoadingUnit(state, val) {
state.loadingUnit = val;
},
updateDialogUnit(state, val) {
state.dialogUnit = val;
},
updateSelectedUnit(state, val) {
state.selectedUnit = val;
},
updateUnitOptions(state, val) {
state.unitOptions = val;
}
},
actions: {
async getDivisionByUser(context) {
context.commit("updateLoadingAutocomplete", true)
try {
let payload = {}
payload.token = one_token()
payload.userId = context.state.user.M_UserID
let response = await api.getDivisionByUser(payload);
if (response.status != "OK") {
context.commit("updateLoadingAutocomplete", false)
context.commit("updateErrMessage", response.message);
context.commit("updateAlertError", true);
} else {
context.commit("updateLoadingAutocomplete", false)
let data = {
records: response.data.records,
selected: response.data.selected
};
context.commit("updateDivisionOptions", data.records);
context.commit("updateSelectedDivision", data.selected[0]);
}
} catch (e) {
context.commit("updateLoadingAutocomplete", false)
context.commit("updateErrMessage", e.message);
context.commit("updateAlertError", true);
}
},
async search(context, payload) {
context.commit("updateLoadingStatus", 1);
try {
// var payload = {
// token: one_token(),
// currentPage: context.state.currentPage,
// divisionID: context.state.selectedDivision == undefined ? 0 : context.state.selectedDivision.DivisionID,
// search: context.state.xsearch,
// };
payload.token = one_token();
let response = await api.search(payload);
if (response.status != "OK") {
context.commit("updateLoadingStatus", 3);
context.commit("updateErrMessage", response.message);
context.commit("updateAlertError", true);
} else {
context.commit("updateLoadingStatus", 2);
context.commit("updateErrMessage", "");
let data = {
records: response.data.records,
total_page: response.data.total_page,
};
context.commit("updateItemUsageList", data.records);
context.commit("updateTotalPage", data.total_page);
if (context.state.last_id == -1) {
if (response.data && response.data.records.length > 0) {
context.commit("updateSelectedItemUsage", response.data.records[0])
}
} else {
let idx = _.findIndex(response.data.records, function (o) {
return o.ItemUsageID == context.state.selectedItemUsage.ItemUsageID
});
if (idx >= 0) {
context.commit("updateSelectedItemUsage", response.data.records[idx]);
}
}
}
} catch (e) {
context.commit("updateLoadingStatus", 3);
context.commit("updateErrMessage", e.message);
context.commit("updateAlertError", true);
}
},
async getUnit(context, payload) {
context.commit("updateLoadingAutocomplete", 1);
try {
payload.token = one_token()
let response = await api.getUnit(payload);
if (response.status != "OK") {
context.commit("updateLoadingAutocomplete", 3);
context.commit("updateErrMessage", response.message);
context.commit("updateAlertError", true);
} else {
context.commit("updateLoadingAutocomplete", 2);
context.commit("updateErrMessage", "");
let data = {
records: response.data.records
};
context.commit("updateUnitList", data.records);
}
} catch (e) {
context.commit("updateLoadingAutocomplete", 3);
context.commit("updateErrMessage", e.message);
context.commit("updateAlertError", true);
}
},
async saveItemUsage(context, payload) {
context.commit("updateLoadingStatus", 1);
try {
payload.token = one_token();
let response = await api.saveItemUsage(payload);
if (response.status != "OK") {
context.commit("updateLoadingStatus", 3);
context.commit("updateErrMessage", response.message);
context.commit("updateAlertError", true);
} else {
context.commit("updateLoadingStatus", 2);
context.commit("updateErrMessage", "");
let data = {
records: response.data.records,
};
context.commit("updateDialogform", false);
context.commit("updateItemRequestList", []);
context.commit("update_last_id", payload.ItemUsageID)
context.commit("updateSnackbar", {
state: true,
type: 'success',
message: 'Item usage saved successfully.'
});
context.dispatch("search", {
currentPage: payload.currentPageUsage,
divisionID: payload.divisionID,
search: payload.searchUsage
});
context.dispatch("used/getItemUsed", {
itemUsageID: payload.ItemUsageID,
currentPage: payload.currentPage,
search: payload.search,
statusConfirm: payload.statusConfirm,
}, { root: true });
}
} catch (e) {
context.commit("updateLoadingStatus", 3);
context.commit("updateErrMessage", e.message);
context.commit("updateAlertError", true);
}
},
async getUnitByItemId(context, payload) {
context.commit("updateLoadingUnit", true)
context.commit("updateDialogUnit", true);
try {
payload.token = one_token();
let response = await api.getUnitByItemId(payload);
if (response.status != "OK") {
context.commit("updateLoadingUnit", false)
context.commit("updateDialogUnit", false);
context.commit("updateErrMessage", response.message);
context.commit("updateAlertError", true);
} else {
context.commit("updateLoadingUnit", false)
context.commit("updateErrMessage", "");
context.commit("updateUnitOptions", response.data.records);
context.commit("updateSelectedUnit", payload.selectedUnit);
}
} catch (e) {
context.commit("updateLoadingUnit", false)
context.commit("updateDialogUnit", false);
context.commit("updateErrMessage", e.message);
context.commit("updateAlertError", true);
}
}
}
};

View File

@@ -0,0 +1,280 @@
// 1 => LOADING
// 2 => DONE
// 3 => ERROR
import * as api from "../api/api.js";
export default {
namespaced: true,
state: {
errMessage: "",
alertError: false,
snackbar: {
state: false,
type: 'success',
message: '',
},
user: one_user(),
currentPage: 1,
loadingStatus: 1, // 1 => LOADING, 2 => DONE, 3 => ERROR
itemUsedList: [],
selectedItemUsed: {},
totalPageUsed: 0,
selectedUsedQty: 0,
dialogUsed: false,
errors: [],
dialogDelete: false,
dialogConfirmation: false,
search: "",
statusConfirmOptions: [
{ value: "X", text: "Semua" },
{ value: "N", text: "Belum Dikonfirmasi" },
{ value: "Y", text: "Sudah Dikonfirmasi" },
],
statusConfirm: "X",
menuStartDate: false,
menuEndDate: false,
fStartDate: moment(new Date()).format("YYYY-MM-DD"),
fEndDate: moment(new Date()).format("YYYY-MM-DD"),
dStartDate: new Date().toISOString().substring(0, 10),
dEndDate: new Date().toISOString().substring(0, 10)
},
mutations: {
updateErrMessage(state, val) {
state.errMessage = val;
},
updateAlertError(state, val) {
state.alertError = val;
},
updateSnackbar(state, val) {
state.snackbar = val;
},
updateLoadingAutocomplete(state, val) {
state.loadingAutocomplete = val;
},
updateDivisionOptions(state, val) {
state.divisionOptions = val;
},
updateSelectedDivision(state, val) {
state.selectedDivision = val;
},
updateUser(state, val) {
state.user = val;
},
updateCurrentPage(state, val) {
state.currentPage = val;
},
updateLoadingStatus(state, val) {
state.loadingStatus = val;
},
updateItemUsedList(state, val) {
state.itemUsedList = val;
},
updateSelectedItemUsed(state, val) {
state.selectedItemUsed = val;
},
updateTotalPageUsed(state, val) {
state.totalPageUsed = val;
},
updateSelectedUsedQty(state, val) {
state.selectedUsedQty = val;
},
updateDialogUsed(state, val) {
state.dialogUsed = val;
},
updateErrors(state, val) {
state.errors = val;
},
updateDialogDelete(state, val) {
state.dialogDelete = val;
},
updateDialogConfirmation(state, val) {
state.dialogConfirmation = val;
},
updateSearch(state, val) {
state.search = val;
state.currentPage = 1; // Reset to first page on new search
},
updateStatusConfirm(state, val) {
state.statusConfirm = val;
},
updateStatusConfirmOptions(state, val) {
state.statusConfirmOptions = val;
},
updateMenuStartDate(state, val) {
state.menuStartDate = val;
},
updateMenuEndDate(state, val) {
state.menuEndDate = val;
},
updateFStartDate(state, val) {
state.fStartDate = val;
},
updateFEndDate(state, val) {
state.fEndDate = val;
},
updateDStartDate(state, val) {
state.dStartDate = val;
},
updateDEndDate(state, val) {
state.dEndDate = val;
}
},
actions: {
async getItemUsed(context, payload) {
context.commit("updateLoadingStatus", 1);
try {
payload.token = one_token();
// var payload = {
// itemUsageID: context.state.usage.selectedItemUsage.ItemUsageID,
// currentPage: context.state.currentPage,
// search: context.state.search,
// statusConfirm: context.state.statusConfirm,
// token: one_token()
// };
let response = await api.getItemUsed(payload);
if (response.status != "OK") {
context.commit("updateLoadingStatus", 3);
context.commit("updateErrMessage", response.message);
context.commit("updateAlertError", true);
} else {
context.commit("updateLoadingStatus", 2);
context.commit("updateErrMessage", "");
let data = {
records: response.data.records,
total_page: response.data.total_page,
};
context.commit("updateItemUsedList", data.records);
context.commit("updateTotalPageUsed", data.total_page);
}
} catch (e) {
context.commit("updateLoadingStatus", 3);
context.commit("updateErrMessage", e.message);
context.commit("updateAlertError", true);
}
},
async updateItemUsed(context, payload) {
context.commit("updateLoadingStatus", 1);
try {
payload.token = one_token();
let response = await api.updateItemUsed(payload);
if (response.status != "OK") {
context.commit("updateLoadingStatus", 3);
context.commit("updateErrMessage", response.message);
context.commit("updateAlertError", true);
} else {
context.commit("updateLoadingStatus", 2);
context.commit("updateErrMessage", "");
context.commit("updateDialogUsed", false);
context.commit("updateSelectedItemUsed", {});
context.commit("updateSelectedUsedQty", 0);
context.commit("usage/update_last_id", payload.itemUsageID, { root: true });
context.commit("updateSnackbar", {
state: true,
type: 'success',
message: 'Item used berhasil diupdate.'
});
context.dispatch("usage/search",{}, { root: true });
context.dispatch("getItemUsed", {
itemUsageID: payload.itemUsageID,
currentPage: payload.currentPage,
search: payload.search,
statusConfirm: payload.statusConfirm,
startdate: payload.startdate,
enddate: payload.enddate
});
}
} catch (e) {
context.commit("updateLoadingStatus", 3);
context.commit("updateErrMessage", e.message);
context.commit("updateAlertError", true);
}
},
async deleteItemUsed(context, payload) {
context.commit("updateLoadingStatus", 1);
try {
payload.token = one_token();
let response = await api.deleteItemUsed(payload);
if (response.status != "OK") {
context.commit("updateLoadingStatus", 3);
context.commit("updateErrMessage", response.message);
context.commit("updateAlertError", true);
} else {
context.commit("updateLoadingStatus", 2);
context.commit("updateErrMessage", "");
context.commit("updateDialogDelete", false);
context.commit("updateSelectedItemUsed", {});
context.commit("usage/update_last_id", payload.itemUsageID, { root: true });
context.commit("updateSnackbar", {
state: true,
type: 'success',
message: 'Item used berhasil dihapus.'
});
context.dispatch("usage/search",{}, { root: true });
context.dispatch("getItemUsed", {
itemUsageID: payload.itemUsageID,
currentPage: payload.currentPage,
search: payload.search,
statusConfirm: payload.statusConfirm,
startdate: payload.startdate,
enddate: payload.enddate
});
}
} catch (e) {
context.commit("updateLoadingStatus", 3);
context.commit("updateErrMessage", e.message);
context.commit("updateAlertError", true);
}
},
async confirmItemUsed(context, payload) {
context.commit("updateLoadingStatus", 1);
try {
payload.token = one_token();
let response = await api.confirmItemUsed(payload);
if (response.status != "OK") {
context.commit("updateLoadingStatus", 3);
context.commit("updateErrMessage", response.message);
context.commit("updateAlertError", true);
} else {
context.commit("updateLoadingStatus", 2);
context.commit("updateErrMessage", "");
context.commit("updateSelectedItemUsed", {});
context.commit("updateDialogConfirmation", false);
context.commit("usage/update_last_id", payload.itemUsageID, { root: true });
context.commit("updateSnackbar", {
state: true,
type: 'success',
message: 'Item used berhasil dikonfirmasi.'
});
context.dispatch("getItemUsed", {
itemUsageID: payload.itemUsageID,
currentPage: payload.currentPage,
search: payload.search,
statusConfirm: payload.statusConfirm,
startdate: payload.startdate,
enddate: payload.enddate
});
}
} catch (e) {
context.commit("updateLoadingStatus", 3);
context.commit("updateErrMessage", e.message);
context.commit("updateAlertError", true);
}
}
}
};

View File

@@ -0,0 +1,13 @@
import usage from "./modules/usage.js";
import used from "./modules/used.js";
import system from "../../../apps/modules/system/system.js";
export const store = new Vuex.Store({
modules: {
usage: usage,
used: used,
system: system,
},
state: {},
mutations: {},
actions: {},
});

View File

@@ -0,0 +1,282 @@
const URL = "/one-api/mockup/masterdata/accounting/";
export async function getPeriode(prm) {
try {
var resp = await axios.post(URL + "Journalfixasset/getPeriode", prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function search(
token,
xdate,
periodeid,
current_page,
search,
branchCode,
regionalId
) {
try {
var resp = await axios.post(URL + "Journalfixasset/search", {
token: token,
xdate: xdate,
periodeid: periodeid,
current_page: current_page,
search: search,
branchCode: branchCode,
regionalId: regionalId
});
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function insertSales(branchCode, date, jurnalno) {
try {
var resp = await axios.get(
URL + `mediajurnalauto/insertSales/${branchCode}/${date}?isregen=1&jurnalno=${jurnalno}`
);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function getRegional(prm) {
try {
var resp = await axios.post(URL + "Journalfixasset/getRegional", prm);
if (resp.status !== 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function getBranch(prm) {
try {
var resp = await axios.post(URL + "Journalfixasset/getBranch", prm);
if (resp.status !== 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function getUserApproveLevel(params) {
try {
var resp = await axios.post(URL + "Journalfixasset/getUserApproveLevel", params);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (error) {
return {
status: "ERR",
message: error.message
};
}
}
export async function getListingCOA(params) {
try {
var resp = await axios.post(URL + "Journalfixasset/getListingCOA", params);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (error) {
return {
status: "ERR",
message: error.message
};
}
}
export async function requestEditJurnal(params) {
try {
const resp = await axios.post(URL + "JournalVerifEdit/requestEditJurnal", params);
if (resp.status !== 200) {
return {
status: "ERR",
message: resp.statusText
};
}
const data = resp.data;
return data;
} catch (error) {
return {
status: "ERR",
message: error.message
};
}
}
export async function saveEditJurnal(params) {
try {
var resp = await axios.post(URL + "JournalVerifEdit/saveEditJurnal", params);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (error) {
return {
status: "ERR",
message: error.message
};
}
}
export async function changeJurnalToPosted(params) {
try {
var resp = await axios.post(URL + "Journalfixasset/changeJurnalToPosted", params);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (error) {
return {
status: "ERR",
message: error.message
};
}
}
export async function getTotalJurnalNotPostedPerPeriod(params) {
try {
var resp = await axios.post(
URL + "Journalfixasset/getTotalJurnalNotPostedPerPeriod",
params
);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (error) {
return {
status: "ERR",
message: error.message
};
}
}
export async function closeJurnalPerPeriode(params) {
try {
var resp = await axios.post(URL + "Journalfixasset/closeJurnalPerPeriode", params);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (error) {
return {
status: "ERR",
message: error.message
};
}
}
export async function getDataJurnalNotClosedPerPeriod(params) {
try {
var resp = await axios.post(
URL + "Journalfixasset/getDataJurnalNotClosedPerPeriod",
params
);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (error) {
return {
status: "ERR",
message: error.message
};
}
}

View File

@@ -0,0 +1,76 @@
<template>
<v-dialog v-model="dialog_close_jurnal" persistent width="40vw">
<v-card>
<v-card-title class="headline grey lighten-2" primary-title>
TUTUP SEMUA JURNAL PADA PERIODE {{ selected_periode.periodeName }}
</v-card-title>
<v-card-text>
<div v-for="item in jurnal_to_close" :key="item.jurnalIsPosted">
<p v-if="item.jurnalIsPosted == 'N'">
Jumlah jurnal yang tidak dapat ditutup: <strong>{{ item.total_jurnal }}</strong>
</p>
<p v-else>
Jumlah jurnal yang dapat ditutup: <strong>{{ item.total_jurnal }}</strong>
</p>
</div>
<p>
Apakah anda yakin akan menutup semua jurnal yang dibuat di
<strong> {{ area_jurnal }} </strong> dalam rentang waktu <br>
<strong>{{ selected_periode.periode }}</strong> <br>
</p>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="error" outline flat @click="dialog_close_jurnal = false">Batal</v-btn>
<v-btn color="primary" dark @click="closeJurnal()">Ya</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script>
module.exports = {
data() {
return {
}
},
computed: {
selected_periode() {
return this.$store.state.journal.selected_periode
},
area_jurnal() {
const user = this.$store.state.journal.user
if (user.M_BranchID == '0') {
return `Regional ${user.S_RegionalName}`
} else {
return `Cabang ${user.M_BranchName}, Regional ${user.S_RegionalName}`
}
},
jurnal_to_close() {
return this.$store.state.journal.jurnal_to_close
},
dialog_close_jurnal: {
get() {
return this.$store.state.journal.dialog_close_jurnal
},
set(val) {
this.$store.commit("journal/update_dialog_close_jurnal", val)
}
}
},
methods: {
closeJurnal() {
var jurnal = this.jurnal_to_close.find(item => item.jurnalIsPosted === 'Y')
if (jurnal && Number(jurnal.total_jurnal) > 0) {
this.$store.dispatch("journal/closeJurnalPerPeriode", { typeid: jurnal.JurnalTypeID })
return;
}
this.$store.commit("journal/update_open_dialog_info", true);
this.$store.commit("journal/update_msg_info",
"Tidak ada jurnal yang dapat ditutup"
);
}
},
}
</script>

View File

@@ -0,0 +1,219 @@
<template>
<v-dialog v-model="dialog_edit_jurnal" persistetnt width="70vw">
<v-card>
<v-card-title class="headline grey lighten-2" primary-title>
EDIT JOURNAL FIX ASSET
</v-card-title>
<v-card-text>
<v-layout row wrap>
<v-flex xs6 pa-1 pr-3>
<div class="font-weight-bold">Company Name</div>
<div class="pa-2 grey lighten-2">
{{ selected_journal.M_BranchCompanyName }}
</div>
</v-flex>
<v-flex xs6 pa-1 pl-3>
<div class="font-weight-bold">Journal</div>
<div class="pa-2 grey lighten-2">
{{ selected_journal.jurnalTitle }}
</div>
</v-flex>
<v-flex xs6 pa-1 pr-3>
<div class="font-weight-bold">Regional</div>
<div class="pa-2 grey lighten-2">
{{ selected_journal.S_RegionalName }}
</div>
</v-flex>
<v-flex xs6 pa-1 pl-3>
<div class="font-weight-bold">Journal Date</div>
<div class="pa-2 grey lighten-2">
{{ selected_journal.jurnalDate }}
</div>
</v-flex>
<v-flex xs6 pa-1 pr-3>
<div class="font-weight-bold">Branch</div>
<div class="pa-2 grey lighten-2">
{{ selected_journal.M_BranchName }}
</div>
</v-flex>
<v-flex xs6 pa-1 pl-3>
<div class="font-weight-bold">Journal Type</div>
<div class="pa-2 grey lighten-2">
{{ selected_journal.JurnalTypeName }}
</div>
</v-flex>
</v-layout>
<v-layout row wrap mt-3>
<v-flex xs12>
<v-data-table
:headers="headerdetails" :items="journal_edit"
hide-actions class="elevation-1"
>
<template slot="items" slot-scope="props">
<tr>
<td class="text-xs-center pa-2">{{ props.item.coaAccountNo }}</td>
<td class="text-xs-left pa-2">
<v-autocomplete
label="Account" hide-details outline
v-model="props.item.coaAccountNo"
:items="list_coa" item-text="coaDescription"
item-value="coaAccountNo"
></v-autocomplete>
</td>
<td class="text-xs-left pa-2">{{ props.item.jurnalAddOnValue }}</td>
<td class="text-xs-center pa-2">{{ props.item.coaCurrencyCode }}</td>
<td class="text-xs-right pa-2">{{ formatCurrency(props.item.jurnalTxDebit) }}</td>
<td class="text-xs-right pa-2">{{ formatCurrency(props.item.jurnalTxCredit) }}</td>
</tr>
</template>
<template v-slot:footer>
<tr>
<td colspan="4" class="font-weight-bold pa-2">TOTAL</td>
<td class="text-xs-right pa-2 font-weight-bold">
{{ formatCurrency(xsummary.debit) }}
</td>
<td class="text-xs-right pa-2 font-weight-bold">
{{ formatCurrency(xsummary.credit) }}
</td>
</tr>
<tr>
<td colspan="5" class="font-weight-bold pa-2">BALANCE</td>
<td width="10%" class="text-xs-right pa-2 font-weight-bold">
{{ formatCurrency(xsummary.balance) }}
</td>
</tr>
</template>
</v-data-table>
</v-flex>
</v-layout>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="error" outline flat @click="closeEditDialog()">Batal</v-btn>
<v-btn color="primary" dark @click="simpanEditDialog()">Simpan</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script>
module.exports = {
data() {
return {
headerdetails: [
{
text: "AKUN", align: "center", sortable: false,
value: "action", width: "20%", class: "pa-2 pl-2 blue lighten-3 white--text",
},
{
text: "DESKRIPSI", align: "center", sortable: false,
value: "mr", width: "25%", class: "pa-2 blue lighten-3 white--text",
},
{
text: "INFO", align: "center", sortable: false,
value: "lab", width: "15%", class: "pa-2 blue lighten-3 white--text",
},
{
text: "CURRENCY", align: "center", sortable: false,
value: "lab", width: "10%", class: "pa-2 blue lighten-3 white--text",
},
{
text: "DEBIT", align: "center", sortable: false,
value: "lab", width: "15%", class: "pa-2 blue lighten-3 white--text",
},
{
text: "CREDIT", align: "center", sortable: false,
value: "lab", width: "15%", class: "pa-2 blue lighten-3 white--text",
}
]
}
},
computed: {
dialog_edit_jurnal: {
get() {
return this.$store.state.journal.dialog_edit_journal;
},
set(val) {1
this.$store.commit("journal/update_dialog_edit_journal", val);
}
},
selected_journal: {
get() {
return this.$store.state.journal.selected_journal;
},
set(val) {
this.$store.commit("journal/update_selected_journal", val);
},
},
journal_edit: {
get() {
return this.$store.state.journal.journal_edit
},
set(val) {
this.$store.commit("journal/update_journal_edit", val);
}
},
selected_periode() {
return this.$store.state.journal.selected_periode
},
xsummary() {
return this.$store.state.journal.summary
},
list_coa() {
return this.$store.state.journal.list_coa
}
},
methods: {
formatCurrency(val) {
const price = parseFloat(val);
const IDR = new Intl.NumberFormat("id-ID", {
style: "currency",
currency: "IDR"
});
return `${IDR.format(price)}`;
},
simpanEditDialog() {
const originaldetail = this.selected_journal.detailtx;
const editnewdetails = this.journal_edit;
const listcoa = this.list_coa;
const originalMap = new Map();
for (const item of originaldetail) {
originalMap.set(item.jurnalTxID, item.coaAccountNo);
}
const coaMap = new Map();
for (const coaItem of listcoa) {
coaMap.set(coaItem.coaAccountNo, coaItem);
}
const editeddetail = editnewdetails.flatMap(detail => {
const originalAcc = originalMap.get(detail.jurnalTxID);
if (originalAcc !== detail.coaAccountNo) {
const accMatch = coaMap.get(detail.coaAccountNo);
if (accMatch) {
return [{
jurnalID: detail.jurnalTxJurnalID,
jurnalTxID: detail.jurnalTxID,
coaID: accMatch.coaID,
coaDescription: accMatch.coaDescription,
coaAccountNo: accMatch.coaAccountNo
}]
} else {
return [];
}
} else {
return [];
}
})
this.$store.dispatch("journal/saveEditJurnal", editeddetail);
},
closeEditDialog() {
this.selected_journal = {};
this.journal_edit = [];
this.dialog_edit_jurnal = false;
}
},
}
</script>

View File

@@ -0,0 +1,68 @@
<template>
<v-dialog v-model="dialog_confirm_posting" persistetnt width="40vw">
<v-card>
<v-card-title class="headline grey lighten-2" primary-title>
POSTING SEMUA JURNAL PADA PERIODE {{ selected_periode.periodeName }}
</v-card-title>
<v-card-text>
<div v-for="item in total_jurnal_not_posted" :key="item.jurnalEditStatus">
<p v-if="item.jurnalEditStatus == 'N'">
Jumlah jurnal yang dapat diposting: <strong>{{ item.total_jurnal }}</strong>
</p>
<p v-if="item.jurnalEditStatus == 'Y'">
Jumlah jurnal yang tidak dapat diposting: <strong>{{ item.total_jurnal }}</strong>
(belum diverifikasi setelah edit)
</p>
</div>
<p>
Apakah anda yakin akan melakukan posting semua jurnal yang dibuat dalam rentang waktu
<strong>{{ selected_periode.periode }}</strong> ?
</p>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="error" outline flat @click="dialog_confirm_posting = false">Batal</v-btn>
<v-btn color="primary" dark @click="postingJurnal()">Ya</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script>
module.exports = {
data() {
return {
}
},
computed: {
selected_periode() {
return this.$store.state.journal.selected_periode
},
total_jurnal_not_posted() {
return this.$store.state.journal.total_jurnal_not_posted
},
dialog_confirm_posting: {
get() {
return this.$store.state.journal.dialog_confirm_posting;
},
set(val) {1
this.$store.commit("journal/update_dialog_confirm_posting", val);
}
},
},
methods: {
postingJurnal() {
var jurnal = this.total_jurnal_not_posted.find(jrnl => jrnl.jurnalEditStatus === 'N')
if (jurnal && Number(jurnal.total_jurnal) > 0) {
this.$store.dispatch("journal/postingJurnal", { typeid: jurnal.JurnalTypeID });
return;
}
this.$store.commit("journal/update_open_dialog_info", true);
this.$store.commit("journal/update_msg_info",
"semua jurnal para periode ini sudah terposting"
);
}
},
}
</script>

View File

@@ -0,0 +1,58 @@
<template>
<v-dialog v-model="dialog_request_edit" persistent width="40vw">
<v-card>
<v-card-title class="headline grey lighten-2" primary-title>
REQUEST EDIT JURNAL {{ selected_journal.jurnalNo }}
</v-card-title>
<v-card-text>
<p v-if="selected_journal.JurnalRequestEditStatusEdit == 'approved'">
Jurnal ini sudah pernah diedit sebelumnya oleh:
{{ selected_journal.JurnalRequestEditStaffName }} <br>
Apakah anda yakin akan mengajukan permintaan untuk melakukan perubahan lagi? <br>
Nomor: <strong>{{ selected_journal.jurnalNo }}</strong> <br>
Judul: <strong>{{ selected_journal.jurnalTitle }}</strong> <br>
Deskripsi: {{ selected_journal.jurnalDescription }} <br>
</p>
<p v-else>
Apakah anda yakin akan mengajukan permintaan untuk melakukan perubahan jurnal: <br>
Nomor: <strong>{{ selected_journal.jurnalNo }}</strong> <br>
Judul: <strong>{{ selected_journal.jurnalTitle }}</strong> <br>
Deskripsi: {{ selected_journal.jurnalDescription }} <br>
</p>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="error" outline @click="dialog_request_edit = false">Batal</v-btn>
<v-btn color="primary" dark @click="requestEdit()">Ya</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script>
module.exports = {
data() {
return {
}
},
computed: {
dialog_request_edit: {
get() {
return this.$store.state.journal.dialog_request_edit
},
set(val) {
this.$store.commit("journal/update_dialog_request_edit", val)
}
},
selected_journal() {
return this.$store.state.journal.selected_journal
}
},
methods: {
requestEdit() {
this.$store.dispatch("journal/requestEditJurnal");
}
},
}
</script>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,73 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>One</title>
<link rel="stylesheet" href="../../../libs/vendor/css/google-fonts.css">
<link rel="stylesheet" href="../../../libs/vendor/css/vuetify.min.css">
</head>
<body>
<div v-cloak id="app">
<v-app id="smartApp">
<one-navbar></one-navbar>
<v-content class="blue lighten-5">
<v-container fluid fill-height class="pl-1 pr-1 pt-2 pb-2">
<v-layout row wrap>
<v-flex xs12 class="center" fill-height pa-1>
<!-- komponen -->
<one-media-journal></one-media-journal>
</v-flex>
</v-layout>
</v-container>
</v-content>
<one-footer> </one-footer>
</v-app>
</div>
<!-- Vendor -->
<script src="../../../libs/vendor/moment.min.js"></script>
<script src="../../../libs/vendor/numeral.min.js"></script>
<script src="../../../libs/vendor/moment-locale-id.js"></script>
<script src="../../../libs/vendor/lodash.js"></script>
<script src="../../../libs/vendor/axios.min.js"></script>
<script src="../../../libs/vendor/vue.js"></script>
<script src="../../../libs/vendor/vuex.js"></script>
<script src="../../../libs/vendor/vuetify.js"></script>
<script src="../../../libs/vendor/httpVueLoader.js"></script>
<script src="../../../libs/one_global.js"></script>
<!-- App Script -->
<?php
$ts = "?ts=" . Date("ymdhis");
?>
<script type="module">
import {
store
} from './store.js<?php echo $ts ?>';
//for testing
// window.store = store;
new Vue({
store,
el: '#app',
components: {
'one-navbar': httpVueLoader('../../../apps/components/oneNavbarComponent.vue'),
'one-footer': httpVueLoader('../../../apps/components/oneFooter.vue'),
'one-media-journal': httpVueLoader('./components/oneMediaJournalList.vue')
}
})
</script>
<style>
[v-cloak] {
display: none
}
.left {}
.right {}
</style>
</body>
</html>

View File

@@ -0,0 +1,582 @@
// 1 => LOADING
// 2 => DONE
// 3 => ERROR
import * as api from "../api/journal.js";
export default {
namespaced: true,
state: {
search_status: 0,
current_page: 1,
x_search: "",
search_error_message: "",
last_id: -1,
coas: [],
total_coas: 0,
selected_coa: {},
dialog_form_coa: false,
act: "new",
save_status: 0,
save_error_message: "",
errors: [],
alert_success: false,
msg_success: "",
alert_error: false,
dialog_error: false,
open_print: false,
// ----
xdate: moment(new Date()).format("YYYY-MM-DD"),
end_date: moment(new Date()).format("YYYY-MM-DD"),
journals: [],
selected_journal: {},
summary: { debit: 0, credit: 0, balance: 0 },
dialog_form_detail: false,
periodeList: [],
selected_periode: {},
loading: false,
dialog_form_periode: false,
autocomplete_status: 0,
search_status: 0,
total_journal: 0,
user: one_user(),
jurnaldetails: [],
dialog_error_jurnal: false,
msgerrjurnallist: [],
regionals: [],
selected_regional: {},
branchs: [],
selected_branch: {},
xsearch: "",
open_dialog_info: false,
msg_info: "",
// --
dialog_edit_journal: false,
user_level: {},
list_coa: [],
journal_edit: [],
dialog_confirm_posting: false,
total_jurnal_not_posted: [],
dialog_request_edit: false,
// ---
dialog_close_jurnal: false,
jurnal_to_close: []
},
mutations: {
update_search_status(state, val) {
state.search_status = val;
},
update_current_page(state, val) {
state.current_page = val;
},
update_x_search(state, val) {
state.x_search = val;
state.current_page = 1;
},
update_search_error_message(state, val) {
state.search_error_message = val;
},
update_last_id(state, val) {
state.last_id = val;
},
update_coas(state, val) {
state.coas = val;
},
update_total_coas(state, val) {
state.total_coas = val;
},
update_selected_coa(state, val) {
state.selected_coa = val;
},
update_dialog_form_coa(state, val) {
state.dialog_form_coa = val;
},
update_act(state, val) {
state.act = val;
},
update_save_status(state, val) {
state.save_status = val;
},
update_save_error_message(state, val) {
state.save_error_message = val;
},
update_errors(state, val) {
state.errors = val;
},
update_alert_success(state, val) {
state.alert_success = val;
},
update_msg_success(state, val) {
state.msg_success = val;
},
update_alert_error(state, val) {
state.alert_error = val;
},
update_dialog_error(state, val) {
state.dialog_error = val;
},
update_open_print(state, value) {
state.open_print = value;
},
// ---
update_xdate(state, val) {
state.xdate = val;
},
update_end_date(state, val) {
state.end_date = val;
},
update_journals(state, val) {
state.journals = val;
},
update_selected_journal(state, val) {
state.selected_journal = val;
},
update_summary(state, val) {
state.summary = val;
},
update_dialog_form_detail(state, val) {
state.dialog_form_detail = val;
},
update_periodeList(state, val) {
state.periodeList = val;
},
update_selected_periode(state, val) {
state.selected_periode = val;
},
update_loading(state, val) {
state.loading = val;
},
update_dialog_form_periode(state, val) {
state.dialog_form_periode = val;
},
update_autocomplete_status(state, val) {
state.autocomplete_status = val;
},
update_search_status(state, val) {
state.search_status = val;
},
update_total_journal(state, val) {
state.total_journal = val;
},
update_user(state, val) {
state.user = val;
},
update_jurnaldetails(state, val) {
state.jurnaldetails = val;
},
update_dialog_error_jurnal(state, val) {
state.dialog_error_jurnal = val;
},
update_msgerrjurnallist(state, val) {
state.msgerrjurnallist = val;
},
update_regionals(state, val) {
state.regionals = val;
},
update_selected_regional(state, val) {
state.selected_regional = val;
},
update_branchs(state, val) {
state.branchs = val;
},
update_selected_branch(state, val) {
state.selected_branch = val;
},
update_xsearch(state, val) {
state.xsearch = val;
state.current_page = 1;
},
update_open_dialog_info(state, val) {
state.open_dialog_info = val;
},
update_msg_info(state, val) {
state.msg_info = val;
},
// --
update_dialog_edit_journal(state, val) {
state.dialog_edit_journal = val;
},
update_user_level(state, val) {
state.user_level = val;
},
update_list_coa(state, val) {
state.list_coa = val;
},
update_journal_edit(state, val) {
state.journal_edit = val;
},
update_dialog_confirm_posting(state, val) {
state.dialog_confirm_posting = val;
},
update_total_jurnal_not_posted(state, val) {
state.total_jurnal_not_posted = val;
},
update_dialog_request_edit(state, val) {
state.dialog_request_edit = val;
},
update_dialog_close_jurnal(state, val) {
state.dialog_close_jurnal = val;
},
update_jurnal_to_close(state, val) {
state.jurnal_to_close = val;
}
},
actions: {
async getPeriode(context) {
context.commit("update_autocomplete_status", 1);
try {
let prm = {};
prm.token = one_token();
let resp = await api.getPeriode(prm);
if (resp.status != "OK") {
context.commit("update_autocomplete_status", 3);
} else {
context.commit("update_autocomplete_status", 2);
let data = resp.data;
context.commit("update_periodeList", resp.data);
// Ambil bulan dan tahun sekarang
let now = new Date();
let currentMonth = now.getMonth() + 1; // getMonth() dimulai dari 0 (Jan = 0)
let currentYear = now.getFullYear().toString(); // Ambil tahun dalam bentuk string
// Cari data dengan periodeMonth dan periodeYear yang cocok
let selectedPeriode = data.find(
(p) =>
p.periodeMonth == currentMonth.toString() &&
p.periodeYear == currentYear
);
// Jika tidak ditemukan, gunakan data pertama sebagai default
if (!selectedPeriode) {
selectedPeriode = data[0];
}
context.commit("update_selected_periode", selectedPeriode);
}
} catch (e) {
context.commit("update_autocomplete_status", 3);
}
},
async search(context, prm) {
context.commit("update_search_status", 1);
try {
let resp = await api.search(
one_token(),
prm.xdate,
prm.periodeid,
prm.current_page,
prm.search,
prm.branchCode,
prm.regionalId
);
if (resp.status != "OK") {
context.commit("update_search_status", 3);
context.commit("update_search_error_message", resp.message);
} else {
context.commit("update_search_status", 2);
context.commit("update_search_error_message", "");
let data = {
records: resp.data.records,
total: resp.data.total
};
context.commit("update_journals", data.records);
context.commit("update_total_journal", data.total);
}
} catch (e) {
context.commit("update_search_status", 3);
context.commit("update_search_error_message", e.message);
}
},
async insertSales(context, prm) {
context.commit("update_save_status", 1);
try {
let branchCode = prm.branchCode;
let date = prm.date;
let jurnalno = prm.jurnalno;
let resp = await api.insertSales(branchCode, date, jurnalno);
if (resp.status != "OK") {
context.commit("update_save_status", 3);
context.commit("update_save_error_message", resp.message);
context.commit("update_alert_error", true);
} else {
context.commit("update_save_status", 2);
context.commit("update_save_error_message", resp.message);
let data = {
total: resp.data.total
};
context.commit("update_alert_success", true);
var msg = resp.data.msg;
context.commit("update_msg_success", msg);
context.dispatch("search", {
current_page: context.state.current_page,
xdate: context.state.xdate,
periodeid: context.state.selected_periode.id
});
}
} catch (e) {
context.commit("update_save_status", 3);
context.commit("update_save_error_message", e.message);
context.commit("update_alert_error", true);
}
},
async getRegional(context) {
context.commit("update_autocomplete_status", 1);
try {
let resp = await api.getRegional({
token: one_token(),
regionalId: context.state.user.S_RegionalID
});
if (resp.status != "OK") {
context.commit("update_search_error_message", resp.message);
context.commit("update_autocomplete_status", 3);
} else {
context.commit("update_search_error_message", "");
context.commit("update_autocomplete_status", 2);
let data = {
records: resp.data.records,
selected: resp.data.selected
};
context.commit("update_regionals", data.records);
context.commit("update_selected_regional", data.selected);
}
} catch (e) {
context.commit("update_search_error_message", e.message);
context.commit("update_autocomplete_status", 3);
}
},
async getBranch(context) {
context.commit("update_autocomplete_status", 1);
try {
let resp = await api.getBranch({
token: one_token(),
regionalId: context.state.selected_regional.S_RegionalID,
branchCode: context.state.user.M_BranchCode
});
if (resp.status != "OK") {
context.commit("update_search_error_message", resp.message);
context.commit("update_autocomplete_status", 3);
} else {
context.commit("update_search_error_message", "");
context.commit("update_autocomplete_status", 2);
let data = {
records: resp.data.records,
selected: resp.data.selected
};
context.commit("update_branchs", data.records);
context.commit("update_selected_branch", data.selected);
}
} catch (e) {
context.commit("update_search_error_message", e.message);
context.commit("update_autocomplete_status", 3);
}
},
async postingJurnal(context, typeid) {
try {
let param = {
token: one_token(),
jurnalTypeID: typeid,
periodeID: context.state.selected_periode.id
};
const resp = await api.changeJurnalToPosted(param);
if (resp.status != "OK") {
context.commit("update_alert_error", true);
context.commit("update_save_error_message", resp.message);
} else {
context.commit("update_msg_success", resp.data);
context.commit("update_alert_success", true);
context.dispatch("search", {
branchCode: context.state.selected_branch.M_BranchCode ?? "",
regionalId: context.state.selected_regional.S_RegionalID,
search: context.state.x_search,
current_page: context.state.current_page,
xdate: context.state.xdate,
periodeid: context.state.selected_periode.id
});
context.commit("update_total_jurnal_not_posted", []);
context.commit("update_dialog_confirm_posting", false);
}
} catch (error) {
context.commit("update_alert_error", true);
context.commit("update_save_error_message", error.message);
}
},
async getUserApprovalLevel(context) {
try {
let param = { token: one_token() };
const resp = await api.getUserApproveLevel(param);
if (resp.status != "OK") {
context.commit("update_alert_error", true);
context.commit("update_save_error_message", resp.message);
} else {
context.commit("update_user_level", resp.data);
}
} catch (error) {
context.commit("update_alert_error", true);
context.commit("update_save_error_message", error.message);
}
},
async getListingCOA(context) {
try {
let param = {
token: one_token(),
keyword: ""
};
const resp = await api.getListingCOA(param);
if (resp.status != "OK") {
context.commit("update_alert_error", true);
context.commit("update_save_error_message", resp.message);
} else {
context.commit("update_list_coa", resp.data);
}
} catch (error) {
context.commit("update_alert_error", true);
context.commit("update_save_error_message", error.message);
}
},
async requestEditJurnal(context) {
try {
let param = {
token: one_token(),
jurnalID: context.state.selected_journal.jurnalID,
staffID: context.state.user.M_UserID,
staffName: context.state.user.M_UserUsername
};
const resp = await api.requestEditJurnal(param);
if (resp.status != "OK") {
context.commit("update_alert_error", true);
context.commit("update_save_error_message", resp.message);
} else {
context.commit("update_msg_success", resp.data);
context.commit("update_alert_success", true);
context.commit("update_dialog_request_edit", false);
}
} catch (error) {
context.commit("update_alert_error", true);
context.commit("update_save_error_message", error.message);
}
},
async saveEditJurnal(context, newdetail) {
try {
let param = {
token: one_token(),
jurnalID: context.state.selected_journal.jurnalID,
jurnalRequestEditID: context.state.selected_journal.JurnalRequestEditID,
oldjurnaltx: context.state.selected_journal.detailtx,
newjurnaltx: newdetail
};
const resp = await api.saveEditJurnal(param);
if (resp.status != "OK") {
context.commit("update_alert_error", true);
context.commit("update_save_error_message", resp.message);
} else {
context.dispatch("search", {
branchCode: context.state.selected_branch.M_BranchCode ?? "",
regionalId: context.state.selected_regional.S_RegionalID,
search: context.state.x_search,
current_page: context.state.current_page,
xdate: context.state.xdate,
periodeid: context.state.selected_periode.id
});
context.commit("update_dialog_edit_journal", false);
context.commit("update_msg_success", resp.data);
context.commit("update_alert_success", true);
}
} catch (error) {
context.commit("update_alert_error", true);
context.commit("update_save_error_message", error.message);
}
},
async totalJurnalNotPostedPerPeriod(context) {
try {
let param = {
token: one_token(),
periodeID: context.state.selected_periode.id
};
const resp = await api.getTotalJurnalNotPostedPerPeriod(param);
if (resp.status != "OK") {
context.commit("update_alert_error", true);
context.commit("update_save_error_message", resp.message);
} else {
context.commit("update_total_jurnal_not_posted", resp.data.total_jurnal ?? []);
}
} catch (error) {
context.commit("update_alert_error", true);
context.commit("update_save_error_message", error.message);
}
},
async getDataJurnalNotClosedPerPeriod(context) {
try {
let param = {
token: one_token(),
periodeID: context.state.selected_periode.id
};
const resp = await api.getDataJurnalNotClosedPerPeriod(param);
if (resp.status != "OK") {
context.commit("update_alert_error", true);
context.commit("update_save_error_message", resp.message);
} else {
context.commit("update_jurnal_to_close", resp.data ?? []);
}
} catch (error) {
context.commit("update_alert_error", true);
context.commit("update_save_error_message", error.message);
}
},
async closeJurnalPerPeriode(context, typeid) {
try {
let param = {
token: one_token(),
jurnalTypeID: typeid,
periodeID: context.state.selected_periode.id
};
const resp = await api.closeJurnalPerPeriode(param);
if (resp.status != "OK") {
context.commit("update_alert_error", true);
context.commit("update_save_error_message", resp.message);
} else {
context.commit("update_msg_success", resp.data);
context.commit("update_alert_success", true);
context.dispatch("search", {
branchCode: context.state.selected_branch.M_BranchCode ?? "",
regionalId: context.state.selected_regional.S_RegionalID,
search: context.state.x_search,
current_page: context.state.current_page,
xdate: context.state.xdate,
periodeid: context.state.selected_periode.id
});
context.commit("update_jurnal_to_close", []);
context.commit("update_dialog_close_jurnal", false);
}
} catch (error) {
context.commit("update_alert_error", true);
context.commit("update_save_error_message", error.message);
}
}
}
};

View File

@@ -0,0 +1,23 @@
// State
// data ...
// Mutations
//
//
// Actions
import journal from "./modules/journal.js";
import system from "../../../apps/modules/system/system.js";
export const store = new Vuex.Store({
modules: {
journal: journal,
system:system
},
state: {
},
mutations: {
},
actions: {
}
});

View File

@@ -0,0 +1,101 @@
const URL = "/one-api/fixedasset/";
export async function getPeriode(prm) {
try {
var resp = await axios.post(URL + 'journalfixedassetv2/getPeriode', prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function search(token, xdate, periodeid, branchid, regionalid) {
try {
var resp = await axios.post(URL + 'journalfixedassetv2/search', {
token:token,
xdate:xdate,
periodeid:periodeid,
branchid:branchid,
regionalid:regionalid
});
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function getdetail(prm) {
try {
var resp = await axios.post(URL + 'journalfixedassetv2/getdetail', prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function insertSales(branchCode, date, jurnalno) {
try {
var resp = await axios.get(URL + `mediajurnalauto/insertSales/${branchCode}/${date}?isregen=1&jurnalno=${jurnalno}`);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function addConfirm(prm) {
try {
var resp = await axios.post(URL + 'journalfixedassetv2/addConfirm', prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}

View File

@@ -0,0 +1,864 @@
<template>
<div style="width: 100%;" class="">
<!-- SNACKBAR -->
<v-snackbar
v-model="snackbar"
:timeout="5000"
:multi-line="false"
:vertical="false"
:top="true"
>
{{ msgSnackbar }}
<v-btn flat @click="updateAlertSuccess(false)"> Tutup </v-btn>
</v-snackbar>
<!-- ERROR DIALOG -->
<v-dialog v-model="dialog_error" max-width="500px">
<v-card>
<v-card-title>
<span>ERROR !</span>
<v-spacer></v-spacer>
</v-card-title>
<v-divider></v-divider>
<div class="ma-3 red--text">{{ msgError }}</div>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="primary" flat @click="dialog_error = false"
>Tutup</v-btn
>
</v-card-actions>
</v-card>
</v-dialog>
<!-- END ERROR DIALOG -->
<v-toolbar dark class="blue lighten-3 white--text">
<v-toolbar-title class="white--text">DETAIL</v-toolbar-title>
<v-spacer></v-spacer>
</v-toolbar>
<v-card class="pa-2">
<v-layout row align-center>
<span>
</span>
<span>
</span>
<v-flex text-xs-right>
</v-flex>
</v-layout>
</v-card>
<v-card class="pa-2 mt-2">
<v-layout row wrap class="scroll-container" style="max-height:600px;overflow: auto;">
<v-flex xs12 pl-2 pr-2 pt-2 pb-2>
<v-data-table
:headers="headers"
:items="xbranchlists"
:loading="isLoading"
hide-actions
class="elevation-1"
>
<template v-slot:items="props">
<tr>
<td class="text-xs-center pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)">
{{ props.item.M_BranchName }}
<span v-if="props.item.ErrStatus === 'Y'">
<v-tooltip bottom>
<template v-slot:activator="{ on, attrs }">
<v-icon v-bind="attrs" v-on="on" class="ml-1" color="red" small @click="viewError(props.item)">error</v-icon>
</template>
<span>error information</span>
</v-tooltip>
</span>
<!-- <span v-if="props.item.ErrStatus === 'Y'"><v-icon small color="red" @click="viewError(props.item)">error</v-icon></span> -->
</td>
<td class="text-xs-left pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)">
{{ props.item.coaDescription }}
</td>
<td class="text-xs-center pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)">
{{ props.item.totaldepretext }}
</td>
</tr>
</template>
</v-data-table>
</v-flex>
</v-layout>
<v-divider></v-divider>
<v-pagination
style="margin-top: 10px; margin-bottom: 10px;"
v-model="curr_page"
:length="xtotal_page"
></v-pagination>
</v-card>
<template>
<v-dialog v-model="dialogformdetail" persistent width="70vw">
<v-card>
<v-card-title class="headline grey lighten-2" primary-title>
DETAIL JOURNAL PAYMENT VOUCHER
</v-card-title>
<v-card-text>
<v-layout wrap>
<v-flex xs12>
<v-layout>
<v-flex xs6 pa-1 pr-3>
<div class="font-weight-bold">
<div>Company Name</div>
</div>
<div class="pa-2 grey lighten-2">
<div>{{ selected_journal.M_BranchCompanyName }}</div>
</div>
<!-- <v-text-field :value="xcompanyname" label="Company Name"></v-text-field> -->
</v-flex>
<v-flex xs6 pa-1 pl-3>
<div class="font-weight-bold">
<div>Journal</div>
</div>
<div class="pa-2 grey lighten-2">
<div>{{ selected_journal.jurnalTitle }}</div>
</div>
<!-- <v-text-field :value="xrefno" label="Ref No"></v-text-field> -->
</v-flex>
</v-layout>
</v-flex>
<v-flex xs12>
<v-layout>
<v-flex xs6 pa-1 pr-3>
<div class="font-weight-bold">
<div>Regional</div>
</div>
<div class="pa-2 grey lighten-2">
<div>{{ selected_journal.S_RegionalName }}</div>
</div>
<!-- <v-text-field :value="xjournalno" label="Journal No"></v-text-field> -->
</v-flex>
<v-flex xs6 pa-1 pl-3>
<div class="font-weight-bold">
<div>Journal Date</div>
</div>
<div class="pa-2 grey lighten-2">
<div>{{ selected_journal.jurnalDate }}</div>
</div>
<!-- <v-text-field :value="xjournaldate" label="Journal Date"></v-text-field> -->
</v-flex>
</v-layout>
</v-flex>
<v-flex xs12>
<v-layout>
<v-flex xs6 pa-1 pr-3>
<div class="font-weight-bold">
<div>Branch</div>
</div>
<div class="pa-2 grey lighten-2">
<div>{{ selected_journal.M_BranchName }}</div>
</div>
<!-- <v-text-field :value="xaccount" label="Account"></v-text-field> -->
</v-flex>
<v-flex xs6 pa-1 pl-3>
<div class="font-weight-bold">
<div>Journal Type</div>
</div>
<div class="pa-2 grey lighten-2">
<div>{{ selected_journal.JurnalTypeName }}</div>
</div>
<!-- <v-text-field :value="xjournaltype" label="Journal Type"></v-text-field> -->
</v-flex>
</v-layout>
</v-flex>
</v-layout>
<v-layout row wrap pt-3>
<v-flex>
<v-data-table
:headers="headerdetails"
:items="xjurnaldetails"
hide-actions
class="elevation-1"
>
<template slot="items" slot-scope="props">
<td
class="text-xs-center pa-2"
>
{{ props.item.coaAccountNo }}
</td>
<td
class="text-xs-left pa-2"
>
{{ props.item.jurnalTxDescription }}
</td>
<td
class="text-xs-left pa-2"
>
{{ props.item.jurnalAddOnValue }}
</td>
<td
class="text-xs-center pa-2"
>
{{ props.item.coaCurrencyCode }}
</td>
<td
class="text-xs-right pa-2"
>
Rp {{ convertMoney(props.item.jurnalTxDebit) }}
</td>
<td
class="text-xs-right pa-2"
>
Rp {{ convertMoney(props.item.jurnalTxCredit) }}
</td>
</template>
<template v-slot:footer>
<tr>
<td colspan="4" class="font-weight-bold pa-2">TOTAL</td>
<td class="text-xs-right pa-2 font-weight-bold">
Rp {{ convertMoney(xsummary.debit) }}
</td>
<td class="text-xs-right pa-2 font-weight-bold">
Rp {{ convertMoney(xsummary.credit) }}
</td>
</tr>
<tr>
<td colspan="5" class="font-weight-bold pa-2">BALANCE</td>
<td width="10%" class="text-xs-right pa-2 font-weight-bold">
Rp {{ convertMoney(xsummary.balance) }}
</td>
</tr>
</template>
</v-data-table>
</v-flex>
</v-layout>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="error" flat @click="closeDialogFormDetail()">Tutup</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<template>
<v-layout row justify-center>
<v-dialog v-model="dialogperiode" persistent max-width="550px">
<v-toolbar dark class="blue lighten-3 white--text">
<v-toolbar-title class="white--text">PILIH PERIODE</v-toolbar-title>
<v-spacer></v-spacer>
</v-toolbar>
<v-card>
<v-card-text class="pt-4 pb-2">
<v-layout wrap>
<v-flex xs12>
<v-autocomplete
v-model="selectedPeriode"
:items="periodeList"
outline
hide-details
color="blue"
label="Periode"
item-text="periodeName"
return-object
>
<template slot="item" slot-scope="{ item }">
<template>
<v-list-tile-content>
<v-list-tile-title v-text="item.periodeName"></v-list-tile-title>
<v-list-tile-sub-title
v-text="item.periode"
></v-list-tile-sub-title>
</v-list-tile-content>
</template>
</template>
</v-autocomplete>
</v-flex>
</v-layout>
</v-card-text>
<v-card-actions class="pr-3">
<v-spacer></v-spacer>
<v-btn color="error" flat @click="closeDialogPeriode()">TUTUP</v-btn>
<v-btn color="primary" @click="choosePeriode()">PILIH</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-layout>
</template>
<template>
<v-layout row justify-center>
<v-dialog v-model="dialogconfirm" persistent max-width="550px">
<v-toolbar dark class="blue lighten-3 white--text">
<v-toolbar-title class="white--text">KONFIRMASI</v-toolbar-title>
<v-spacer></v-spacer>
</v-toolbar>
<v-card>
<v-card-text class="pt-4 pb-2">
<v-layout wrap>
<v-flex xs12>
Yakin, mau konfirmasi fixed aset periode <span class="font-weight-bold">{{ this.$store.state.journal.selected_periode.periode }}</span> ?
</v-flex>
</v-layout>
</v-card-text>
<v-card-actions class="pr-3">
<v-spacer></v-spacer>
<v-btn color="error" flat @click="closeDialogConfirm()">TUTUP</v-btn>
<v-btn color="primary" @click="addConfirm()">YAKIN</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-layout>
</template>
<template>
<v-layout row justify-center>
<v-dialog v-model="dialogerror" persistent max-width="650px">
<v-toolbar dark class="red lighten-1 white--text">
<v-toolbar-title class="white--text">ERROR INFORMATION</v-toolbar-title>
<v-spacer></v-spacer>
</v-toolbar>
<v-card>
<v-card-text class="pt-4 pb-2">
<v-layout wrap>
<v-flex xs12>
<div v-for="(error, index) in msgerrjurnallist" :key="index">
<p><strong>Error Type:</strong> {{ error.JurnalErr_Msg.err_type }}</p>
<p><strong>Message:</strong> {{ error.JurnalErr_Msg.err_msg }}</p>
<v-divider></v-divider>
</div>
</v-flex>
</v-layout>
</v-card-text>
<v-card-actions class="pr-3">
<v-spacer></v-spacer>
<v-btn color="error" flat @click="closeDialogError()">TUTUP</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-layout>
</template>
<template>
<v-dialog v-model="dialogregenerate" max-width="30%">
<v-card>
<v-card-title class="headline grey lighten-2 pt-2 pb-2" primary-title>
Peringatan !
</v-card-title>
<v-card-text class="pt-2 pb-2">
<v-layout row>
<v-flex xs12 d-flex>
<v-layout row>
<v-flex pb-1 xs12>
<v-layout row>
<v-flex pt-2 pr-2 xs12>
Yakin, mau konfirmasi regenerate jurnal <span class="font-weight-bold">{{ msgalertgenerate }}</span> ?
</v-flex>
</v-layout>
</v-flex>
</v-layout>
</v-flex>
</v-layout>
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="error" flat @click="dialogregenerate = false">
Tutup
</v-btn>
<v-btn
color="primary"
@click="doRegenerateJurnal()"
>
Ya
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<one-dialog-print :title="printtitle" :width="printwidth" :height="700" :status="openprint" :urlprint="urlprint"
@close-dialog-print="openprint = false"></one-dialog-print>
</div>
</template>
<style scoped>
</style>
<script>
module.exports = {
components: {
'one-dialog-print': httpVueLoader('../../common/oneDialogPrintX.vue')
},
mounted() {
this.$store.dispatch("journal/getPeriode")
.then(() => {
// Setelah `selected_periode` diupdate dengan data pertama
this.$store.dispatch("journal/search", {
current_page: this.$store.state.journal.current_page,
xdate: this.$store.state.journal.xdate,
periodeid: this.$store.state.journal.selected_periode.id,
branchid: this.$store.state.journal.user.M_BranchID,
regionalid: this.$store.state.journal.user.S_RegionalID,
});
})
.catch(error => {
console.error("Error fetching periode:", error);
});
},
data: () => ({
menufilterdate: false,
menufilterdateend: false,
date: new Date().toISOString().substr(0, 10),
search_city: "",
oldlabel: "",
selectedData: {},
debit: 0,
credit: 0,
btnUpload: false,
xperiodeid: "",
search_item_periode: "",
xyearandmonth: "",
xperiode: "",
formatreport: "pdf",
urlprint: "",
printtitle: '',
printwidth: '100%',
dialogregenerate: false,
msgalertgenerate: "",
xbranchCode: "",
xsearchDate: "",
xFa_ItemID: "",
xname: "",
headers: [
{
text: "CABANG",
align: "center",
sortable: false,
value: "action",
width: "5%",
class: "pa-1 blue lighten-3 white--text",
},
{
text: "COA",
align: "center",
sortable: false,
value: "mr",
width: "15%",
class: "pa-1 blue lighten-3 white--text",
},
{
text: "TOTAL",
align: "center",
sortable: false,
value: "lab",
width: "10%",
class: "pa-1 blue lighten-3 white--text",
}
],
headerdetails: [
{
text: "AKUN",
align: "center",
sortable: false,
value: "action",
width: "20%",
class: "pa-2 pl-2 blue lighten-3 white--text",
},
{
text: "DESKRIPSI",
align: "center",
sortable: false,
value: "mr",
width: "25%",
class: "pa-2 blue lighten-3 white--text",
},
{
text: "INFO",
align: "center",
sortable: false,
value: "lab",
width: "15%",
class: "pa-2 blue lighten-3 white--text",
},
{
text: "CURRENCY",
align: "center",
sortable: false,
value: "lab",
width: "10%",
class: "pa-2 blue lighten-3 white--text",
},
{
text: "DEBIT",
align: "center",
sortable: false,
value: "lab",
width: "15%",
class: "pa-2 blue lighten-3 white--text",
},
{
text: "CREDIT",
align: "center",
sortable: false,
value: "lab",
width: "15%",
class: "pa-2 blue lighten-3 white--text",
}
],
}),
computed: {
isLoading() {
return this.$store.state.journal.search_status === 1;
},
periodeList() {
return this.$store.state.journal.periodeList
},
dialogperiode() {
return this.$store.state.journal.dialog_form_periode
},
dialogconfirm() {
return this.$store.state.journal.dialog_form_confirm
},
selectedPeriode: {
get() {
return this.$store.state.journal.selected_periode
},
set(val) {
this.$store.commit("journal/update_selected_periode", val)
},
},
dialogformdetail() {
return this.$store.state.journal.dialog_form_detail
},
xjournals() {
return this.$store.state.journal.journals
},
xsummary() {
return this.$store.state.journal.summary
},
ishide: {
get() {
return this.$store.state.journal.ishide
},
set(val) {
this.$store.commit("journal/update_ishide", val)
}
},
xdate: {
get() {
return this.$store.state.journal.xdate
},
set(val) {
this.$store.commit("journal/update_xdate", val)
}
},
xdateend: {
get() {
return this.$store.state.journal.end_date
},
set(val) {
this.$store.commit("journal/update_end_date", val)
}
},
filterComputedDateFormatted() {
return this.formatDate(this.xdate)
},
filterComputedDateFormattedEnd() {
return this.formatDate(this.xdateend)
},
curr_page: {
get() {
return this.$store.state.journal.current_page;
},
set(val) {
this.$store.commit("journal/update_current_page", val);
this.$store.dispatch("journal/search", {
current_page: this.$store.state.journal.current_page,
xdate: this.$store.state.journal.xdate,
periodeid: this.$store.state.journal.selected_periode.id,
branchid: this.$store.state.journal.user.M_BranchID,
regionalid: this.$store.state.journal.user.S_RegionalID,
});
},
},
xtotal_page: {
get() {
return this.$store.state.journal.total_journal;
},
set(val) {
this.$store.commit("journal/update_total_journal", val);
},
},
selected_journal: {
get() {
return this.$store.state.journal.selected_journal;
},
set(val) {
this.$store.commit("journal/update_selected_journal", val);
},
},
user() {
return this.$store.state.journal.user
},
xjurnaldetails() {
return this.$store.state.journal.jurnaldetails
},
xbranchlists() {
return this.$store.state.journal.branchlists
},
openprint: {
get() {
return this.$store.state.journal.open_print;
},
set(val) {
this.$store.commit("journal/update_open_print", val);
},
},
dialogerror: {
get() {
return this.$store.state.journal.dialog_error_jurnal;
},
set(val) {
this.$store.commit("journal/update_dialog_error_jurnal", val);
},
},
msgerrjurnallist() {
return this.$store.state.journal.msgerrjurnallist;
},
snackbar: {
get() {
return this.$store.state.journal.alert_success;
},
set(val) {
this.$store.commit("journal/update_alert_success", val);
},
},
msgSnackbar() {
return this.$store.state.journal.msg_success;
},
dialog_error: {
get() {
return this.$store.state.journal.alert_error;
},
set(val) {
this.$store.commit("journal/update_alert_error", val);
},
},
msgError() {
return this.$store.state.journal.save_error_message;
},
},
methods: {
convertMoney(money){
return one_money(money)
},
doPrint(val) {
// console.log(val)
this.printwidth = 1028
this.printtitle = ""
let user = one_user()
tm = Date.now()
var rptname = 'rpt_jurnal_pendapatan_001'
var formatrpt = this.formatreport
this.urlprint = "/birt/run?__report=report/one/accounting/" + rptname + ".rptdesign&__format=" + formatrpt + "&PID=" + val.Fa_ItemID + "&username=" + user.M_StaffName + "&tm=" + tm
// console.log(this.urlprint)
this.$store.commit("journal/update_open_print", true)
},
isSelected(p) {
return p.Fa_ItemID == this.$store.state.journal.selected_journal.Fa_ItemID;
},
selectMe(sc) {
this.$store.commit("journal/update_selected_journal", sc);
},
thr_search: _.debounce(function () {
this.$store.dispatch("journal/search", {
current_page: this.$store.state.journal.current_page,
xdate: this.xdate,
periodeid: this.selectedPeriode.id,
branchid: this.$store.state.journal.user.M_BranchID,
regionalid: this.$store.state.journal.user.S_RegionalID,
})
}, 1000),
closeDialogPeriode() {
this.$store.commit("journal/update_dialog_form_periode", false)
},
openDialogPeriode() {
this.$store.commit("journal/update_dialog_form_periode", true)
},
openDialogConfirm() {
this.$store.commit("journal/update_dialog_form_confirm", true)
},
closeDialogConfirm() {
this.$store.commit("journal/update_dialog_form_confirm", false)
},
addConfirm() {
this.xperiodeid = this.$store.state.journal.selected_periode.id
this.xyearandmonth = this.$store.state.journal.selected_periode.yearandmonth
this.xperiode = this.$store.state.journal.selected_periode.periode
this.$store.commit("journal/update_dialog_form_confirm", false)
this.$store.dispatch("journal/addConfirm", {
current_page: this.$store.state.journal.current_page,
xdate: this.xdate,
periodeid: this.selectedPeriode.id,
details : this.$store.state.journal.journals
})
},
choosePeriode() {
this.xperiodeid = this.$store.state.journal.selected_periode.id
this.xyearandmonth = this.$store.state.journal.selected_periode.yearandmonth
this.xperiode = this.$store.state.journal.selected_periode.periode
// console.log(this.xperiodeid)
this.$store.commit("journal/update_dialog_form_periode", false)
this.$store.dispatch("journal/search", {
current_page: this.$store.state.journal.current_page,
xdate: this.xdate,
periodeid: this.selectedPeriode.id,
branchid: this.$store.state.journal.user.M_BranchID,
regionalid: this.$store.state.journal.user.S_RegionalID,
})
},
closeDialogFormDetail() {
this.$store.commit("journal/update_dialog_form_detail", false)
},
vieDetail(val) {
this.$store.commit("journal/update_dialog_form_detail", true)
this.$store.commit("journal/update_jurnaldetails", val.detailtx)
let totalDebit = 0;
let totalKredit = 0;
for (let item = 0; item < val.detailtx.length; item++) {
const element = val.detailtx[item];
totalDebit += parseFloat(element.jurnalTxDebit || '0');
totalKredit += parseFloat(element.jurnalTxCredit || '0');
}
let totalBalance = totalDebit - totalKredit;
let summary = {
debit: totalDebit,
credit: totalKredit,
balance: totalBalance,
};
this.$store.commit("journal/update_summary", summary);
},
formatDate(date) {
if (!date) return null
const [year, month, day] = date.split('-')
return `${day}-${month}-${year}`
},
deFormatedDate(date) {
if (!date) return null
const [day, month, year] = date.split('-')
return `${year}-${month.padStart(2, '0')}-${day.padStart(2, '0')}`
},
isObjectEmpty(val) {
let obj = val;
return Object.keys(obj).length === 0 && obj.constructor === Object;
},
isPeriodeEmpty() {
return Object.keys(this.selectedPeriode).length === 0;
},
openDialogEdit(val) {
this.selectedData = val;
if (val.type == "DB") {
this.debit = val.value;
this.credit = 0;
}
if (val.type == "CR") {
this.credit = val.value;
this.debit = 0;
}
this.dialogEdit = true;
},
formatCurrency(val) {
// Format the price above to USD using the locale, style, and currency.
let price = parseFloat(val);
let USDollar = new Intl.NumberFormat("id-ID", {
style: "currency",
currency: "IDR",
});
// console.log(
// `The formated version of ${price} is ${USDollar.format(price)}`
// );
return `${USDollar.format(price)}`;
},
resetInputFile() {
document.getElementById("csv_file").value = null;
this.dialogImport = false;
},
viewError(val) {
this.$store.commit("journal/update_dialog_error_jurnal", true)
this.$store.commit("journal/update_msgerrjurnallist", val.ErrMsg)
},
closeDialogError() {
this.$store.commit("journal/update_dialog_error_jurnal", false)
},
openGenerate(val) {
// console.log(val)
this.xbranchCode = val.jurnalM_BranchCode
this.xsearchDate = this.deFormatedDate(val.jurnalDate)
this.xFa_ItemID = val.Fa_ItemID
this.xname = val.jurnalTitle
this.msgalertgenerate = val.jurnalTitle
this.dialogregenerate = true
},
doRegenerateJurnal() {
this.dialogregenerate = false
// console.log(prm)
let user = one_user();
console.log(user.M_BranchID)
if (user.M_BranchID === 0 || user.M_BranchID === '0') {
// generate regional
this.$store.dispatch("journal/insertSales", {branchCode: 'ZZ', date: this.xsearchDate, jurnalno: this.selected_journal.jurnalNo})
} else {
// generate cabang
this.$store.dispatch("journal/insertSales", {branchCode: this.xbranchCode, date: this.xsearchDate, jurnalno: this.selected_journal.jurnalNo})
}
},
updateAlertSuccess(val) {
this.$store.commit("journal/update_alert_success", val);
},
},
watch: {
xdate(val, old) {
this.xdate = val
this.thr_search()
},
xdateend(val, old) {
this.xdateend = val
this.thr_search()
},
// search_item_periode(val, old) {
// if (val == old) return
// if (!val) return
// if (val.length < 1) {
// this.$store.dispatch("journal/getPeriode", this.search_item_periode)
// return this.thr_search_periode()
// }
// if (val.length > 1) {
// this.$store.dispatch("journal/getPeriode", this.search_item_periode)
// return this.thr_search_periode()
// }
// }
},
};
</script>

View File

@@ -0,0 +1,956 @@
<template>
<div style="width: 100%;" class="">
<!-- SNACKBAR -->
<v-snackbar
v-model="snackbar"
:timeout="5000"
:multi-line="false"
:vertical="false"
:top="true"
>
{{ msgSnackbar }}
<v-btn flat @click="updateAlertSuccess(false)"> Tutup </v-btn>
</v-snackbar>
<!-- ERROR DIALOG -->
<v-dialog v-model="dialog_error" max-width="500px">
<v-card>
<v-card-title>
<span>ERROR !</span>
<v-spacer></v-spacer>
</v-card-title>
<v-divider></v-divider>
<div class="ma-3 red--text">{{ msgError }}</div>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="primary" flat @click="dialog_error = false"
>Tutup</v-btn
>
</v-card-actions>
</v-card>
</v-dialog>
<!-- END ERROR DIALOG -->
<v-toolbar dark class="blue lighten-3 white--text">
<v-toolbar-title class="white--text">CONFIRM</v-toolbar-title>
<v-spacer></v-spacer>
</v-toolbar>
<v-card class="pa-2">
<v-layout row align-center>
<span>
<v-chip outline color="teal">
{{ this.$store.state.journal.selected_periode.yearandmonth }}
</v-chip>
</span>
<span>
<v-chip outline color="red">
{{ this.$store.state.journal.selected_periode.periode }}
</v-chip>
<v-btn color="orange" class="white--text" @click="openDialogPeriode()">Period</v-btn>
</span>
<v-flex text-xs-right>
<v-btn v-if="this.ishide === 'N'" color="green" class="white--text" @click="openDialogConfirm()">Confirm</v-btn>
</v-flex>
</v-layout>
</v-card>
<v-card class="pa-2 mt-2">
<v-layout row wrap class="scroll-container" style="max-height:600px;overflow: auto;">
<v-flex xs12 pl-2 pr-2 pt-2 pb-2>
<v-data-table
:headers="headers"
:items="xjournals"
:loading="isLoading"
hide-actions
class="elevation-1"
>
<template v-slot:items="props">
<tr>
<td class="text-xs-center pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)">
{{ props.item.CodeFixedAsset }}
<span v-if="props.item.ErrStatus === 'Y'">
<v-tooltip bottom>
<template v-slot:activator="{ on, attrs }">
<v-icon v-bind="attrs" v-on="on" class="ml-1" color="red" small @click="viewError(props.item)">error</v-icon>
</template>
<span>error information</span>
</v-tooltip>
</span>
<!-- <span v-if="props.item.ErrStatus === 'Y'"><v-icon small color="red" @click="viewError(props.item)">error</v-icon></span> -->
</td>
<td class="text-xs-left pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)">
{{ props.item.Fa_ItemNote }}
<p>{{ props.item.NameFixedAsset }}</p>
</td>
<td class="text-xs-center pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)">
{{ props.item.AcquisitionPrice_text }}
</td>
<td class="text-xs-center pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)">
{{ props.item.BookValue_text }}
</td>
<td class="text-xs-center pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)">
{{ props.item.depresiasi_text }}
</td>
<td class="text-xs-center pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)">
{{ props.item.akumulasi_text }}
</td>
<td class="text-xs-center pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)">
{{ props.item.nilai_saat_ini_text }}
</td>
<td class="text-xs-center pa-2"
v-bind:class="{ 'amber lighten-4': isSelected(props.item) }"
@click="selectMe(props.item)">
<span v-if="props.item.Fa_ItemIsConfirm == 'Y'">
<v-chip
color="indigo"
class="ml-0"
outline
small
>
confirmed
</v-chip>
</span>
<span v-else="props.item.Fa_ItemIsConfirm == 'N'">
<v-chip
color="red"
class="ml-0"
outline
small
>
not confirmed
</v-chip>
</span>
</td>
</tr>
</template>
</v-data-table>
</v-flex>
</v-layout>
<v-divider></v-divider>
<v-pagination
style="margin-top: 10px; margin-bottom: 10px;"
v-model="curr_page"
:length="xtotal_page"
></v-pagination>
</v-card>
<template>
<v-dialog v-model="dialogformdetail" persistent width="70vw">
<v-card>
<v-card-title class="headline grey lighten-2" primary-title>
DETAIL JOURNAL PAYMENT VOUCHER
</v-card-title>
<v-card-text>
<v-layout wrap>
<v-flex xs12>
<v-layout>
<v-flex xs6 pa-1 pr-3>
<div class="font-weight-bold">
<div>Company Name</div>
</div>
<div class="pa-2 grey lighten-2">
<div>{{ selected_journal.M_BranchCompanyName }}</div>
</div>
<!-- <v-text-field :value="xcompanyname" label="Company Name"></v-text-field> -->
</v-flex>
<v-flex xs6 pa-1 pl-3>
<div class="font-weight-bold">
<div>Journal</div>
</div>
<div class="pa-2 grey lighten-2">
<div>{{ selected_journal.jurnalTitle }}</div>
</div>
<!-- <v-text-field :value="xrefno" label="Ref No"></v-text-field> -->
</v-flex>
</v-layout>
</v-flex>
<v-flex xs12>
<v-layout>
<v-flex xs6 pa-1 pr-3>
<div class="font-weight-bold">
<div>Regional</div>
</div>
<div class="pa-2 grey lighten-2">
<div>{{ selected_journal.S_RegionalName }}</div>
</div>
<!-- <v-text-field :value="xjournalno" label="Journal No"></v-text-field> -->
</v-flex>
<v-flex xs6 pa-1 pl-3>
<div class="font-weight-bold">
<div>Journal Date</div>
</div>
<div class="pa-2 grey lighten-2">
<div>{{ selected_journal.jurnalDate }}</div>
</div>
<!-- <v-text-field :value="xjournaldate" label="Journal Date"></v-text-field> -->
</v-flex>
</v-layout>
</v-flex>
<v-flex xs12>
<v-layout>
<v-flex xs6 pa-1 pr-3>
<div class="font-weight-bold">
<div>Branch</div>
</div>
<div class="pa-2 grey lighten-2">
<div>{{ selected_journal.M_BranchName }}</div>
</div>
<!-- <v-text-field :value="xaccount" label="Account"></v-text-field> -->
</v-flex>
<v-flex xs6 pa-1 pl-3>
<div class="font-weight-bold">
<div>Journal Type</div>
</div>
<div class="pa-2 grey lighten-2">
<div>{{ selected_journal.JurnalTypeName }}</div>
</div>
<!-- <v-text-field :value="xjournaltype" label="Journal Type"></v-text-field> -->
</v-flex>
</v-layout>
</v-flex>
</v-layout>
<v-layout row wrap pt-3>
<v-flex>
<v-data-table
:headers="headerdetails"
:items="xjurnaldetails"
hide-actions
class="elevation-1"
>
<template slot="items" slot-scope="props">
<td
class="text-xs-center pa-2"
>
{{ props.item.coaAccountNo }}
</td>
<td
class="text-xs-left pa-2"
>
{{ props.item.jurnalTxDescription }}
</td>
<td
class="text-xs-left pa-2"
>
{{ props.item.jurnalAddOnValue }}
</td>
<td
class="text-xs-center pa-2"
>
{{ props.item.coaCurrencyCode }}
</td>
<td
class="text-xs-right pa-2"
>
Rp {{ convertMoney(props.item.jurnalTxDebit) }}
</td>
<td
class="text-xs-right pa-2"
>
Rp {{ convertMoney(props.item.jurnalTxCredit) }}
</td>
</template>
<template v-slot:footer>
<tr>
<td colspan="4" class="font-weight-bold pa-2">TOTAL</td>
<td class="text-xs-right pa-2 font-weight-bold">
Rp {{ convertMoney(xsummary.debit) }}
</td>
<td class="text-xs-right pa-2 font-weight-bold">
Rp {{ convertMoney(xsummary.credit) }}
</td>
</tr>
<tr>
<td colspan="5" class="font-weight-bold pa-2">BALANCE</td>
<td width="10%" class="text-xs-right pa-2 font-weight-bold">
Rp {{ convertMoney(xsummary.balance) }}
</td>
</tr>
</template>
</v-data-table>
</v-flex>
</v-layout>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="error" flat @click="closeDialogFormDetail()">Tutup</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<template>
<v-layout row justify-center>
<v-dialog v-model="dialogperiode" persistent max-width="550px">
<v-toolbar dark class="blue lighten-3 white--text">
<v-toolbar-title class="white--text">PILIH PERIODE</v-toolbar-title>
<v-spacer></v-spacer>
</v-toolbar>
<v-card>
<v-card-text class="pt-4 pb-2">
<v-layout wrap>
<v-flex xs12>
<v-autocomplete
v-model="selectedPeriode"
:items="periodeList"
outline
hide-details
color="blue"
label="Periode"
item-text="periodeName"
return-object
>
<template slot="item" slot-scope="{ item }">
<template>
<v-list-tile-content>
<v-list-tile-title v-text="item.periodeName"></v-list-tile-title>
<v-list-tile-sub-title
v-text="item.periode"
></v-list-tile-sub-title>
</v-list-tile-content>
</template>
</template>
</v-autocomplete>
</v-flex>
</v-layout>
</v-card-text>
<v-card-actions class="pr-3">
<v-spacer></v-spacer>
<v-btn color="error" flat @click="closeDialogPeriode()">TUTUP</v-btn>
<v-btn color="primary" @click="choosePeriode()">PILIH</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-layout>
</template>
<template>
<v-layout row justify-center>
<v-dialog v-model="dialogconfirm" persistent max-width="550px">
<v-toolbar dark class="blue lighten-3 white--text">
<v-toolbar-title class="white--text">KONFIRMASI</v-toolbar-title>
<v-spacer></v-spacer>
</v-toolbar>
<v-card>
<v-card-text class="pt-4 pb-2">
<v-layout wrap>
<v-flex xs12>
Yakin, mau konfirmasi fixed aset periode <span class="font-weight-bold">{{ this.$store.state.journal.selected_periode.periode }}</span> ?
</v-flex>
</v-layout>
</v-card-text>
<v-card-actions class="pr-3">
<v-spacer></v-spacer>
<v-btn color="error" flat @click="closeDialogConfirm()">TUTUP</v-btn>
<v-btn color="primary" @click="addConfirm()">YAKIN</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-layout>
</template>
<template>
<v-layout row justify-center>
<v-dialog v-model="dialogerror" persistent max-width="650px">
<v-toolbar dark class="red lighten-1 white--text">
<v-toolbar-title class="white--text">ERROR INFORMATION</v-toolbar-title>
<v-spacer></v-spacer>
</v-toolbar>
<v-card>
<v-card-text class="pt-4 pb-2">
<v-layout wrap>
<v-flex xs12>
<div v-for="(error, index) in msgerrjurnallist" :key="index">
<p><strong>Error Type:</strong> {{ error.JurnalErr_Msg.err_type }}</p>
<p><strong>Message:</strong> {{ error.JurnalErr_Msg.err_msg }}</p>
<v-divider></v-divider>
</div>
</v-flex>
</v-layout>
</v-card-text>
<v-card-actions class="pr-3">
<v-spacer></v-spacer>
<v-btn color="error" flat @click="closeDialogError()">TUTUP</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-layout>
</template>
<template>
<v-dialog v-model="dialogregenerate" max-width="30%">
<v-card>
<v-card-title class="headline grey lighten-2 pt-2 pb-2" primary-title>
Peringatan !
</v-card-title>
<v-card-text class="pt-2 pb-2">
<v-layout row>
<v-flex xs12 d-flex>
<v-layout row>
<v-flex pb-1 xs12>
<v-layout row>
<v-flex pt-2 pr-2 xs12>
Yakin, mau konfirmasi regenerate jurnal <span class="font-weight-bold">{{ msgalertgenerate }}</span> ?
</v-flex>
</v-layout>
</v-flex>
</v-layout>
</v-flex>
</v-layout>
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="error" flat @click="dialogregenerate = false">
Tutup
</v-btn>
<v-btn
color="primary"
@click="doRegenerateJurnal()"
>
Ya
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<one-dialog-print :title="printtitle" :width="printwidth" :height="700" :status="openprint" :urlprint="urlprint"
@close-dialog-print="openprint = false"></one-dialog-print>
</div>
</template>
<style scoped>
</style>
<script>
module.exports = {
components: {
'one-dialog-print': httpVueLoader('../../common/oneDialogPrintX.vue')
},
mounted() {
this.$store.dispatch("journal/getPeriode")
.then(() => {
// Setelah `selected_periode` diupdate dengan data pertama
this.$store.dispatch("journal/search", {
current_page: this.$store.state.journal.current_page,
xdate: this.$store.state.journal.xdate,
periodeid: this.$store.state.journal.selected_periode.id,
branchid: this.$store.state.journal.user.M_BranchID,
regionalid: this.$store.state.journal.user.S_RegionalID,
});
})
.catch(error => {
console.error("Error fetching periode:", error);
});
},
data: () => ({
menufilterdate: false,
menufilterdateend: false,
date: new Date().toISOString().substr(0, 10),
search_city: "",
oldlabel: "",
selectedData: {},
debit: 0,
credit: 0,
btnUpload: false,
xperiodeid: "",
search_item_periode: "",
xyearandmonth: "",
xperiode: "",
formatreport: "pdf",
urlprint: "",
printtitle: '',
printwidth: '100%',
dialogregenerate: false,
msgalertgenerate: "",
xbranchCode: "",
xsearchDate: "",
xFa_ItemID: "",
xname: "",
headers: [
{
text: "CODE",
align: "center",
sortable: false,
value: "action",
width: "5%",
class: "pa-1 blue lighten-3 white--text",
},
{
text: "NAME",
align: "center",
sortable: false,
value: "mr",
width: "15%",
class: "pa-1 blue lighten-3 white--text",
},
{
text: "NILAI PEROLEHAN",
align: "center",
sortable: false,
value: "lab",
width: "10%",
class: "pa-1 blue lighten-3 white--text",
},
{
text: "NILAI BUKU SAAT INI",
align: "center",
sortable: false,
value: "lab",
width: "10%",
class: "pa-1 blue lighten-3 white--text",
},
{
text: "DEPRESIASI",
align: "center",
sortable: false,
value: "lab",
width: "10%",
class: "pa-1 blue lighten-3 white--text",
},
{
text: "AKUMULASI",
align: "center",
sortable: false,
value: "lab",
width: "10%",
class: "pa-1 blue lighten-3 white--text",
},
{
text: "NILAI SAAT INI",
align: "center",
sortable: false,
value: "lab",
width: "10%",
class: "pa-1 blue lighten-3 white--text",
},
{
text: "STATUS",
align: "center",
sortable: false,
value: "lab",
width: "10%",
class: "pa-1 blue lighten-3 white--text",
}
],
headerdetails: [
{
text: "AKUN",
align: "center",
sortable: false,
value: "action",
width: "20%",
class: "pa-2 pl-2 blue lighten-3 white--text",
},
{
text: "DESKRIPSI",
align: "center",
sortable: false,
value: "mr",
width: "25%",
class: "pa-2 blue lighten-3 white--text",
},
{
text: "INFO",
align: "center",
sortable: false,
value: "lab",
width: "15%",
class: "pa-2 blue lighten-3 white--text",
},
{
text: "CURRENCY",
align: "center",
sortable: false,
value: "lab",
width: "10%",
class: "pa-2 blue lighten-3 white--text",
},
{
text: "DEBIT",
align: "center",
sortable: false,
value: "lab",
width: "15%",
class: "pa-2 blue lighten-3 white--text",
},
{
text: "CREDIT",
align: "center",
sortable: false,
value: "lab",
width: "15%",
class: "pa-2 blue lighten-3 white--text",
}
],
}),
computed: {
isLoading() {
return this.$store.state.journal.search_status === 1;
},
periodeList() {
return this.$store.state.journal.periodeList
},
dialogperiode() {
return this.$store.state.journal.dialog_form_periode
},
dialogconfirm() {
return this.$store.state.journal.dialog_form_confirm
},
selectedPeriode: {
get() {
return this.$store.state.journal.selected_periode
},
set(val) {
this.$store.commit("journal/update_selected_periode", val)
},
},
dialogformdetail() {
return this.$store.state.journal.dialog_form_detail
},
xjournals() {
return this.$store.state.journal.journals
},
xsummary() {
return this.$store.state.journal.summary
},
ishide: {
get() {
return this.$store.state.journal.ishide
},
set(val) {
this.$store.commit("journal/update_ishide", val)
}
},
xdate: {
get() {
return this.$store.state.journal.xdate
},
set(val) {
this.$store.commit("journal/update_xdate", val)
}
},
xdateend: {
get() {
return this.$store.state.journal.end_date
},
set(val) {
this.$store.commit("journal/update_end_date", val)
}
},
filterComputedDateFormatted() {
return this.formatDate(this.xdate)
},
filterComputedDateFormattedEnd() {
return this.formatDate(this.xdateend)
},
curr_page: {
get() {
return this.$store.state.journal.current_page;
},
set(val) {
this.$store.commit("journal/update_current_page", val);
this.$store.dispatch("journal/search", {
current_page: this.$store.state.journal.current_page,
xdate: this.$store.state.journal.xdate,
periodeid: this.$store.state.journal.selected_periode.id,
branchid: this.$store.state.journal.user.M_BranchID,
regionalid: this.$store.state.journal.user.S_RegionalID,
});
},
},
xtotal_page: {
get() {
return this.$store.state.journal.total_journal;
},
set(val) {
this.$store.commit("journal/update_total_journal", val);
},
},
selected_journal: {
get() {
return this.$store.state.journal.selected_journal;
},
set(val) {
this.$store.commit("journal/update_selected_journal", val);
},
},
user() {
return this.$store.state.journal.user
},
xjurnaldetails() {
return this.$store.state.journal.jurnaldetails
},
openprint: {
get() {
return this.$store.state.journal.open_print;
},
set(val) {
this.$store.commit("journal/update_open_print", val);
},
},
dialogerror: {
get() {
return this.$store.state.journal.dialog_error_jurnal;
},
set(val) {
this.$store.commit("journal/update_dialog_error_jurnal", val);
},
},
msgerrjurnallist() {
return this.$store.state.journal.msgerrjurnallist;
},
snackbar: {
get() {
return this.$store.state.journal.alert_success;
},
set(val) {
this.$store.commit("journal/update_alert_success", val);
},
},
msgSnackbar() {
return this.$store.state.journal.msg_success;
},
dialog_error: {
get() {
return this.$store.state.journal.alert_error;
},
set(val) {
this.$store.commit("journal/update_alert_error", val);
},
},
msgError() {
return this.$store.state.journal.save_error_message;
},
},
methods: {
convertMoney(money){
return one_money(money)
},
doPrint(val) {
// console.log(val)
this.printwidth = 1028
this.printtitle = ""
let user = one_user()
tm = Date.now()
var rptname = 'rpt_jurnal_pendapatan_001'
var formatrpt = this.formatreport
this.urlprint = "/birt/run?__report=report/one/accounting/" + rptname + ".rptdesign&__format=" + formatrpt + "&PID=" + val.Fa_ItemID + "&username=" + user.M_StaffName + "&tm=" + tm
// console.log(this.urlprint)
this.$store.commit("journal/update_open_print", true)
},
isSelected(p) {
return p.Fa_ItemID == this.$store.state.journal.selected_journal.Fa_ItemID;
},
selectMe(sc) {
this.$store.commit("journal/update_selected_journal", sc);
console.log(sc)
this.$store.commit("journal/update_branchlists", sc.branchlists)
},
thr_search: _.debounce(function () {
this.$store.dispatch("journal/search", {
current_page: this.$store.state.journal.current_page,
xdate: this.xdate,
periodeid: this.selectedPeriode.id,
branchid: this.$store.state.journal.user.M_BranchID,
regionalid: this.$store.state.journal.user.S_RegionalID,
})
}, 1000),
closeDialogPeriode() {
this.$store.commit("journal/update_dialog_form_periode", false)
},
openDialogPeriode() {
this.$store.commit("journal/update_dialog_form_periode", true)
},
openDialogConfirm() {
this.$store.commit("journal/update_dialog_form_confirm", true)
},
closeDialogConfirm() {
this.$store.commit("journal/update_dialog_form_confirm", false)
},
addConfirm() {
this.xperiodeid = this.$store.state.journal.selected_periode.id
this.xyearandmonth = this.$store.state.journal.selected_periode.yearandmonth
this.xperiode = this.$store.state.journal.selected_periode.periode
this.$store.commit("journal/update_dialog_form_confirm", false)
this.$store.dispatch("journal/addConfirm", {
current_page: this.$store.state.journal.current_page,
xdate: this.xdate,
periodeid: this.selectedPeriode.id,
details : this.$store.state.journal.journals
})
},
choosePeriode() {
this.xperiodeid = this.$store.state.journal.selected_periode.id
this.xyearandmonth = this.$store.state.journal.selected_periode.yearandmonth
this.xperiode = this.$store.state.journal.selected_periode.periode
// console.log(this.xperiodeid)
this.$store.commit("journal/update_dialog_form_periode", false)
this.$store.dispatch("journal/search", {
current_page: this.$store.state.journal.current_page,
xdate: this.xdate,
periodeid: this.selectedPeriode.id,
branchid: this.$store.state.journal.user.M_BranchID,
regionalid: this.$store.state.journal.user.S_RegionalID,
})
},
closeDialogFormDetail() {
this.$store.commit("journal/update_dialog_form_detail", false)
},
vieDetail(val) {
this.$store.commit("journal/update_dialog_form_detail", true)
this.$store.commit("journal/update_jurnaldetails", val.detailtx)
let totalDebit = 0;
let totalKredit = 0;
for (let item = 0; item < val.detailtx.length; item++) {
const element = val.detailtx[item];
totalDebit += parseFloat(element.jurnalTxDebit || '0');
totalKredit += parseFloat(element.jurnalTxCredit || '0');
}
let totalBalance = totalDebit - totalKredit;
let summary = {
debit: totalDebit,
credit: totalKredit,
balance: totalBalance,
};
this.$store.commit("journal/update_summary", summary);
},
formatDate(date) {
if (!date) return null
const [year, month, day] = date.split('-')
return `${day}-${month}-${year}`
},
deFormatedDate(date) {
if (!date) return null
const [day, month, year] = date.split('-')
return `${year}-${month.padStart(2, '0')}-${day.padStart(2, '0')}`
},
isObjectEmpty(val) {
let obj = val;
return Object.keys(obj).length === 0 && obj.constructor === Object;
},
isPeriodeEmpty() {
return Object.keys(this.selectedPeriode).length === 0;
},
openDialogEdit(val) {
this.selectedData = val;
if (val.type == "DB") {
this.debit = val.value;
this.credit = 0;
}
if (val.type == "CR") {
this.credit = val.value;
this.debit = 0;
}
this.dialogEdit = true;
},
formatCurrency(val) {
// Format the price above to USD using the locale, style, and currency.
let price = parseFloat(val);
let USDollar = new Intl.NumberFormat("id-ID", {
style: "currency",
currency: "IDR",
});
// console.log(
// `The formated version of ${price} is ${USDollar.format(price)}`
// );
return `${USDollar.format(price)}`;
},
resetInputFile() {
document.getElementById("csv_file").value = null;
this.dialogImport = false;
},
viewError(val) {
this.$store.commit("journal/update_dialog_error_jurnal", true)
this.$store.commit("journal/update_msgerrjurnallist", val.ErrMsg)
},
closeDialogError() {
this.$store.commit("journal/update_dialog_error_jurnal", false)
},
openGenerate(val) {
// console.log(val)
this.xbranchCode = val.jurnalM_BranchCode
this.xsearchDate = this.deFormatedDate(val.jurnalDate)
this.xFa_ItemID = val.Fa_ItemID
this.xname = val.jurnalTitle
this.msgalertgenerate = val.jurnalTitle
this.dialogregenerate = true
},
doRegenerateJurnal() {
this.dialogregenerate = false
// console.log(prm)
let user = one_user();
console.log(user.M_BranchID)
if (user.M_BranchID === 0 || user.M_BranchID === '0') {
// generate regional
this.$store.dispatch("journal/insertSales", {branchCode: 'ZZ', date: this.xsearchDate, jurnalno: this.selected_journal.jurnalNo})
} else {
// generate cabang
this.$store.dispatch("journal/insertSales", {branchCode: this.xbranchCode, date: this.xsearchDate, jurnalno: this.selected_journal.jurnalNo})
}
},
updateAlertSuccess(val) {
this.$store.commit("journal/update_alert_success", val);
},
},
watch: {
xdate(val, old) {
this.xdate = val
this.thr_search()
},
xdateend(val, old) {
this.xdateend = val
this.thr_search()
},
// search_item_periode(val, old) {
// if (val == old) return
// if (!val) return
// if (val.length < 1) {
// this.$store.dispatch("journal/getPeriode", this.search_item_periode)
// return this.thr_search_periode()
// }
// if (val.length > 1) {
// this.$store.dispatch("journal/getPeriode", this.search_item_periode)
// return this.thr_search_periode()
// }
// }
},
};
</script>

View File

@@ -0,0 +1,76 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>One</title>
<link rel="stylesheet" href="../../../libs/vendor/css/google-fonts.css">
<link rel="stylesheet" href="../../../libs/vendor/css/vuetify.min.css">
</head>
<body>
<div v-cloak id="app">
<v-app id="smartApp">
<one-navbar></one-navbar>
<v-content style="background: #F5E8DF!important;">
<v-container fluid fill-height class="pl-1 pr-1 pt-2 pb-2">
<v-layout row wrap>
<v-flex xs8 class="left" fill-height pa-1>
<one-media-journal></one-media-journal>
</v-flex>
<v-flex xs4 class="right" fill-height pa-1>
<one-branch></one-branch>
</v-flex>
</v-layout>
</v-container>
</v-content>
<one-footer> </one-footer>
</v-app>
</div>
<!-- Vendor -->
<script src="../../../libs/vendor/moment.min.js"></script>
<script src="../../../libs/vendor/numeral.min.js"></script>
<script src="../../../libs/vendor/moment-locale-id.js"></script>
<script src="../../../libs/vendor/lodash.js"></script>
<script src="../../../libs/vendor/axios.min.js"></script>
<script src="../../../libs/vendor/vue.js"></script>
<script src="../../../libs/vendor/vuex.js"></script>
<script src="../../../libs/vendor/vuetify.js"></script>
<script src="../../../libs/vendor/httpVueLoader.js"></script>
<script src="../../../libs/one_global.js"></script>
<!-- App Script -->
<?php
$ts = "?ts=" . Date("ymdhis");
?>
<script type="module">
import {
store
} from './store.js<?php echo $ts ?>';
//for testing
// window.store = store;
new Vue({
store,
el: '#app',
components: {
'one-navbar': httpVueLoader('../../../apps/components/oneNavbarComponent.vue'),
'one-footer': httpVueLoader('../../../apps/components/oneFooter.vue'),
'one-media-journal': httpVueLoader('./components/oneMediaJournalList.vue'),
'one-branch': httpVueLoader('./components/oneBranchList.vue')
}
})
</script>
<style>
[v-cloak] {
display: none
}
.left {}
.right {}
</style>
</body>
</html>

View File

@@ -0,0 +1,361 @@
// 1 => LOADING
// 2 => DONE
// 3 => ERROR
import * as api from "../api/journal.js"
export default {
namespaced: true,
state: {
search_status: 0,
current_page: 1,
x_search: "",
search_error_message: "",
last_id: -1,
coas: [],
total_coas: 0,
selected_coa: {},
dialog_form_coa: false,
act: 'new',
save_status: 0,
save_error_message: '',
errors: [],
alert_success: false,
msg_success: "",
alert_error: false,
dialog_error: false,
open_print: false,
// ----
xdate: moment(new Date()).format('YYYY-MM-DD'),
end_date: moment(new Date()).format('YYYY-MM-DD'),
journals: [
// {
// "journalID": "1",
// "journalNo": "JM002/08",
// "date": "31-08-2024",
// "name": "budhi/budhi",
// "account": "508501001",
// "title": "MS BESIN, SOLAR, PARKIR, TOL, TRANSPORT",
// "description": "ACCRUED PARKIR AGST 24",
// "debit": "275000",
// "credit": "0",
// "posted": "Y"
// },
// {
// "journalID": "2",
// "journalNo": "JM002/08",
// "date": "31-08-2024",
// "name": "budhi/budhi",
// "account": "2004009",
// "title": "ACCRUED EXP OTHERS",
// "description": "ACCRUED PARKIR AGST 24",
// "debit": "0",
// "credit": "275000",
// "posted": "Y"
// }
],
selected_journal: {},
summary: {"debit": 0, "credit": 0, "balance": 0},
dialog_form_detail: false,
periodeList: [],
selected_periode: {},
loading: false,
dialog_form_periode: false,
dialog_form_confirm: false,
autocomplete_status: 0,
search_status: 0,
search_error_message: "",
total_journal: 0,
user: one_user(),
jurnaldetails: [],
dialog_error_jurnal: false,
msgerrjurnallist: [],
user: one_user(),
ishide: 'Y',
branchlists: []
},
mutations: {
update_ishide(state, val) {
state.ishide = val
},
update_search_status(state, val) {
state.search_status = val
},
update_current_page(state, val) {
state.current_page = val
},
update_x_search(state, val) {
state.x_search = val
state.current_page = 1
},
update_search_error_message(state, val) {
state.search_error_message = val
},
update_last_id(state, val) {
state.last_id = val
},
update_coas(state, val) {
state.coas = val
},
update_total_coas(state, val) {
state.total_coas = val
},
update_selected_coa(state, val) {
state.selected_coa = val
},
update_dialog_form_coa(state, val) {
state.dialog_form_coa = val
},
update_act(state, val) {
state.act = val
},
update_save_status(state, val) {
state.save_status = val
},
update_save_error_message(state, val) {
state.save_error_message = val
},
update_errors(state, val) {
state.errors = val
},
update_alert_success(state, val) {
state.alert_success = val
},
update_msg_success(state, val) {
state.msg_success = val
},
update_alert_error(state, val) {
state.alert_error = val
},
update_dialog_error(state, val) {
state.dialog_error = val
},
update_open_print(state, value) {
state.open_print = value
},
// ---
update_xdate(state, val) {
state.xdate = val
},
update_end_date(state, val) {
state.end_date = val
},
update_journals(state, val) {
state.journals = val
},
update_branchlists(state, val) {
state.branchlists = val
},
update_selected_journal(state, val) {
state.selected_journal = val
},
update_summary(state, val) {
state.summary = val
},
update_dialog_form_detail(state, val) {
state.dialog_form_detail = val
},
update_periodeList(state, val) {
state.periodeList = val
},
update_selected_periode(state, val) {
state.selected_periode = val
},
update_loading(state, val) {
state.loading = val
},
update_dialog_form_periode(state, val) {
state.dialog_form_periode = val
},
update_dialog_form_confirm(state, val) {
state.dialog_form_confirm = val
},
update_autocomplete_status(state, val) {
state.autocomplete_status = val
},
update_search_status(state, val) {
state.search_status = val
},
update_search_error_message(state, val) {
state.search_error_message = val
},
update_total_journal(state, val) {
state.total_journal = val
},
update_user(state, val) {
state.user = val
},
update_jurnaldetails(state, val) {
state.jurnaldetails = val
},
update_dialog_error_jurnal(state, val) {
state.dialog_error_jurnal = val
},
update_msgerrjurnallist(state, val) {
state.msgerrjurnallist = val
},
update_user(state, val) {
state.user = val
}
},
actions: {
async getPeriode(context) {
context.commit("update_autocomplete_status", 1)
try {
let prm = {}
prm.token = one_token()
let resp = await api.getPeriode(prm)
if (resp.status != "OK") {
context.commit("update_autocomplete_status", 3)
} else {
context.commit("update_autocomplete_status", 2)
let data = resp.data
context.commit("update_periodeList", data)
// Ambil bulan dan tahun sekarang
let now = new Date();
let currentMonth = now.getMonth() + 1; // getMonth() dimulai dari 0 (Jan = 0)
let currentYear = now.getFullYear().toString(); // Ambil tahun dalam bentuk string
// Cari data dengan periodeMonth dan periodeYear yang cocok
let selectedPeriode = data.find(p => p.periodeMonth == currentMonth.toString() && p.periodeYear == currentYear);
// Jika tidak ditemukan, gunakan data pertama sebagai default
if (!selectedPeriode) {
selectedPeriode = data[0];
}
context.commit("update_selected_periode", selectedPeriode)
}
} catch (e) {
context.commit("update_autocomplete_status", 3)
}
},
async search(context, prm) {
context.commit("update_search_status", 1)
try {
// var prm = {
// token: one_token(),
// periodeid: context.state.selected_periode.id
// }
// var prm = {}
// prm.one_token()
let resp = await api.search(one_token(), prm.xdate, prm.periodeid, prm.branchid, prm.regionalid)
if (resp.status != "OK") {
context.commit("update_search_status", 3)
context.commit("update_search_error_message", resp.message)
} else {
context.commit("update_search_status", 2)
context.commit("update_search_error_message", "")
let data = {
records: resp.data.records,
total: resp.data.total
}
context.commit("update_journals", data.records)
context.commit("update_ishide", data.records[0].ishide)
context.commit("update_total_journal", data.total)
}
} catch (e) {
context.commit("update_search_status", 3)
context.commit("update_search_error_message", e.message)
}
},
async getdetail(context, prm) {
context.commit("update_search_status", 1)
try {
// var prm = {
// token: one_token(),
// periodeid: context.state.selected_periode.id
// }
// var prm = {}
prm.token = one_token()
let resp = await api.getdetail(prm)
if (resp.status != "OK") {
context.commit("update_search_status", 3)
context.commit("update_search_error_message", resp.message)
} else {
context.commit("update_search_status", 2)
context.commit("update_search_error_message", "")
let data = {
records: resp.data.records,
total: resp.data.total
}
context.commit("update_branchlists", data.records)
}
} catch (e) {
context.commit("update_search_status", 3)
context.commit("update_search_error_message", e.message)
}
},
async insertSales(context, prm) {
context.commit("update_save_status", 1)
try {
let branchCode = prm.branchCode;
let date = prm.date;
let jurnalno = prm.jurnalno
let resp = await api.insertSales(branchCode, date, jurnalno)
if (resp.status != "OK") {
context.commit("update_save_status", 3)
context.commit("update_save_error_message", resp.message)
context.commit("update_alert_error", true)
} else {
context.commit("update_save_status", 2)
context.commit("update_save_error_message", resp.message)
let data = {
total: resp.data.total
}
context.commit("update_alert_success", true)
var msg = resp.data.msg
context.commit("update_msg_success", msg)
context.dispatch("search", {
current_page: context.state.current_page,
xdate: context.state.xdate,
periodeid: context.state.selected_periode.id
})
}
} catch (e) {
context.commit("update_save_status", 3)
context.commit("update_save_error_message", e.message)
context.commit("update_alert_error", true)
}
},
async addConfirm(context, prm) {
context.commit("update_save_status", 1)
try {
prm.token = one_token()
let resp = await api.addConfirm(prm)
if (resp.status != "OK") {
context.commit("update_save_status", 3)
context.commit("update_save_error_message", resp.message)
context.commit("update_alert_error", true)
} else {
context.commit("update_save_status", 2)
context.commit("update_save_error_message", resp.message)
let data = {
total: resp.data.total
}
context.commit("update_alert_success", true)
var msg = " Fixed aset periode " + context.state.selected_periode.periode + " berhasil dikonfirmasi"
context.commit("update_msg_success", msg)
context.dispatch("search", {
current_page: context.state.current_page,
xdate: context.state.xdate,
periodeid: context.state.selected_periode.id
})
}
} catch (e) {
context.commit("update_save_status", 3)
context.commit("update_save_error_message", e.message)
context.commit("update_alert_error", true)
}
},
}
}

View File

@@ -0,0 +1,23 @@
// State
// data ...
// Mutations
//
//
// Actions
import journal from "./modules/journal.js";
import system from "../../../apps/modules/system/system.js";
export const store = new Vuex.Store({
modules: {
journal: journal,
system:system
},
state: {
},
mutations: {
},
actions: {
}
});

View File

@@ -0,0 +1,282 @@
const URL = "/one-api/mockup/masterdata/accounting/";
export async function getPeriode(prm) {
try {
var resp = await axios.post(URL + "JournalItemUsage/getPeriode", prm);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function search(
token,
xdate,
periodeid,
current_page,
search,
branchCode,
regionalId
) {
try {
var resp = await axios.post(URL + "JournalItemUsage/search", {
token: token,
xdate: xdate,
periodeid: periodeid,
current_page: current_page,
search: search,
branchCode: branchCode,
regionalId: regionalId
});
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function insertSales(branchCode, date, jurnalno) {
try {
var resp = await axios.get(
URL + `mediajurnalauto/insertSales/${branchCode}/${date}?isregen=1&jurnalno=${jurnalno}`
);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function getRegional(prm) {
try {
var resp = await axios.post(URL + "JournalItemUsage/getRegional", prm);
if (resp.status !== 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function getBranch(prm) {
try {
var resp = await axios.post(URL + "JournalItemUsage/getBranch", prm);
if (resp.status !== 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (e) {
return {
status: "ERR",
message: e.message
};
}
}
export async function getUserApproveLevel(params) {
try {
var resp = await axios.post(URL + "JournalItemUsage/getUserApproveLevel", params);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (error) {
return {
status: "ERR",
message: error.message
};
}
}
export async function getListingCOA(params) {
try {
var resp = await axios.post(URL + "JournalItemUsage/getListingCOA", params);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (error) {
return {
status: "ERR",
message: error.message
};
}
}
export async function requestEditJurnal(params) {
try {
const resp = await axios.post(URL + "JournalVerifEdit/requestEditJurnal", params);
if (resp.status !== 200) {
return {
status: "ERR",
message: resp.statusText
};
}
const data = resp.data;
return data;
} catch (error) {
return {
status: "ERR",
message: error.message
};
}
}
export async function saveEditJurnal(params) {
try {
var resp = await axios.post(URL + "JournalVerifEdit/saveEditJurnal", params);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (error) {
return {
status: "ERR",
message: error.message
};
}
}
export async function changeJurnalToPosted(params) {
try {
var resp = await axios.post(URL + "JournalItemUsage/changeJurnalToPosted", params);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (error) {
return {
status: "ERR",
message: error.message
};
}
}
export async function getTotalJurnalNotPostedPerPeriod(params) {
try {
var resp = await axios.post(
URL + "JournalItemUsage/getTotalJurnalNotPostedPerPeriod",
params
);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (error) {
return {
status: "ERR",
message: error.message
};
}
}
export async function closeJurnalPerPeriode(params) {
try {
var resp = await axios.post(URL + "JournalItemUsage/closeJurnalPerPeriode", params);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (error) {
return {
status: "ERR",
message: error.message
};
}
}
export async function getDataJurnalNotClosedPerPeriod(params) {
try {
var resp = await axios.post(
URL + "JournalItemUsage/getDataJurnalNotClosedPerPeriod",
params
);
if (resp.status != 200) {
return {
status: "ERR",
message: resp.statusText
};
}
let data = resp.data;
return data;
} catch (error) {
return {
status: "ERR",
message: error.message
};
}
}

View File

@@ -0,0 +1,76 @@
<template>
<v-dialog v-model="dialog_close_jurnal" persistent width="40vw">
<v-card>
<v-card-title class="headline grey lighten-2" primary-title>
TUTUP SEMUA JURNAL PADA PERIODE {{ selected_periode.periodeName }}
</v-card-title>
<v-card-text>
<div v-for="item in jurnal_to_close" :key="item.jurnalIsPosted">
<p v-if="item.jurnalIsPosted == 'N'">
Jumlah jurnal yang tidak dapat ditutup: <strong>{{ item.total_jurnal }}</strong>
</p>
<p v-else>
Jumlah jurnal yang dapat ditutup: <strong>{{ item.total_jurnal }}</strong>
</p>
</div>
<p>
Apakah anda yakin akan menutup semua jurnal yang dibuat di
<strong> {{ area_jurnal }} </strong> dalam rentang waktu <br>
<strong>{{ selected_periode.periode }}</strong> <br>
</p>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="error" outline flat @click="dialog_close_jurnal = false">Batal</v-btn>
<v-btn color="primary" dark @click="closeJurnal()">Ya</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script>
module.exports = {
data() {
return {
}
},
computed: {
selected_periode() {
return this.$store.state.journal.selected_periode
},
area_jurnal() {
const user = this.$store.state.journal.user
if (user.M_BranchID == '0') {
return `Regional ${user.S_RegionalName}`
} else {
return `Cabang ${user.M_BranchName}, Regional ${user.S_RegionalName}`
}
},
jurnal_to_close() {
return this.$store.state.journal.jurnal_to_close
},
dialog_close_jurnal: {
get() {
return this.$store.state.journal.dialog_close_jurnal
},
set(val) {
this.$store.commit("journal/update_dialog_close_jurnal", val)
}
}
},
methods: {
closeJurnal() {
var jurnal = this.jurnal_to_close.find(item => item.jurnalIsPosted === 'Y')
if (jurnal && Number(jurnal.total_jurnal) > 0) {
this.$store.dispatch("journal/closeJurnalPerPeriode", { typeid: jurnal.JurnalTypeID })
return;
}
this.$store.commit("journal/update_open_dialog_info", true);
this.$store.commit("journal/update_msg_info",
"Tidak ada jurnal yang dapat ditutup"
);
}
},
}
</script>

View File

@@ -0,0 +1,223 @@
<template>
<v-dialog v-model="dialog_edit_jurnal" persistetnt width="70vw">
<v-card>
<v-card-title class="headline grey lighten-2" primary-title>
EDIT JOURNAL ITEM USAGE
</v-card-title>
<v-card-text>
<v-layout row wrap>
<v-flex xs6 pa-1 pr-3>
<div class="font-weight-bold">Company Name</div>
<div class="pa-2 grey lighten-2">
{{ selected_journal.M_BranchCompanyName }}
</div>
</v-flex>
<v-flex xs6 pa-1 pl-3>
<div class="font-weight-bold">Journal</div>
<div class="pa-2 grey lighten-2">
{{ selected_journal.jurnalTitle }}
</div>
</v-flex>
<v-flex xs6 pa-1 pr-3>
<div class="font-weight-bold">Regional</div>
<div class="pa-2 grey lighten-2">
{{ selected_journal.S_RegionalName }}
</div>
</v-flex>
<v-flex xs6 pa-1 pl-3>
<div class="font-weight-bold">Journal Date</div>
<div class="pa-2 grey lighten-2">
{{ selected_journal.jurnalDate }}
</div>
</v-flex>
<v-flex xs6 pa-1 pr-3>
<div class="font-weight-bold">Branch</div>
<div class="pa-2 grey lighten-2">
{{ selected_journal.M_BranchName }}
</div>
</v-flex>
<v-flex xs6 pa-1 pl-3>
<div class="font-weight-bold">Journal Type</div>
<div class="pa-2 grey lighten-2">
{{ selected_journal.JurnalTypeName }}
</div>
</v-flex>
</v-layout>
<v-layout row wrap mt-3>
<v-flex xs12>
<v-data-table
:headers="headerdetails" :items="journal_edit"
hide-actions class="elevation-1"
>
<template slot="items" slot-scope="props">
<tr>
<td class="text-xs-center pa-2">{{ props.item.coaAccountNo }}</td>
<td class="text-xs-left pa-2">
<v-autocomplete
label="Account" hide-details outline
v-model="props.item.coaAccountNo"
:items="list_coa" item-text="coaDescription"
item-value="coaAccountNo"
></v-autocomplete>
</td>
<td class="text-xs-left pa-2">{{ props.item.jurnalAddOnValue }}</td>
<td class="text-xs-center pa-2">{{ props.item.coaCurrencyCode }}</td>
<td class="text-xs-right pa-2">{{ formatCurrency(props.item.jurnalTxDebit) }}</td>
<td class="text-xs-right pa-2">{{ formatCurrency(props.item.jurnalTxCredit) }}</td>
</tr>
</template>
<template v-slot:footer>
<tr>
<td colspan="4" class="font-weight-bold pa-2">TOTAL</td>
<td class="text-xs-right pa-2 font-weight-bold">
{{ formatCurrency(xsummary.debit) }}
</td>
<td class="text-xs-right pa-2 font-weight-bold">
{{ formatCurrency(xsummary.credit) }}
</td>
</tr>
<tr>
<td colspan="5" class="font-weight-bold pa-2">BALANCE</td>
<td width="10%" class="text-xs-right pa-2 font-weight-bold">
{{ formatCurrency(xsummary.balance) }}
</td>
</tr>
</template>
</v-data-table>
</v-flex>
</v-layout>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="error" outline flat @click="closeEditDialog()">Batal</v-btn>
<v-btn color="primary" dark @click="simpanEditDialog()">Simpan</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script>
module.exports = {
data() {
return {
headerdetails: [
{
text: "AKUN", align: "center", sortable: false,
value: "action", width: "20%", class: "pa-2 pl-2 blue lighten-3 white--text",
},
{
text: "DESKRIPSI", align: "center", sortable: false,
value: "mr", width: "25%", class: "pa-2 blue lighten-3 white--text",
},
{
text: "INFO", align: "center", sortable: false,
value: "lab", width: "15%", class: "pa-2 blue lighten-3 white--text",
},
{
text: "CURRENCY", align: "center", sortable: false,
value: "lab", width: "10%", class: "pa-2 blue lighten-3 white--text",
},
{
text: "DEBIT", align: "center", sortable: false,
value: "lab", width: "15%", class: "pa-2 blue lighten-3 white--text",
},
{
text: "CREDIT", align: "center", sortable: false,
value: "lab", width: "15%", class: "pa-2 blue lighten-3 white--text",
}
]
}
},
computed: {
dialog_edit_jurnal: {
get() {
return this.$store.state.journal.dialog_edit_journal;
},
set(val) {1
this.$store.commit("journal/update_dialog_edit_journal", val);
}
},
selected_journal: {
get() {
return this.$store.state.journal.selected_journal;
},
set(val) {
this.$store.commit("journal/update_selected_journal", val);
},
},
journal_edit: {
get() {
return this.$store.state.journal.journal_edit
},
set(val) {
this.$store.commit("journal/update_journal_edit", val);
}
},
selected_periode() {
return this.$store.state.journal.selected_periode
},
xsummary() {
return this.$store.state.journal.summary
},
list_coa() {
return this.$store.state.journal.list_coa
}
},
methods: {
formatCurrency(val) {
const price = parseFloat(val);
const IDR = new Intl.NumberFormat("id-ID", {
style: "currency",
currency: "IDR"
});
return `${IDR.format(price)}`;
},
simpanEditDialog() {
const originaldetail = this.selected_journal.detailtx;
const editnewdetails = this.journal_edit;
const listcoa = this.list_coa;
const originalMap = new Map();
for (const item of originaldetail) {
originalMap.set(item.jurnalTxID, item.coaAccountNo);
}
const coaMap = new Map();
for (const coaItem of listcoa) {
coaMap.set(coaItem.coaAccountNo, coaItem);
}
const editeddetail = editnewdetails.flatMap(detail => {
const originalAcc = originalMap.get(detail.jurnalTxID);
if (originalAcc !== detail.coaAccountNo) {
const accMatch = coaMap.get(detail.coaAccountNo);
if (accMatch) {
return [{
jurnalID: detail.jurnalTxJurnalID,
jurnalTxID: detail.jurnalTxID,
coaID: accMatch.coaID,
coaDescription: accMatch.coaDescription,
coaAccountNo: accMatch.coaAccountNo
}]
} else {
return [];
}
} else {
return [];
}
})
this.$store.dispatch("journal/saveEditJurnal", editeddetail);
},
closeEditDialog() {
this.selected_journal = {};
this.journal_edit = [];
this.dialog_edit_jurnal = false;
}
},
watch: {
},
}
</script>

View File

@@ -0,0 +1,68 @@
<template>
<v-dialog v-model="dialog_confirm_posting" persistetnt width="40vw">
<v-card>
<v-card-title class="headline grey lighten-2" primary-title>
POSTING SEMUA JURNAL PADA PERIODE {{ selected_periode.periodeName }}
</v-card-title>
<v-card-text>
<div v-for="item in total_jurnal_not_posted" :key="item.jurnalEditStatus">
<p v-if="item.jurnalEditStatus == 'N'">
Jumlah jurnal yang dapat diposting: <strong>{{ item.total_jurnal }}</strong>
</p>
<p v-if="item.jurnalEditStatus == 'Y'">
Jumlah jurnal yang tidak dapat diposting: <strong>{{ item.total_jurnal }}</strong>
(belum diverifikasi setelah edit)
</p>
</div>
<p>
Apakah anda yakin akan melakukan posting semua jurnal yang dibuat dalam rentang waktu
<strong>{{ selected_periode.periode }}</strong> ?
</p>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="error" outline flat @click="dialog_confirm_posting = false">Batal</v-btn>
<v-btn color="primary" dark @click="postingJurnal()">Ya</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script>
module.exports = {
data() {
return {
}
},
computed: {
selected_periode() {
return this.$store.state.journal.selected_periode
},
total_jurnal_not_posted() {
return this.$store.state.journal.total_jurnal_not_posted
},
dialog_confirm_posting: {
get() {
return this.$store.state.journal.dialog_confirm_posting;
},
set(val) {1
this.$store.commit("journal/update_dialog_confirm_posting", val);
}
},
},
methods: {
postingJurnal() {
var jurnal = this.total_jurnal_not_posted.find(jrnl => jrnl.jurnalEditStatus === 'N')
if (jurnal && Number(jurnal.total_jurnal) > 0) {
this.$store.dispatch("journal/postingJurnal", { typeid: jurnal.JurnalTypeID });
return;
}
this.$store.commit("journal/update_open_dialog_info", true);
this.$store.commit("journal/update_msg_info",
"semua jurnal para periode ini sudah terposting"
);
}
},
}
</script>

View File

@@ -0,0 +1,58 @@
<template>
<v-dialog v-model="dialog_request_edit" persistent width="40vw">
<v-card>
<v-card-title class="headline grey lighten-2" primary-title>
REQUEST EDIT JURNAL {{ selected_journal.jurnalNo }}
</v-card-title>
<v-card-text>
<p v-if="selected_journal.JurnalRequestEditStatusEdit == 'approved'">
Jurnal ini sudah pernah diedit sebelumnya oleh:
{{ selected_journal.JurnalRequestEditStaffName }} <br>
Apakah anda yakin akan mengajukan permintaan untuk melakukan perubahan lagi? <br>
Nomor: <strong>{{ selected_journal.jurnalNo }}</strong> <br>
Judul: <strong>{{ selected_journal.jurnalTitle }}</strong> <br>
Deskripsi: {{ selected_journal.jurnalDescription }} <br>
</p>
<p v-else>
Apakah anda yakin akan mengajukan permintaan untuk melakukan perubahan jurnal: <br>
Nomor: <strong>{{ selected_journal.jurnalNo }}</strong> <br>
Judul: <strong>{{ selected_journal.jurnalTitle }}</strong> <br>
Deskripsi: {{ selected_journal.jurnalDescription }} <br>
</p>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="error" outline @click="dialog_request_edit = false">Batal</v-btn>
<v-btn color="primary" dark @click="requestEdit()">Ya</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script>
module.exports = {
data() {
return {
}
},
computed: {
dialog_request_edit: {
get() {
return this.$store.state.journal.dialog_request_edit
},
set(val) {
this.$store.commit("journal/update_dialog_request_edit", val)
}
},
selected_journal() {
return this.$store.state.journal.selected_journal
}
},
methods: {
requestEdit() {
this.$store.dispatch("journal/requestEditJurnal");
}
},
}
</script>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,73 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>One</title>
<link rel="stylesheet" href="../../../libs/vendor/css/google-fonts.css">
<link rel="stylesheet" href="../../../libs/vendor/css/vuetify.min.css">
</head>
<body>
<div v-cloak id="app">
<v-app id="smartApp">
<one-navbar></one-navbar>
<v-content class="blue lighten-5">
<v-container fluid fill-height class="pl-1 pr-1 pt-2 pb-2">
<v-layout row wrap>
<v-flex xs12 class="center" fill-height pa-1>
<!-- komponen -->
<one-media-journal></one-media-journal>
</v-flex>
</v-layout>
</v-container>
</v-content>
<one-footer> </one-footer>
</v-app>
</div>
<!-- Vendor -->
<script src="../../../libs/vendor/moment.min.js"></script>
<script src="../../../libs/vendor/numeral.min.js"></script>
<script src="../../../libs/vendor/moment-locale-id.js"></script>
<script src="../../../libs/vendor/lodash.js"></script>
<script src="../../../libs/vendor/axios.min.js"></script>
<script src="../../../libs/vendor/vue.js"></script>
<script src="../../../libs/vendor/vuex.js"></script>
<script src="../../../libs/vendor/vuetify.js"></script>
<script src="../../../libs/vendor/httpVueLoader.js"></script>
<script src="../../../libs/one_global.js"></script>
<!-- App Script -->
<?php
$ts = "?ts=" . Date("ymdhis");
?>
<script type="module">
import {
store
} from './store.js<?php echo $ts ?>';
//for testing
// window.store = store;
new Vue({
store,
el: '#app',
components: {
'one-navbar': httpVueLoader('../../../apps/components/oneNavbarComponent.vue'),
'one-footer': httpVueLoader('../../../apps/components/oneFooter.vue'),
'one-media-journal': httpVueLoader('./components/oneMediaJournalList.vue')
}
})
</script>
<style>
[v-cloak] {
display: none
}
.left {}
.right {}
</style>
</body>
</html>

View File

@@ -0,0 +1,582 @@
// 1 => LOADING
// 2 => DONE
// 3 => ERROR
import * as api from "../api/journal.js";
export default {
namespaced: true,
state: {
search_status: 0,
current_page: 1,
x_search: "",
search_error_message: "",
last_id: -1,
coas: [],
total_coas: 0,
selected_coa: {},
dialog_form_coa: false,
act: "new",
save_status: 0,
save_error_message: "",
errors: [],
alert_success: false,
msg_success: "",
alert_error: false,
dialog_error: false,
open_print: false,
// ----
xdate: moment(new Date()).format("YYYY-MM-DD"),
end_date: moment(new Date()).format("YYYY-MM-DD"),
journals: [],
selected_journal: {},
summary: { debit: 0, credit: 0, balance: 0 },
dialog_form_detail: false,
periodeList: [],
selected_periode: {},
loading: false,
dialog_form_periode: false,
autocomplete_status: 0,
search_status: 0,
total_journal: 0,
user: one_user(),
jurnaldetails: [],
dialog_error_jurnal: false,
msgerrjurnallist: [],
regionals: [],
selected_regional: {},
branchs: [],
selected_branch: {},
xsearch: "",
open_dialog_info: false,
msg_info: "",
// --
dialog_edit_journal: false,
user_level: {},
list_coa: [],
journal_edit: [],
dialog_confirm_posting: false,
total_jurnal_not_posted: [],
dialog_request_edit: false,
// ---
dialog_close_jurnal: false,
jurnal_to_close: []
},
mutations: {
update_search_status(state, val) {
state.search_status = val;
},
update_current_page(state, val) {
state.current_page = val;
},
update_x_search(state, val) {
state.x_search = val;
state.current_page = 1;
},
update_search_error_message(state, val) {
state.search_error_message = val;
},
update_last_id(state, val) {
state.last_id = val;
},
update_coas(state, val) {
state.coas = val;
},
update_total_coas(state, val) {
state.total_coas = val;
},
update_selected_coa(state, val) {
state.selected_coa = val;
},
update_dialog_form_coa(state, val) {
state.dialog_form_coa = val;
},
update_act(state, val) {
state.act = val;
},
update_save_status(state, val) {
state.save_status = val;
},
update_save_error_message(state, val) {
state.save_error_message = val;
},
update_errors(state, val) {
state.errors = val;
},
update_alert_success(state, val) {
state.alert_success = val;
},
update_msg_success(state, val) {
state.msg_success = val;
},
update_alert_error(state, val) {
state.alert_error = val;
},
update_dialog_error(state, val) {
state.dialog_error = val;
},
update_open_print(state, value) {
state.open_print = value;
},
// ---
update_xdate(state, val) {
state.xdate = val;
},
update_end_date(state, val) {
state.end_date = val;
},
update_journals(state, val) {
state.journals = val;
},
update_selected_journal(state, val) {
state.selected_journal = val;
},
update_summary(state, val) {
state.summary = val;
},
update_dialog_form_detail(state, val) {
state.dialog_form_detail = val;
},
update_periodeList(state, val) {
state.periodeList = val;
},
update_selected_periode(state, val) {
state.selected_periode = val;
},
update_loading(state, val) {
state.loading = val;
},
update_dialog_form_periode(state, val) {
state.dialog_form_periode = val;
},
update_autocomplete_status(state, val) {
state.autocomplete_status = val;
},
update_search_status(state, val) {
state.search_status = val;
},
update_total_journal(state, val) {
state.total_journal = val;
},
update_user(state, val) {
state.user = val;
},
update_jurnaldetails(state, val) {
state.jurnaldetails = val;
},
update_dialog_error_jurnal(state, val) {
state.dialog_error_jurnal = val;
},
update_msgerrjurnallist(state, val) {
state.msgerrjurnallist = val;
},
update_regionals(state, val) {
state.regionals = val;
},
update_selected_regional(state, val) {
state.selected_regional = val;
},
update_branchs(state, val) {
state.branchs = val;
},
update_selected_branch(state, val) {
state.selected_branch = val;
},
update_xsearch(state, val) {
state.xsearch = val;
state.current_page = 1;
},
update_open_dialog_info(state, val) {
state.open_dialog_info = val;
},
update_msg_info(state, val) {
state.msg_info = val;
},
// --
update_dialog_edit_journal(state, val) {
state.dialog_edit_journal = val;
},
update_user_level(state, val) {
state.user_level = val;
},
update_list_coa(state, val) {
state.list_coa = val;
},
update_journal_edit(state, val) {
state.journal_edit = val;
},
update_dialog_confirm_posting(state, val) {
state.dialog_confirm_posting = val;
},
update_total_jurnal_not_posted(state, val) {
state.total_jurnal_not_posted = val;
},
update_dialog_request_edit(state, val) {
state.dialog_request_edit = val;
},
update_dialog_close_jurnal(state, val) {
state.dialog_close_jurnal = val;
},
update_jurnal_to_close(state, val) {
state.jurnal_to_close = val;
}
},
actions: {
async getPeriode(context) {
context.commit("update_autocomplete_status", 1);
try {
let prm = {};
prm.token = one_token();
let resp = await api.getPeriode(prm);
if (resp.status != "OK") {
context.commit("update_autocomplete_status", 3);
} else {
context.commit("update_autocomplete_status", 2);
let data = resp.data;
context.commit("update_periodeList", resp.data);
// Ambil bulan dan tahun sekarang
let now = new Date();
let currentMonth = now.getMonth() + 1; // getMonth() dimulai dari 0 (Jan = 0)
let currentYear = now.getFullYear().toString(); // Ambil tahun dalam bentuk string
// Cari data dengan periodeMonth dan periodeYear yang cocok
let selectedPeriode = data.find(
(p) =>
p.periodeMonth == currentMonth.toString() &&
p.periodeYear == currentYear
);
// Jika tidak ditemukan, gunakan data pertama sebagai default
if (!selectedPeriode) {
selectedPeriode = data[0];
}
context.commit("update_selected_periode", selectedPeriode);
}
} catch (e) {
context.commit("update_autocomplete_status", 3);
}
},
async search(context, prm) {
context.commit("update_search_status", 1);
try {
let resp = await api.search(
one_token(),
prm.xdate,
prm.periodeid,
prm.current_page,
prm.search,
prm.branchCode,
prm.regionalId
);
if (resp.status != "OK") {
context.commit("update_search_status", 3);
context.commit("update_search_error_message", resp.message);
} else {
context.commit("update_search_status", 2);
context.commit("update_search_error_message", "");
let data = {
records: resp.data.records,
total: resp.data.total
};
context.commit("update_journals", data.records);
context.commit("update_total_journal", data.total);
}
} catch (e) {
context.commit("update_search_status", 3);
context.commit("update_search_error_message", e.message);
}
},
async insertSales(context, prm) {
context.commit("update_save_status", 1);
try {
let branchCode = prm.branchCode;
let date = prm.date;
let jurnalno = prm.jurnalno;
let resp = await api.insertSales(branchCode, date, jurnalno);
if (resp.status != "OK") {
context.commit("update_save_status", 3);
context.commit("update_save_error_message", resp.message);
context.commit("update_alert_error", true);
} else {
context.commit("update_save_status", 2);
context.commit("update_save_error_message", resp.message);
let data = {
total: resp.data.total
};
context.commit("update_alert_success", true);
var msg = resp.data.msg;
context.commit("update_msg_success", msg);
context.dispatch("search", {
current_page: context.state.current_page,
xdate: context.state.xdate,
periodeid: context.state.selected_periode.id
});
}
} catch (e) {
context.commit("update_save_status", 3);
context.commit("update_save_error_message", e.message);
context.commit("update_alert_error", true);
}
},
async getRegional(context) {
context.commit("update_autocomplete_status", 1);
try {
let resp = await api.getRegional({
token: one_token(),
regionalId: context.state.user.S_RegionalID
});
if (resp.status != "OK") {
context.commit("update_search_error_message", resp.message);
context.commit("update_autocomplete_status", 3);
} else {
context.commit("update_search_error_message", "");
context.commit("update_autocomplete_status", 2);
let data = {
records: resp.data.records,
selected: resp.data.selected
};
context.commit("update_regionals", data.records);
context.commit("update_selected_regional", data.selected);
}
} catch (e) {
context.commit("update_search_error_message", e.message);
context.commit("update_autocomplete_status", 3);
}
},
async getBranch(context) {
context.commit("update_autocomplete_status", 1);
try {
let resp = await api.getBranch({
token: one_token(),
regionalId: context.state.selected_regional.S_RegionalID,
branchCode: context.state.user.M_BranchCode
});
if (resp.status != "OK") {
context.commit("update_search_error_message", resp.message);
context.commit("update_autocomplete_status", 3);
} else {
context.commit("update_search_error_message", "");
context.commit("update_autocomplete_status", 2);
let data = {
records: resp.data.records,
selected: resp.data.selected
};
context.commit("update_branchs", data.records);
context.commit("update_selected_branch", data.selected);
}
} catch (e) {
context.commit("update_search_error_message", e.message);
context.commit("update_autocomplete_status", 3);
}
},
async postingJurnal(context, typeid) {
try {
let param = {
token: one_token(),
jurnalTypeID: typeid,
periodeID: context.state.selected_periode.id
};
const resp = await api.changeJurnalToPosted(param);
if (resp.status != "OK") {
context.commit("update_alert_error", true);
context.commit("update_save_error_message", resp.message);
} else {
context.commit("update_msg_success", resp.data);
context.commit("update_alert_success", true);
context.dispatch("search", {
branchCode: context.state.selected_branch.M_BranchCode ?? "",
regionalId: context.state.selected_regional.S_RegionalID,
search: context.state.x_search,
current_page: context.state.current_page,
xdate: context.state.xdate,
periodeid: context.state.selected_periode.id
});
context.commit("update_total_jurnal_not_posted", []);
context.commit("update_dialog_confirm_posting", false);
}
} catch (error) {
context.commit("update_alert_error", true);
context.commit("update_save_error_message", error.message);
}
},
async getUserApprovalLevel(context) {
try {
let param = { token: one_token() };
const resp = await api.getUserApproveLevel(param);
if (resp.status != "OK") {
context.commit("update_alert_error", true);
context.commit("update_save_error_message", resp.message);
} else {
context.commit("update_user_level", resp.data);
}
} catch (error) {
context.commit("update_alert_error", true);
context.commit("update_save_error_message", error.message);
}
},
async getListingCOA(context) {
try {
let param = {
token: one_token(),
keyword: ""
};
const resp = await api.getListingCOA(param);
if (resp.status != "OK") {
context.commit("update_alert_error", true);
context.commit("update_save_error_message", resp.message);
} else {
context.commit("update_list_coa", resp.data);
}
} catch (error) {
context.commit("update_alert_error", true);
context.commit("update_save_error_message", error.message);
}
},
async requestEditJurnal(context) {
try {
let param = {
token: one_token(),
jurnalID: context.state.selected_journal.jurnalID,
staffID: context.state.user.M_UserID,
staffName: context.state.user.M_UserUsername
};
const resp = await api.requestEditJurnal(param);
if (resp.status != "OK") {
context.commit("update_alert_error", true);
context.commit("update_save_error_message", resp.message);
} else {
context.commit("update_msg_success", resp.data);
context.commit("update_alert_success", true);
context.commit("update_dialog_request_edit", false);
}
} catch (error) {
context.commit("update_alert_error", true);
context.commit("update_save_error_message", error.message);
}
},
async saveEditJurnal(context, newdetail) {
try {
let param = {
token: one_token(),
jurnalID: context.state.selected_journal.jurnalID,
jurnalRequestEditID: context.state.selected_journal.JurnalRequestEditID,
oldjurnaltx: context.state.selected_journal.detailtx,
newjurnaltx: newdetail
};
const resp = await api.saveEditJurnal(param);
if (resp.status != "OK") {
context.commit("update_alert_error", true);
context.commit("update_save_error_message", resp.message);
} else {
context.dispatch("search", {
branchCode: context.state.selected_branch.M_BranchCode ?? "",
regionalId: context.state.selected_regional.S_RegionalID,
search: context.state.x_search,
current_page: context.state.current_page,
xdate: context.state.xdate,
periodeid: context.state.selected_periode.id
});
context.commit("update_dialog_edit_journal", false);
context.commit("update_msg_success", resp.data);
context.commit("update_alert_success", true);
}
} catch (error) {
context.commit("update_alert_error", true);
context.commit("update_save_error_message", error.message);
}
},
async totalJurnalNotPostedPerPeriod(context) {
try {
let param = {
token: one_token(),
periodeID: context.state.selected_periode.id
};
const resp = await api.getTotalJurnalNotPostedPerPeriod(param);
if (resp.status != "OK") {
context.commit("update_alert_error", true);
context.commit("update_save_error_message", resp.message);
} else {
context.commit("update_total_jurnal_not_posted", resp.data ?? []);
}
} catch (error) {
context.commit("update_alert_error", true);
context.commit("update_save_error_message", error.message);
}
},
async getDataJurnalNotClosedPerPeriod(context) {
try {
let param = {
token: one_token(),
periodeID: context.state.selected_periode.id
};
const resp = await api.getDataJurnalNotClosedPerPeriod(param);
if (resp.status != "OK") {
context.commit("update_alert_error", true);
context.commit("update_save_error_message", resp.message);
} else {
context.commit("update_jurnal_to_close", resp.data ?? []);
}
} catch (error) {
context.commit("update_alert_error", true);
context.commit("update_save_error_message", error.message);
}
},
async closeJurnalPerPeriode(context, typeid) {
try {
let param = {
token: one_token(),
jurnalTypeID: typeid,
periodeID: context.state.selected_periode.id
};
const resp = await api.closeJurnalPerPeriode(param);
if (resp.status != "OK") {
context.commit("update_alert_error", true);
context.commit("update_save_error_message", resp.message);
} else {
context.commit("update_msg_success", resp.data);
context.commit("update_alert_success", true);
context.dispatch("search", {
branchCode: context.state.selected_branch.M_BranchCode ?? "",
regionalId: context.state.selected_regional.S_RegionalID,
search: context.state.x_search,
current_page: context.state.current_page,
xdate: context.state.xdate,
periodeid: context.state.selected_periode.id
});
context.commit("update_jurnal_to_close", []);
context.commit("update_dialog_close_jurnal", false);
}
} catch (error) {
context.commit("update_alert_error", true);
context.commit("update_save_error_message", error.message);
}
}
}
};

View File

@@ -0,0 +1,23 @@
// State
// data ...
// Mutations
//
//
// Actions
import journal from "./modules/journal.js";
import system from "../../../apps/modules/system/system.js";
export const store = new Vuex.Store({
modules: {
journal: journal,
system:system
},
state: {
},
mutations: {
},
actions: {
}
});

Some files were not shown because too many files have changed in this diff Show More