Luciano
10/7/2019 - 7:51 PM

VUE JS list child component for Invoices

<template>

    <div>

        <div v-if="show_filter !== false" class="px-4 pt-4 mb-4" :class="scope_customer ? 'shadow-none' : 'ui-bordered'">
            <b-form @submit.prevent="refreshTable(true)">
                <b-form-row>
                    <b-form-group class="col" label="Buscar">
                        <input
                            type="text"
                            class="form-control"
                            v-model="search.text"
                            :placeholder="'Ingrese términos a buscar...'">
                    </b-form-group>

                    <b-form-group class="input-group col" label="Fecha">
                        <div class="input-group">
                            <flat-pickr
                                v-model="search.date"
                                :config="dateRangeConfig"
                                class="form-control"
                                placeholder="Seleccione..."
                                name="date">
                            </flat-pickr>
                            <div class="input-group-btn">
                                <button class="btn btn-sm btn-danger md-btn-flat mt-2" type="button" title="Clear" data-clear>
                                    <i class="fa fa-times"><span aria-hidden="true" class="sr-only">Clear</span></i>
                                </button>
                            </div>
                        </div>
                    </b-form-group>

                    <b-form-group class="col" label="Estado">
                        <multiselect
                            :allow-empty="true"
                            :multiple="false"
                            :close-on-select="true"
                            :searchable="false"
                            :show-labels="false"
                            placeholder="Seleccione..."
                            name="status"
                            v-model="search.status"
                            label="name"
                            track-by="id"
                            :options="statuses">
                        </multiselect>
                    </b-form-group>

                    <b-form-group class="col" label="Talonario">
                        <multiselect
                            :allow-empty="true"
                            :multiple="false"
                            :close-on-select="true"
                            :searchable="false"
                            :show-labels="false"
                            placeholder="Seleccione..."
                            name="book"
                            v-model="search.book"
                            label="full_name"
                            track-by="id"
                            :options="books">
                        </multiselect>
                    </b-form-group>

                    <b-form-group class="col" label="Pendiente de Pago">
                        <multiselect
                            :allow-empty="true"
                            :multiple="false"
                            :close-on-select="true"
                            :searchable="false"
                            :show-labels="false"
                            placeholder="Seleccione..."
                            name="total_pending"
                            v-model="search.total_pending"
                            label="name"
                            track-by="id"
                            :options="[{id:1, name:'SI'},{id:0, name: 'NO'}]">
                        </multiselect>
                    </b-form-group>

                    <b-form-group class="col-md col-xl-2 mb-4">
                        <label class="form-label d-none d-md-block">&nbsp;</label>
                        <ladda-btn type="submit" :loading="loading" data-style="zoom-out" class="btn btn-secondary btn-block">Buscar</ladda-btn>
                    </b-form-group>
                </b-form-row>
            </b-form>
        </div>

        <b-card :header="card_header || ''"  header-tag="h6" :class="scope_customer ? 'shadow-none' : ''">

            <v-server-table
                v-if="!scope_customer || (scope_customer && customer_id)"
                ref="table"
                :columns="columns"
                :options="options"
                @loading="tableLoading"
                @loaded="tableLoaded">

                <template slot="id" slot-scope="props">
                    <router-link
                        tag="a"
                        class="text-nowrap"
                        :to="{name:'invoice-view', params: { invoice_id: props.row.id } }"
                        :target="scope_customer ? '_blank' : ''"
                        title="Ver">{{ props.row.number }}
                    </router-link>
                </template>

                <template slot="date" slot-scope="props">
                    {{ moment.utc(props.row.date).format('DD/MM/YYYY') }}
                </template>

                <template slot="status" slot-scope="props">

                    <span v-if="props.row.status_id == 6" class="badge badge-success">{{ props.row.status }}</span>
                    <span v-else-if="props.row.status_id == 5" class="badge badge-danger">{{ props.row.status }}</span>
                    <span v-else class="badge badge-default">{{ props.row.status }}</span>

                </template>

                <template slot="customer" slot-scope="props">
                    <router-link
                        v-if="props.row.customer_id && $store.getters.user.can.view_customer"
                        tag="a"
                        :to="{name:'customer-view', params: { customer_id: props.row.customer_id } }"
                        title="Editar">
                            {{ props.row.customer }}
                            <!--span v-if="props.row.customer && props.row.customer.deleted_at" class="badge badge-outline-danger ml-4">Eliminado</span-->
                    </router-link>

                    <div v-else>{{ props.row.customer}}</div>
                </template>

                <template slot="total_pending" slot-scope="props">
                    <span v-if="props.row.total_pending == 0 && props.row.total != 0" class="text-success">{{ props.row.total_pending }}</span>
                    <span v-else>{{ props.row.total_pending }}</span>
                </template>

                <template slot="actions" slot-scope="props">
                    <div class="text-center">

                        <router-link
                            :disabled="!$store.getters.user.can.edit_invoice"
                            tag="b-btn"
                            class="btn-dark btn-xs icon-btn md-btn-flat user-tooltip"
                            title="Editar"
                            :to="{name:'invoice-edit', params: { invoice_id: props.row.id } }"><i class="ion ion-md-create"></i>
                        </router-link>

                        <b-dropdown variant="default btn-xs icon-btn md-btn-flat hide-arrow" :right="!isRTL">

                            <template slot="button-content"><i class="ion ion-ios-settings"></i></template>

                            <b-dropdown-item
                                :disabled="!$store.getters.user.can.discharge_invoice || props.row.status_id == 5"
                                @click.prevent="formality = props.row">Anular
                            </b-dropdown-item>

                            <div role="separator" class="dropdown-divider m-0"></div>

                            <b-dropdown-item :to="'/print/invoice/'+props.row.id" target="_blank">Imprimir</b-dropdown-item>

                        </b-dropdown>
                    </div>
                </template>
            </v-server-table>
        </b-card>

        <!-- DISCHARGE COMPONENT -->
        <discharge-formality-table-component
            class="d-inline"
            :formality="formality"
            :permission="$store.getters.user.can.discharge_invoice"
            @discharged="refreshTable"
            @cancelled="formality = {}">
        </discharge-formality-table-component>

    </div>

