![]() Server : Apache System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64 User : corals ( 1002) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/corals/ts.corals.io/frontend/pages/ |
<template> <div> <CRUDIndex ref="expensesTable" :columns="columns" :resourceURL="resourceUrl" :options="options" :form="form" :bulk-action-options="bulkActionOptions" :labels="labels" :cloneAttr="cloneAttr" form-size="lg"> <template v-slot:user_id="{object}"> {{ object.row.user }} </template> <template v-slot:project="{object}"> <nuxt-link :to="`/clients/${object.row.client_id}/projects/${object.row.project_id}`"> {{ object.row.project }} </nuxt-link> </template> <template v-slot:client="{object}"> <nuxt-link :to="'/clients/'+object.row.client_id"> {{ object.row.client }} </nuxt-link> </template> <template v-slot:payment_method="{object}"> {{ object.row.payment_method }} </template> <template v-slot:category_id="{object}"> {{ object.row.category }} </template> <template v-slot:file="{object}"> <a :href="object.row.file" target="_blank" v-if="object.row.file">File</a> <span v-else>-</span> </template> <template v-slot:status="{object}"> <span v-html="object.row.status"></span> </template> <template v-slot:invoice="{object}"> <nuxt-link :to="'/invoices/'+object.row.invoice_id" v-if="object.row.invoice_id && object.row.invoice_id !== '-'"> {{ object.row.invoice_code }} </nuxt-link> <span v-else-if="object.row.billable"> Not Invoiced </span> <span v-else> - </span> </template> <template v-slot:default="{form}"> <div class="" v-if="!form.id"> <div class="custom-control custom-checkbox mb-2"> <input type="checkbox" id="active_options" class="custom-control-input" v-model="active_options"/> <label for="active_options" class="custom-control-label"> <small>Show Active Options</small> </label> </div> </div> <div class="row sm-gutters"> <div class="col-md-5"> <corals-datepicker :form="form" required field="expense_date" label="Expense Date"/> </div> <div class="col-md-4"> <corals-input :form="form" type="number" field="amount" step="0.1" required min="0"/> </div> <div class="col-md-3"> <corals-select :form="form" field="currency" :options="form.getFormData('currency_options')" required/> </div> </div> <div class="row sm-gutters"> <div class="col-md-5"> <corals-select :form="form" required label="Category" field="category_id" :options="getCategoriesOrProjectsOptions(form.getFormData('categories'))"/> <corals-checkbox field="billable" :form="form" description="It will be included in the next client invoice when project selected"/> </div> <div class="col-md-7"> <corals-textarea field="notes" required rows="3" :form="form"/> </div> </div> <div class="row sm-gutters"> <div class="col-md-5"> <corals-select :form="form" label="Project" field="project_id" :options="getCategoriesOrProjectsOptions(form.getFormData('projects'))"/> </div> <div class="col-md-7"> <corals-select :form="form" label="User" field="user_id" :options="form.getFormData('users')"/> </div> </div> <div class="row sm-gutters"> <div class="col-md-6"> <corals-radio :form="form" label="Payment Method" field="payment_method" :list="form.getFormData('payment_method_options')" required/> </div> <div class="col-md-6"> <corals-radio :form="form" field="status" required label="Status" :list="form.getFormData('status_options')"/> </div> </div> <div class="row sm-gutters"> <div class="col-md-6"> <label>Attachment</label> <div v-if="filePath"> <a :href="filePath" target="_blank">Show File</a> <corals-checkbox field="clear" :form="form"/> </div> <div class="mb-2"> <b-form-file v-model="form.file" placeholder="Upload File..."></b-form-file> <span v-if="filePath && form.file" class="text-muted small">Note: when a new file is uploaded, the existing file is automatically deleted</span> </div> </div> </div> </template> <template v-slot:extra-actions="{object}"> <b-link @click.prevent="generateInvoiceForExpense(object)" title="Generate an Invoice" v-if="object.generateInvoice"> <fa icon="file-invoice" class="text-success"/> </b-link> </template> </CRUDIndex> </div> </template> <script> import CRUDIndex from "@/components/layout/CRUDIndex"; import commonMixin from "@/mixins/commonMixin"; import CoralsSelect from "@/components/CoralsForm/CoralsSelect"; export default { name: "index", components: {CoralsSelect, CRUDIndex}, middleware: 'Authorization', mixins: [commonMixin], provide() { return { handleBulkAction: this.handleBulkAction, } }, data() { return { active_options: 1, filePath: null, resourceUrl: 'timesheet/expenses', labels: { title: 'Expenses', singularTitle: 'Expense', }, cloneAttr: { category_id: null, project_id: null, client_id: null, notes: null, amount: null, expense_date: new Date(), billable: null, status: null, currency: null, payment_method: null, }, options: { listColumns: { billable: this.yesNoOptions(), status: [], payment_method: [], category_id: [], user_id: [], }, customColumns: ['status', 'project', 'client', 'payment_method', 'file', 'user_id', 'category_id', 'invoice'], filterable: ['status', 'payment_method', 'expense_date', 'category_id', 'project', 'client', 'notes', 'user_id', 'invoice'], hideCreate: this.$cant('create', 'expense'), headings: { 'payment_method': 'Payment Method', 'category_id': 'Category', 'user_id': 'User', }, }, form: this.$form({ id: null, category_id: '', project_id: '', client_id: '', user_id: '', notes: '', amount: '', status: 'paid', file: null, clear: 0, expense_date: new Date(), billable: 0, currency: 'usd', payment_method: 'paypal', }, { fetchFormDataURL: '/timesheet/expenses/get-form-data', model: 'expense', loadFormDataCallBack: () => { this.options.listColumns.status = this.getOptions(this.form.formData.status_options); let categories = JSON.parse(JSON.stringify(this.form.formData.categories)); categories.shift(); this.options.listColumns.category_id = this.getOptions(categories); this.options.listColumns.payment_method = this.getOptions(this.form.formData.payment_method_options); this.options.listColumns.user_id = this.getOptions(this.form.formData.users); } }), } }, methods: { generateInvoiceForExpense(expense) { this.$swal.fire({ title: 'Are you sure?', text: "You wont to generate invoice for this expenses?", icon: 'warning', showCancelButton: true, confirmButtonColor: '#14A44D', cancelButtonColor: '#d7d7d7', confirmButtonText: 'Yes, Generate it!' }).then((result) => { if (result.value) { this.$axios.post(`timesheet/expenses/${expense.id}/generate-invoice`) .then(response => { let level = response.data.data.level; let message = response.data.data.message; if (level === 'success') { this.$toast.success(message); } else { this.$toast.error(message); } this.$refs.expensesTable.refresh(); }) } }) }, getOptions(list) { let allOption = {id: '', text: 'All'}; let options = []; options.push(allOption); list.map(row => { let label = row.label.split(","); options.push({id: row.id ?? row.value, text: label[0]}); }); return options; }, getCategoriesOrProjectsOptions(arrayData) { let resultsData = []; let DataGroups = []; let activeObjects = []; if (!this.active_options) { activeObjects = arrayData.filter((object => object['group'] !== true)); DataGroups = arrayData.filter((group => group['group'] === true)); } else { activeObjects = arrayData.filter((object => (object['is_active'] === 1 || object['status'] === 'active') && object['group'] !== true)); DataGroups = arrayData.filter((group => group['group'] === true && group['status'] === 'active')); } DataGroups.forEach(group => { group['is_group_empty'] = true; resultsData.push(group); activeObjects.filter(activeObject => { if (group['code'] === activeObject['group']) { group['is_group_empty'] = false; resultsData.push(activeObject); } }); }); return resultsData; }, handleBulkAction(action, selectedIds) { this.$bvModal.msgBoxConfirm('Are you sure?', { size: 'md', buttonSize: 'sm', okVariant: 'danger', footerClass: 'p-2', hideHeaderClose: false, centered: true }) .then(value => { if (value === true) { this.$axios.post('timesheet/expenses/bulk-action', { 'selection': selectedIds, 'action': action }).then(response => { let level = response.data.data.level; let message = response.data.data.message; if (level === 'success') { this.$toast.success(message); } else { this.$toast.error(message); } this.$eventBus.$emit('setSelectedIds', []); this.$refs.expensesTable.refresh(); }).catch(err => { this.$toast.error(err.response.data.message); }); } }) .catch(err => { }) }, }, watch: { 'form.id'() { this.filePath = null; if (this.form.file !== null && typeof this.form.file !== 'object') { this.filePath = this.form.file; this.form.file = null; } } }, computed: { columns() { let columns = []; if (this.$isAdmin() && this.bulkActionOptions.length) { columns.push('checkbox'); } columns.push('expense_date', 'user_id', 'amount', 'file', 'status', 'payment_method', 'category_id', 'project', 'client', 'notes', 'invoice', 'actions'); if (this.$notAdmin()) { columns.pop(); } return columns; }, bulkActionOptions() { let actions = ['delete','paid','pending','voided']; if (this.$notAdmin()) { actions.pop(); } return actions; }, }, } </script> <style scoped> </style>