| Server IP : 34.87.99.72 / Your IP : 216.73.217.31 Web Server : Apache/2.4.46 (Unix) OpenSSL/1.1.1n System : Linux zlock-bitnami-lamp-prod-v2-vm 4.19.0-16-cloud-amd64 #1 SMP Debian 4.19.181-1 (2021-03-19) x86_64 User : bitnami ( 1000) PHP Version : 7.4.18 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : OFF Directory : /opt/bitnami/apache/htdocs/app/resources/js/views/BoxDeliveries/ |
Upload File : |
<template>
<v-container>
<!-- introduction -->
<v-row align="end">
<v-col>
<div class="headline font-weight-bold">Booking Histories (Deliveries)</div>
<div class="subtitle-2 grey--text">Delivery booking histories created by customer.</div>
</v-col>
</v-row>
<!-- search bar -->
<v-row
dense
align="center"
class="mt-3"
>
<w-search-bar
:search.sync="search_.search"
:search-by.sync="search_.searchBy"
:disabled="model_loading_"
:items="searchBy_options"
:date-search-by.sync="date_search_by"
@search="searchData_()"
></w-search-bar>
</v-row>
<v-row align="center" class="mt-3" justify="end">
<v-spacer></v-spacer>
<v-col cols="auto">
<w-action-btn-group
:items="action_btn_group_items()"
></w-action-btn-group>
</v-col>
</v-row>
<v-card class="mt-4" color="transparent" flat>
<v-data-table
ref="dataTable"
:headers="table_headers"
:items="resourceDataSet_"
:options.sync="settings_"
:server-items-length="totalData_"
:footer-props="{
'items-per-page-options': [5, 10, 25, 50]
}"
:loading="model_loading_"
disable-sort
:item-class="row_classes_"
>
<template #[`item.delivery_booking_fee`]="{ item }">
{{ 'RM ' + ($authUser.isAdmin() ? item.delivery_booking_fee : '-' ) }}
</template>
<template #[`item.zlock_profit_sharing`]="{ item }">
{{ 'RM ' + getZlockProfitSharing(item) }}
</template>
<template #[`item.created_at`]="{ item }">
{{ $dayjs(item.created_at).format('YYYY-MM-DD hh:mma') }}
</template>
<template #[`item.dropper`]="{ item }">
<div>{{ item.dropper ? item.dropper.full_name : "-" }}</div>
<div class="x-caption font-italic">{{ item.dropper ? item.dropper.unique_id : "-" }}</div>
</template>
<template #[`item.partner`]="{ item }">
<div>{{ item.partner ? item.partner.full_name : "-" }}</div>
<div class="x-caption font-italic">{{ item.partner ? item.partner.partner_package_name : "-" }}</div>
</template>
<template #[`item.delivery_partner`]="{ item }">
{{ item.delivery_partner.name || '-' }}
</template>
<template #[`item.collected_at`]="{ item }">
{{ item.collected_at ? $dayjs(item.collected_at).format('YYYY-MM-DD hh:mma') : '-' }}
</template>
<template #[`item.status`]="{ item }">
<a v-if="item.status.tracking_url" :href="item.status.tracking_url" target="_blank">Track</a>
<span v-else :class="item.status.class">{{ item.status.message }}</span>
</template>
<template #[`item.action`]="{ item }">
<v-btn icon small :to="'/booking-history/delivery/'+item.id">
<v-icon small>mdi-eye</v-icon>
</v-btn>
<w-dropdown-menu
v-if="$authUser.isAdmin()"
left bottom
:items="menu_items(item)"
></w-dropdown-menu>
</template>
</v-data-table>
</v-card>
<!-- form dialog -->
<v-dialog v-model="form_dialog_" max-width="550px" persistent>
<BoxDeliveryForm
:item="form_item_" :action="form_action_" :visible.sync="form_dialog_"
@initialize="initialize_()"
></BoxDeliveryForm>
</v-dialog>
<v-dialog v-model="delivery_form" max-width="550px" persistent>
<DeliveryInstructionExport
:visible.sync="delivery_form"
></DeliveryInstructionExport>
</v-dialog>
<!-- filter dialog -->
<w-side-dialog
v-model="filter_dialog"
title="Filters"
clearable
@clear="initFilters()"
>
<template #default>
<v-row dense>
<template v-for="(filter,i) in filter_options">
<v-col :key="i" cols="12">
<v-select
v-model="filters_[filter.model]"
:label="filter.label"
:items="filter.items"
class="caption"
outlined
dense hide-details
></v-select>
</v-col>
</template>
</v-row>
</template>
<template #actions>
<div class="text-right">
<v-btn
rounded block color="primary"
@click="searchData_()"
>
Apply
</v-btn>
</div>
</template>
</w-side-dialog>
<!-- model info dialog -->
<v-navigation-drawer
v-model="view_dialog_"
floating
app
right
temporary
:style="$vuetify.breakpoint.mdAndUp ? 'min-width: 350px;' : '' "
>
<v-card height="100%">
<pre>{{ view_item_ }}</pre>
</v-card>
</v-navigation-drawer>
<v-dialog v-model="report_date_form" max-width="550px" persistent>
<ReportDateForm
:visible.sync="report_date_form" :type_id="report_date_type_id"
@download="download"
></ReportDateForm>
</v-dialog>
</v-container>
</template>
<script>
import BoxDeliveryForm from './BoxDeliveryOverviewForm'
import DeliveryInstructionExport from './BoxDeliveryInstructionForm'
import WActionBtnGroup from "@components/WActionBtnGroup"
import WDropdownMenu from "@components/WDropdownMenu"
import WSideDialog from "@components/WSideDialog"
import WSearchBar from "@components/WSearchBar"
import ReportDateForm from "../Reports/ReportDateForm"
import { resourceMixin } from "@/js/mixins/ResourceMixin"
import { formActionMixin } from "@/js/mixins/FormActionMixin"
import { errorHandlerMixin } from "@/js/mixins/ErrorHandlerMixin"
const PARTNER_ROLE_ID = 2
export default{
components:{
BoxDeliveryForm,
DeliveryInstructionExport,
WActionBtnGroup,
WDropdownMenu,
WSideDialog,
WSearchBar,
ReportDateForm,
},
mixins: [
resourceMixin,
formActionMixin,
errorHandlerMixin
],
props:{
user: {
type: Object,
default: ()=>{
return {}
}
},
},
data(){
return {
table_headers: [],
partner_list: [],
filter_dialog: false,
filter_options:[],
sort_options:[],
searchBy_options: [
{ value: 'id', text: 'ID' },
{ value: 'dropper_name', text: 'Dropper Name' },
{ value: 'locker_name', text: 'Locker Name' },
{ value: 'delivery_partner', text: 'Delivery Partner' },
{ value: 'start_at', text: 'Start At' },
{ value: 'collected_at', text: 'Collected At' },
],
delivery_form: false,
date_search_by: [
'start_at',
'collected_at',
],
report_date_form: false,
report_date_type_id: 0
}
},
computed: {
},
created(){
this.search_.searchBy = 'dropper_name'
this.getAllRefs_([
]).then(()=>{
this.initTableHeader()
this.getPartnerList()
this.setupFilterBar()
this.initFilters()
}).then(()=>{
this.initialize_()
})
},
methods:{
emitIntialize(){
this.$emit('initialize')
this.initialize_()
},
initFilters(){
this.filters_ = {
user_id : null,
status_id : null,
}
},
getResourceData_(){
let payload = {
...this.setPagination_(),
...this.search_,
...this.filters_,
...this.sort_,
}
if(payload.status_id == 1){
payload.uncollected = 1;
}else if(payload.status_id == 2){
payload.collected = 1;
}
this.model_loading_ = true
this.$api.getBoxDeliveryOverviewList(payload).then((res)=>{
let { data, total } = res.data.result
this.resourceDataSet_ = data
this.totalData_ = total
this.resourceDataSet_.forEach((item)=>{
let classes = "grey--text"
if(item.status.polar_id == 1){
classes = "error--text"
}else if(item.status.polar_id == 2){
classes = "success--text"
}
item.status.class = classes
})
}).catch((err)=>{
this.errorHandler_(err)
}).finally(()=>{
this.model_loading_ = false
})
},
menu_items(item){
return [
// {
// icon: "mdi-eye", title: "View More",
// action: ()=>{ this.viewMore_(item) }
// },
{
icon: "mdi-square-edit-outline", title: "Edit",
action: () => {
this.editItem_(item)
}
},
{
icon: "mdi-truck-delivery-outline", title: "Collect Item",
action: () => {
this.confirmCollectItem(item)
},
disabled: item.dirty_at == null || item.collected_at != null ? true : false
},
{
icon: "mdi-printer", title: "Print Delivery Label",
action: () => {
this.confirmPrintLabel(item)
},
},
]
},
download(date = []){
let payload = {
...this.search_,
...this.filters_,
...this.sort_,
}
if(payload.status_id == 1){
payload.uncollected = 1;
}else if(payload.status_id == 2){
payload.collected = 1;
}
payload.date = date
this.model_loading_ = true
this.$api.exportBoxDeliveryOverviewList(payload).then((res)=>{
let result = res.data.result
if(result)
this.downloadFile_(result.fileUrl, result.fileName)
else
this.$toast.warning("No data")
}).catch((err)=>{
this.errorHandler_(err)
}).finally(()=>{
this.model_loading_ = false
})
},
action_btn_group_items(){
return [
{
icon: "mdi-refresh",
disabled: this.model_loading_,
action: () => { this.searchData_() }
},
{
icon: "mdi-filter-outline",
action: () => { this.filter_dialog = true }
},
{
icon: "mdi-download",
disabled: this.model_loading_,
action: () => { this.report_date_form = true }
},
{
icon: "mdi-truck",
disabled: this.model_loading_,
action: () => { this.delivery_form = true }
},
]
},
setupFilterBar(){
this.filter_options = [
{
cols: 12,
model: "status_id",
label: "Status",
items: [
{ value: null, text: "All" },
{ value: 1, text: "On-going" },
{ value: 2, text: "Completed" },
],
},
]
},
getPartnerProfitSharing(item)
{
let total_booking_fees_partner = item.total_booking_fee_partner;
var profit_percentage = 0.30
if(item.meta.profit_percentage)
{
profit_percentage = item.meta.profit_percentage/100
}
else if(item.locker[0].partner)
{
let partner = item.locker[0].partner
if(partner.partner_package)
{
profit_percentage = partner.partner_package.profit_percentage/100
}
}
else
return 0.00
return (total_booking_fees_partner * profit_percentage).toFixed(2);
},
getZlockProfitSharing(item)
{
return (item.total_booking_fee - this.getPartnerProfitSharing(item)).toFixed(2);
},
initTableHeader()
{
this.table_headers = [
{ text: '#', value: 'id' },
{ text: 'Dropper', value: 'dropper' },
{ text: 'Locker', value: 'locker[0].name' },
{ text: 'Locker Partner', value: 'partner' },
{ text: 'Delivery Partner', value: 'delivery_partner' },
{ text: 'Start at', value: 'created_at' },
{ text: 'Collected at', value: 'collected_at' },
// { text: 'Actions', value: 'action', class: 'text-center' },
]
if(this.$authUser.isAdmin())
{
this.table_headers = [
...this.table_headers,
{ text: 'Compartment No', value: 'box.box_no' },
{ text: 'Charges', value: 'delivery_booking_fee' },
]
}
this.table_headers = [
...this.table_headers,
{ text: 'Actions', value: 'action', class: 'text-center' },
{ text: 'Status', value: 'status' },
]
},
getPartnerList()
{
if(this.$authUser.isAdmin())
{
let payload = {
role_id: PARTNER_ROLE_ID
}
this.model_loading_ = true
this.$api.getUserList(payload).then((res)=>{
let { data } = res.data.result
this.partner_list = data
console.log(this.partner_list)
}).catch((err)=>{
this.errorHandler_(err)
}).finally(()=>{
this.model_loading_ = false
})
}
},
async confirmCollectItem(item){
let text = `<div class="pt-2">
<div class="mb-2 font-weight-bold">Are you sure to continue?</div>
<div class="caption font-italic">
The locker door of this item will be opened. Please get staff <strong>READY</strong> before proceed.
</div>
</div>`
const res = await this.$dialog.confirm({
color: 'red',
text: text,
title: 'Warning'
})
if(res){
this.collectItem(item)
}
},
collectItem(item){
this.submit_loading = true
this.errors = {}
let payload = {
id : item.id,
}
let theApi = this.$api.collectBoxDelivery(payload)
theApi.then((res)=>{
this.$toast.success("Item collected successfully.")
this.initialize_()
}).catch((err) => {
this.errors = this.errorHandler_(err,[
"id",
])
}).finally(()=>{
this.submit_loading = false
})
},
async confirmPrintLabel(item){
let text = `<div class="pt-2">
<div class="mb-2 font-weight-bold">Are you sure to continue?</div>
<div class="caption font-italic">
The delivery label will be printed. Please have someone <strong>READY</strong> before proceed.
</div>
</div>`
const res = await this.$dialog.confirm({
color: 'red',
text: text,
title: 'Warning'
})
if(res){
this.printLabel(item)
}
},
printLabel(item){
this.submit_loading = true
this.errors = {}
let payload = {
id : String(item.id),
}
let theApi = this.$api.printLabelBoxDelivery(payload)
theApi.then((res)=>{
this.$toast.success("Printing delivery label...")
this.initialize_()
}).catch((err) => {
this.errors = this.errorHandler_(err,[
"id",
])
}).finally(()=>{
this.submit_loading = false
})
},
}
}
</script>