</template>

<script>

import NProgress from 'nprogress'
import flatPickr from 'vue-flatpickr-component'
import {Spanish} from 'flatpickr/dist/l10n/es.js'
import moment from 'moment'
import LaddaBtn from '@/vendor/libs/ladda/Ladda'
import Multiselect from 'vue-multiselect'

import DischargeFormalityTableComponent from '@/components/formalities/DischargeFormalityTableComponent'

export default {
    name: 'invoice-list-table',

    components: {
        NProgress,
        flatPickr,
        LaddaBtn,
        Multiselect,
        DischargeFormalityTableComponent,
    },

    props: [
        'customer_id',
        'scope_customer',
        'show_filter',
        'card_header',
        'date_until',
        'status'
    ],

    data() {
        return {

            moment:moment,

            // Flatpicker
            dateRangeConfig: {
                altInput: true,
                altFormat: 'd/m/Y',
                allowInput: true,
                locale: Spanish,
                mode: 'range',
                wrap: true
            },

            columns: this.scope_customer ?
                        ( this.$store.getters.user.can.view_prices ?
                            ['id', 'date', 'status', 'total', 'total_pending', 'actions'] :
                            ['id', 'date', 'status', 'actions'] )
                        :
                        ( this.$store.getters.user.can.view_prices ?
                            ['id', 'date', 'customer', 'status', 'total', 'total_pending', 'actions'] :
                            ['id', 'date', 'customer', 'status', 'actions'] )
                        ,

            options: {
                filterable: false,
                uniqueKey:'id',
                highlightMatches: true,
                perPage:25,
                sortable: [''],

                pagination: {
                    chunk: 5,
                    edge: true
                },

                sortIcon: {
                    is: 'fa-sort',
                    base: 'fas',
                    up: 'fa-sort-up',
                    down: 'fa-sort-down'
                },

                texts:{
                    count:"Mostrando {from} a {to} de {count} registros|{count} registros|Un registro",
                    first:'Primero',
                    last:'Último',
                    filter:"Buscar:",
                    filterPlaceholder:"Términos a buscar",
                    limit:"Registros:",
                    page:"Página:",
                    noResults:"No hay resultados",
                    filterBy:"Filtrar por {column}",
                    loading:'Cargando...',
                    defaultOption:'Seleccionar {column}',
                    columns:'Columnas'
                },

                headings: {
                    id: 'Número',
                    date: 'Fecha',
                    expiration_date: 'Fecha de Entrega',
                    status: 'Estado',
                    title: 'Título',
                    category: 'Categoría',
                    customer: 'Cliente',
                    total: 'Total',
                    total_pending: 'Total Recibido',
                    total_pending: 'Saldo Pendiente',
                    actions: '',
                },

                orderBy: {
                    ascending: false,
                    column:  'id'
                },

                requestKeys: {
                    query:'queryString'
                },

                requestFunction: function (data) {

                    data.date = this.search.date
                    data.expiration_date = this.search.expiration_date
                    data.text = this.search.text

                    if (this.date_until) data.date_until = this.date_until
                    if (this.status) data.status = this.status
                    if (this.customer_id) data.customer = this.customer_id
                    if (this.search.total_pending) data.total_pending = this.search.total_pending.id

                    data.status = this.search.status ? [this.search.status.id] : this.statuses.map(item => item.id)
                    data.book = this.search.book ? [this.search.book.id] : this.books.map(item => item.id)

                    return axios.get('/invoices/all', {
                        params: data
                    }).catch(function (e) {
                        this.dispatch('error', e);
                    }.bind(this));

                }.bind(this),

                responseAdapter: function(resp) {
                    var data = this.getResponseData(resp);
                    let array = Object.values(data.data);

                    return { data: array, count: data.count }
                }
            },

            statuses:[],
            books: [],

            loading:false,

            formality: null,
            search:{},
        }
    },

    mounted(){
        this.getStatuses()
        this.getBooks()
    },

    methods: {

        getStatuses() {
            axios.get('/statuses/all')
                .then((response) => {
                    this.statuses = response.data.filter(function(e) { return e['name'] === 'Activo' || e['name'] === 'Anulado' })
                }).catch((error) => {
                    console.log(error.response.data)
                });
        },

        getBooks() {

            axios({
                method: 'post',
                url:    '/books/by-group',
                data:   {
                    ids: [process.env.MIX_INVOICE_GROUP_ID]
                }
            })
            .then((response)=>{

                this.books = response.data

            }).catch((error)=>{
                console.log(error.response.data)
            })
        },

        tableLoading(){
            NProgress.start()
        },

        tableLoaded(){
            NProgress.done()
        },

        refreshTable(refresh = false){
            refresh ? this.$refs.table.refresh() : this.$refs.table.getData()
        },
    }
}
</script>