build version 400

This commit is contained in:
Mohit Panjwani
2020-12-02 17:54:08 +05:30
parent 326508e567
commit 89ee58590c
963 changed files with 62887 additions and 48868 deletions

View File

@ -1,262 +1,375 @@
<template>
<div class="payment-create main-content">
<base-page class="relative payment-create">
<form action="" @submit.prevent="submitPaymentData">
<div class="page-header">
<h3 class="page-title">{{ isEdit ? $t('payments.edit_payment') : $t('payments.new_payment') }}</h3>
<ol class="breadcrumb">
<li class="breadcrumb-item"><router-link slot="item-title" to="/admin/dashboard">{{ $t('general.home') }}</router-link></li>
<li class="breadcrumb-item"><router-link slot="item-title" to="/admin/payments">{{ $tc('payments.payment', 2) }}</router-link></li>
<li class="breadcrumb-item">{{ isEdit ? $t('payments.edit_payment') : $t('payments.new_payment') }}</li>
</ol>
<div class="page-actions header-button-container">
<base-button
<sw-page-header class="mb-5" :title="pageTitle">
<sw-breadcrumb slot="breadcrumbs">
<sw-breadcrumb-item
to="/admin/dashboard"
:title="$t('general.home')"
/>
<sw-breadcrumb-item
to="/admin/payments"
:title="$tc('payments.payment', 2)"
/>
<sw-breadcrumb-item
v-if="$route.name === 'payments.edit'"
to="#"
:title="$t('payments.edit_payment')"
active
/>
<sw-breadcrumb-item
v-else
to="#"
:title="$t('payments.new_payment')"
active
/>
</sw-breadcrumb>
<template slot="actions">
<sw-button
:loading="isLoading"
:disabled="isLoading"
icon="save"
color="theme"
type="submit">
{{ isEdit ? $t('payments.update_payment') : $t('payments.save_payment') }}
</base-button>
</div>
</div>
<div class="payment-card card">
<div class="card-body">
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label class="form-label">{{ $t('payments.date') }}</label><span class="text-danger"> *</span>
<base-date-picker
v-model="formData.payment_date"
:invalid="$v.formData.payment_date.$error"
:calendar-button="true"
calendar-button-icon="calendar"
@change="$v.formData.payment_date.$touch()"
/>
<div v-if="$v.formData.payment_date.$error">
<span v-if="!$v.formData.payment_date.required" class="text-danger">{{ $t('validation.required') }}</span>
</div>
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label class="form-label">{{ $t('payments.payment_number') }}</label><span class="text-danger"> *</span>
<base-prefix-input
:invalid="$v.paymentNumAttribute.$error"
v-model.trim="paymentNumAttribute"
:prefix="paymentPrefix"
@input="$v.paymentNumAttribute.$touch()"
/>
<div v-if="$v.paymentNumAttribute.$error">
<span v-if="!$v.paymentNumAttribute.required" class="text-danger">{{ $tc('validation.required') }}</span>
<span v-if="!$v.paymentNumAttribute.numeric" class="text-danger">{{ $tc('validation.numbers_only') }}</span>
</div>
</div>
</div>
<div class="col-sm-6">
<label class="form-label">{{ $t('payments.customer') }}</label><span class="text-danger"> *</span>
<base-select
ref="baseSelect"
v-model="customer"
:invalid="$v.customer.$error"
:options="customerList"
:searchable="true"
:show-labels="false"
:allow-empty="false"
:disabled="isEdit"
:placeholder="$t('customers.select_a_customer')"
label="name"
track-by="id"
variant="primary"
type="submit"
size="lg"
class="hidden sm:flex"
>
<save-icon v-if="!isLoading" class="mr-2 -ml-1" />
{{
isEdit
? $t('payments.update_payment')
: $t('payments.save_payment')
}}
</sw-button>
</template>
</sw-page-header>
<base-loader v-if="isRequestOnGoing" :show-bg-overlay="true" />
<sw-card v-else>
<div class="grid gap-6 grid-col-1 md:grid-cols-2">
<sw-input-group
:label="$t('payments.date')"
:error="DateError"
required
>
<base-date-picker
v-model="formData.payment_date"
:invalid="$v.formData.payment_date.$error"
:calendar-button="true"
class="mt-1"
calendar-button-icon="calendar"
@change="$v.formData.payment_date.$touch()"
/>
</sw-input-group>
<sw-input-group
:label="$t('payments.payment_number')"
:error="paymentNumError"
required
>
<sw-input
:prefix="`${paymentPrefix} - `"
:invalid="$v.paymentNumAttribute.$error"
v-model.trim="paymentNumAttribute"
class="mt-1"
@input="$v.paymentNumAttribute.$touch()"
/>
</sw-input-group>
<sw-input-group
:label="$t('payments.customer')"
:error="customerError"
required
>
<sw-select
v-model="customer"
:options="customers"
:searchable="true"
:show-labels="false"
:allow-empty="false"
:disabled="isEdit"
:placeholder="$t('customers.select_a_customer')"
label="name"
class="mt-1"
track-by="id"
/>
</sw-input-group>
<sw-input-group :label="$t('payments.invoice')">
<sw-select
v-model="invoice"
:options="invoiceList"
:searchable="true"
:show-labels="false"
:allow-empty="false"
:disabled="isEdit"
:placeholder="$t('invoices.select_invoice')"
:custom-label="invoiceWithAmount"
class="mt-1"
track-by="invoice_number"
/>
</sw-input-group>
<sw-input-group
:label="$t('payments.amount')"
:error="amountError"
required
>
<div class="relative w-full mt-1">
<sw-money
v-model="amount"
:currency="customerCurrency"
:invalid="$v.formData.amount.$error"
class="relative w-full focus:border focus:border-solid focus:border-primary-500"
@input="$v.formData.amount.$touch()"
/>
<div v-if="$v.customer.$error">
<span v-if="!$v.customer.required" class="text-danger">{{ $tc('validation.required') }}</span>
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label class="form-label">{{ $t('payments.invoice') }}</label>
<base-select
v-model="invoice"
:options="invoiceList"
:searchable="true"
:show-labels="false"
:allow-empty="false"
:disabled="isEdit"
:placeholder="$t('invoices.select_invoice')"
:custom-label="invoiceWithAmount"
track-by="invoice_number"
/>
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label class="form-label">{{ $t('payments.amount') }}</label><span class="text-danger"> *</span>
<div class="base-input">
<money
:class="{'invalid' : $v.formData.amount.$error}"
v-model="amount"
v-bind="customerCurrency"
class="input-field"
/>
</div>
<div v-if="$v.formData.amount.$error">
<span v-if="!$v.formData.amount.required" class="text-danger">{{ $t('validation.required') }}</span>
<span v-if="!$v.formData.amount.between && $v.formData.amount.numeric && amount <= 0" class="text-danger">{{ $t('validation.payment_greater_than_zero') }}</span>
<span v-if="!$v.formData.amount.between && amount > 0" class="text-danger">{{ $t('validation.payment_greater_than_due_amount') }}</span>
</div>
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label class="form-label">{{ $t('payments.payment_mode') }}</label>
<base-select
v-model="formData.payment_method"
:options="paymentModes"
:searchable="true"
:show-labels="false"
:placeholder="$t('payments.select_payment_mode')"
label="name"
</sw-input-group>
<sw-input-group :label="$t('payments.payment_mode')">
<sw-select
v-model="formData.payment_method"
:options="paymentModes"
:searchable="true"
:show-labels="false"
:placeholder="$t('payments.select_payment_mode')"
label="name"
:maxHeight="150"
class="mt-1"
>
<div slot="afterList">
<button
type="button"
class="flex items-center justify-center w-full px-2 py-2 bg-gray-200 border-none outline-none text-primary-400"
@click="addPaymentMode"
>
<div slot="afterList">
<button type="button" class="list-add-button" @click="addPaymentMode">
<font-awesome-icon class="icon" icon="cart-plus" />
<label>{{ $t('settings.customization.payments.add_payment_mode') }}</label>
</button>
</div>
</base-select>
<shopping-cart-icon class="h-5 mr-3 text-primary-400" />
<label>{{
$t('settings.customization.payments.add_payment_mode')
}}</label>
</button>
</div>
</div>
<div class="col-sm-12 ">
<div class="form-group">
<label class="form-label">{{ $t('payments.note') }}</label>
<base-text-area
v-model="formData.notes"
@input="$v.formData.notes.$touch()"
/>
<div v-if="$v.formData.notes.$error">
<span v-if="!$v.formData.notes.maxLength" class="text-danger">{{ $t('validation.notes_maxlength') }}</span>
</div>
</div>
</div>
<div class="col-sm-12">
<div class="form-group collapse-button-container">
<base-button
:loading="isLoading"
icon="save"
color="theme"
type="submit"
class="collapse-button"
>
{{ $t('payments.save_payment') }}
</base-button>
</div>
</div>
</sw-select>
</sw-input-group>
</div>
<div v-if="customFields.length > 0">
<div class="grid gap-6 mt-6 grid-col-1 md:grid-cols-2">
<sw-input-group
v-for="(field, index) in customFields"
:label="field.label"
:required="field.is_required ? true : false"
:key="index"
>
<component
:type="field.type.label"
:field="field"
:isEdit="isEdit"
:is="field.type + 'Field'"
:invalid-fields="invalidFields"
@update="setCustomFieldValue"
/>
</sw-input-group>
</div>
</div>
</div>
<sw-popup
ref="notePopup"
class="my-6 text-sm font-semibold leading-5 text-primary-400"
>
<div slot="activator" class="float-right mt-1">
+ {{ $t('general.insert_note') }}
</div>
<note-select-popup type="Payment" @select="onSelectNote" />
</sw-popup>
<sw-input-group :label="$t('payments.note')" class="mt-6 mb-4">
<base-custom-input
v-model="formData.notes"
:fields="PaymentFields"
class="mb-4"
/>
</sw-input-group>
<sw-button
:disabled="isLoading"
:loading="isLoading"
variant="primary"
type="submit"
class="flex w-full mt-4 sm:hidden md:hidden"
>
<save-icon v-if="!isLoading" class="mr-2 -ml-1" />
{{
isEdit ? $t('payments.update_payment') : $t('payments.save_payment')
}}
</sw-button>
</sw-card>
</form>
</div>
</base-page>
</template>
<script>
import { mapActions, mapGetters } from 'vuex'
import MultiSelect from 'vue-multiselect'
import { validationMixin } from 'vuelidate'
import moment from 'moment'
const { required, between, maxLength, numeric } = require('vuelidate/lib/validators')
import { ShoppingCartIcon } from '@vue-hero-icons/solid'
import CustomFieldsMixin from '../../mixins/customFields'
const { required, between, numeric } = require('vuelidate/lib/validators')
export default {
components: { MultiSelect },
mixins: [validationMixin],
data () {
mixins: [CustomFieldsMixin],
components: { ShoppingCartIcon },
data() {
return {
formData: {
user_id: null,
payment_number: null,
payment_date: null,
amount: 0,
payment_date: new Date(),
amount: 100,
payment_method: null,
invoice_id: null,
notes: null,
payment_method_id: null
payment_method_id: null,
},
money: {
decimal: '.',
thousands: ',',
prefix: '$ ',
precision: 2,
masked: false
masked: false,
},
customer: null,
invoice: null,
customerList: [],
invoiceList: [],
isLoading: false,
isRequestOnGoing: false,
maxPayableAmount: Number.MAX_SAFE_INTEGER,
isSettingInitialData: true,
paymentNumAttribute: null,
paymentPrefix: ''
paymentPrefix: '',
PaymentFields: [
'customer',
'company',
'customerCustom',
'payment',
'paymentCustom',
],
}
},
validations () {
validations() {
return {
customer: {
required
required,
},
formData: {
payment_date: {
required
required,
},
amount: {
required,
between: between(1, this.maxPayableAmount + 1)
between: between(1, this.maxPayableAmount + 1),
},
notes: {
maxLength: maxLength(255)
}
},
paymentNumAttribute: {
required,
numeric
}
numeric,
},
}
},
computed: {
...mapGetters('currency', [
'defaultCurrencyForInput'
]),
...mapGetters('payment', [
'paymentModes'
]),
...mapGetters('company', ['defaultCurrencyForInput']),
...mapGetters('payment', ['paymentModes', 'selectedNote']),
...mapGetters('customer', ['customers']),
amount: {
get: function () {
return this.formData.amount / 100
},
set: function (newValue) {
this.formData.amount = newValue * 100
}
},
},
isEdit () {
pageTitle() {
if (this.$route.name === 'payments.edit') {
return this.$t('payments.edit_payment')
}
return this.$t('payments.new_payment')
},
isEdit() {
if (this.$route.name === 'payments.edit') {
return true
}
return false
},
customerCurrency () {
customerCurrency() {
if (this.customer && this.customer.currency) {
return {
decimal: this.customer.currency.decimal_separator,
thousands: this.customer.currency.thousand_separator,
prefix: this.customer.currency.symbol + ' ',
precision: this.customer.currency.precision,
masked: false
masked: false,
}
} else {
return this.defaultCurrencyForInput
}
}
},
customerError() {
if (!this.$v.customer.$error) {
return ''
}
if (!this.$v.customer.required) {
return this.$tc('validation.required')
}
},
DateError() {
if (!this.$v.formData.payment_date.$error) {
return ''
}
if (!this.$v.formData.payment_date.required) {
return this.$t('validation.required')
}
},
amountError() {
if (!this.$v.formData.amount.$error) {
return ''
}
if (!this.$v.formData.amount.required) {
return this.$t('validation.required')
}
if (
!this.$v.formData.amount.between &&
this.$v.formData.amount.numeric &&
this.amount <= 0
) {
return this.$t('validation.payment_greater_than_zero')
}
if (!this.$v.formData.amount.between && this.amount > 0) {
return this.$t('validation.payment_greater_than_due_amount')
}
},
paymentNumError() {
if (!this.$v.paymentNumAttribute.$error) {
return ''
}
if (!this.$v.paymentNumAttribute.required) {
return this.$tc('validation.required')
}
if (!this.$v.paymentNumAttribute.numeric) {
return this.$tc('validation.numbers_only')
}
},
},
watch: {
customer (newValue) {
customer(newValue) {
this.formData.user_id = newValue.id
if (!this.isEdit) {
if (this.isSettingInitialData) {
@ -270,16 +383,23 @@ export default {
this.fetchCustomerInvoices(newValue.id)
}
},
invoice (newValue) {
selectedNote() {
if (this.selectedNote) {
this.formData.notes = this.selectedNote
}
},
invoice(newValue) {
if (newValue) {
this.formData.invoice_id = newValue.id
if (!this.isEdit) {
this.setPaymentAmountByInvoiceData(newValue.id)
}
}
}
},
},
async mounted () {
async mounted() {
this.$v.formData.$reset()
this.resetSelectedNote()
this.$nextTick(() => {
this.loadData()
if (this.$route.params.id && !this.isEdit) {
@ -288,91 +408,159 @@ export default {
})
},
methods: {
...mapActions('invoice', [
'fetchInvoice'
]),
...mapActions('invoice', ['fetchInvoice', 'fetchInvoices']),
...mapActions('payment', [
'fetchCreatePayment',
'addPayment',
'updatePayment',
'fetchEditPaymentData'
'fetchPayment',
'fetchPaymentModes',
'resetSelectedNote',
]),
...mapActions('modal', [
'openModal'
]),
invoiceWithAmount ({ invoice_number, due_amount }) {
return `${invoice_number} (${this.$utils.formatGraphMoney(due_amount, this.customer.currency)})`
...mapActions('company', ['fetchCompanySettings']),
...mapActions('modal', ['openModal']),
...mapActions('customer', ['fetchCustomers']),
invoiceWithAmount({ invoice_number, due_amount }) {
return `${invoice_number} (${this.$utils.formatGraphMoney(
due_amount,
this.customer.currency
)})`
},
async addPaymentMode () {
async addPaymentMode() {
this.openModal({
'title': this.$t('settings.customization.payments.add_payment_mode'),
'componentName': 'PaymentMode'
title: this.$t('settings.customization.payments.add_payment_mode'),
componentName: 'PaymentMode',
})
},
async loadData () {
async checkAutoGenerate() {
let response = await this.fetchCompanySettings(['payment_auto_generate'])
let response1 = await axios.get('/api/v1/next-number?key=payment')
if (response.data && response.data.payment_auto_generate === 'YES') {
if (response1.data) {
this.paymentNumAttribute = response1.data.nextNumber
this.paymentPrefix = response1.data.prefix
return true
}
} else {
this.paymentPrefix = response1.data.prefix
}
},
async loadData() {
if (this.isEdit) {
let response = await this.fetchEditPaymentData(this.$route.params.id)
this.customerList = response.data.customers
this.formData = { ...response.data.payment }
this.isRequestOnGoing = true
let response = await this.fetchPayment(this.$route.params.id)
this.formData = { ...this.formData, ...response.data.payment }
this.customer = response.data.payment.user
this.formData.payment_date = moment(response.data.payment.payment_date, 'YYYY-MM-DD').toString()
this.formData.payment_date = moment(
response.data.payment.payment_date,
'YYYY-MM-DD'
).toString()
this.formData.amount = parseFloat(response.data.payment.amount)
this.paymentPrefix = response.data.payment_prefix
this.paymentNumAttribute = response.data.nextPaymentNumber
this.formData.payment_method = response.data.payment.payment_method
if (response.data.payment.invoice !== null) {
this.maxPayableAmount = parseInt(response.data.payment.amount) + parseInt(response.data.payment.invoice.due_amount)
this.maxPayableAmount =
parseInt(response.data.payment.amount) +
parseInt(response.data.payment.invoice.due_amount)
this.invoice = response.data.payment.invoice
}
// this.fetchCustomerInvoices(this.customer.id)
let res = await this.fetchCustomFields({
type: 'Payment',
limit: 'all',
})
this.setEditCustomFields(
response.data.payment.fields,
res.data.customFields.data
)
if (this.formData.payment_method_id) {
await this.fetchPaymentModes({ limit: 'all' })
}
if (this.formData.user_id) {
await this.fetchCustomers({ limit: 'all' })
}
this.isRequestOnGoing = false
} else {
let response = await this.fetchCreatePayment()
this.customerList = response.data.customers
this.paymentNumAttribute = response.data.nextPaymentNumberAttribute
this.paymentPrefix = response.data.payment_prefix
this.formData.payment_date = moment(new Date()).toString()
this.isRequestOnGoing = true
this.checkAutoGenerate()
this.setInitialCustomFields('Payment')
this.formData.payment_date = moment().toString()
this.fetchPaymentModes({ limit: 'all' })
await this.fetchCustomers({ limit: 'all' })
if (this.$route.query.customer) {
this.setPaymentCustomer(parseInt(this.$route.query.customer))
}
this.isRequestOnGoing = false
}
return true
},
async setInvoicePaymentData () {
setPaymentCustomer(id) {
this.customer = this.customers.find((c) => {
return c.id === id
})
},
async setInvoicePaymentData() {
let data = await this.fetchInvoice(this.$route.params.id)
this.customer = data.data.invoice.user
this.invoice = data.data.invoice
},
async setPaymentAmountByInvoiceData (id) {
async setPaymentAmountByInvoiceData(id) {
let data = await this.fetchInvoice(id)
this.formData.amount = data.data.invoice.due_amount
this.maxPayableAmount = data.data.invoice.due_amount
},
async fetchCustomerInvoices (userID) {
let response = await axios.get(`/api/invoices/unpaid/${userID}`)
if (response.data) {
this.invoiceList = response.data.invoices
async fetchCustomerInvoices(userId) {
let data = {
customer_id: userId,
status: 'UNPAID',
}
let response = await this.fetchInvoices(data)
this.invoiceList = response.data.invoices.data
},
async submitPaymentData () {
async submitPaymentData() {
let validate = await this.touchCustomField()
this.$v.customer.$touch()
this.$v.formData.$touch()
if (this.$v.$invalid) {
if (this.$v.$invalid || validate.error) {
return true
}
this.formData.payment_number = this.paymentPrefix + '-' + this.paymentNumAttribute
this.formData.payment_number =
this.paymentPrefix + '-' + this.paymentNumAttribute
if (this.isEdit) {
let data = {
editData: {
...this.formData,
payment_method_id: this.formData.payment_method ? this.formData.payment_method.id : null,
payment_date: moment(this.formData.payment_date).format('DD/MM/YYYY')
payment_method_id: this.formData.payment_method
? this.formData.payment_method.id
: null,
payment_date: moment(this.formData.payment_date).format(
'YYYY-MM-DD'
),
},
id: this.$route.params.id
id: this.$route.params.id,
}
try {
this.isLoading = true
let response = await this.updatePayment(data)
if (response.data.success) {
this.isLoading = false
this.$router.push(
`/admin/payments/${response.data.payment.id}/view`
)
window.toastr['success'](this.$t('payments.updated_message'))
this.$router.push('/admin/payments')
return true
}
if (response.data.error === 'invalid_amount') {
@ -391,15 +579,19 @@ export default {
} else {
let data = {
...this.formData,
payment_method_id: this.formData.payment_method ? this.formData.payment_method.id : null,
payment_date: moment(this.formData.payment_date).format('DD/MM/YYYY')
payment_method_id: this.formData.payment_method
? this.formData.payment_method.id
: null,
payment_date: moment(this.formData.payment_date).format('YYYY-MM-DD'),
}
this.isLoading = true
try {
let response = await this.addPayment(data)
if (response.data.success) {
this.$router.push(
`/admin/payments/${response.data.payment.id}/view`
)
window.toastr['success'](this.$t('payments.created_message'))
this.$router.push('/admin/payments')
this.isLoading = true
return true
}
@ -417,7 +609,11 @@ export default {
window.toastr['error'](err.response.data.message)
}
}
}
}
},
onSelectNote(data) {
this.formData.notes = '' + data.notes
this.$refs.notePopup.close()
},
},
}
</script>

View File

@ -1,306 +1,365 @@
<template>
<div class="payments main-content">
<div class="page-header">
<h3 class="page-title">{{ $t('payments.title') }}</h3>
<ol class="breadcrumb">
<li class="breadcrumb-item">
<router-link
slot="item-title"
to="dashboard">
{{ $t('general.home') }}
</router-link>
</li>
<li class="breadcrumb-item">
<router-link
slot="item-title"
to="#">
{{ $tc('payments.payment',2) }}
</router-link>
</li>
</ol>
<div class="page-actions row">
<div class="col-xs-2 mr-4">
<base-button
v-show="totalPayments || filtersApplied"
:outline="true"
:icon="filterIcon"
color="theme"
right-icon
size="large"
@click="toggleFilter"
>
{{ $t('general.filter') }}
</base-button>
</div>
<router-link slot="item-title" class="col-xs-2" to="payments/create">
<base-button
color="theme"
icon="plus"
size="large"
>
{{ $t('payments.add_payment') }}
</base-button>
</router-link>
</div>
</div>
<base-page class="payments">
<sw-page-header :title="$t('payments.title')">
<sw-breadcrumb slot="breadcrumbs">
<sw-breadcrumb-item to="dashboard" :title="$t('general.home')" />
<sw-breadcrumb-item to="#" :title="$tc('payments.payment', 2)" active />
</sw-breadcrumb>
<transition name="fade" mode="out-in">
<div v-show="showFilters" class="filter-section">
<div class="row">
<div class="col-md-4">
<label class="form-label">{{ $t('payments.customer') }}</label>
<base-customer-select
ref="customerSelect"
@select="onSelectCustomer"
@deselect="clearCustomerSearch"
/>
</div>
<div class="col-sm-4">
<label for="">{{ $t('payments.payment_number') }}</label>
<base-input
v-model="filters.payment_number"
:placeholder="$t(payments.payment_number)"
name="payment_number"
/>
</div>
<div class="col-sm-4">
<label class="form-label">{{ $t('payments.payment_mode') }}</label>
<base-select
v-model="filters.payment_mode"
:options="paymentModes"
:searchable="true"
:show-labels="false"
:placeholder="$t('payments.payment_mode')"
label="name"
/>
</div>
</div>
<label class="clear-filter" @click="clearFilter">{{ $t('general.clear_all') }}</label>
</div>
</transition>
<div v-cloak v-show="showEmptyScreen" class="col-xs-1 no-data-info" align="center">
<capsule-icon class="mt-5 mb-4"/>
<div class="row" align="center">
<label class="col title">{{ $t('payments.no_payments') }}</label>
</div>
<div class="row">
<label class="description col mt-1" align="center">{{ $t('payments.list_of_payments') }}</label>
</div>
<div class="btn-container">
<base-button
:outline="true"
color="theme"
class="mt-3"
size="large"
@click="$router.push('payments/create')"
<template slot="actions">
<sw-button
v-show="totalPayments"
variant="primary-outline"
size="lg"
@click="toggleFilter"
>
{{ $t('payments.add_new_payment') }}
</base-button>
</div>
</div>
{{ $t('general.filter') }}
<component :is="filterIcon" class="w-4 h-4 ml-2 -mr-1" />
</sw-button>
<div v-show="!showEmptyScreen" class="table-container">
<div class="table-actions mt-5">
<p class="table-stats">{{ $t('general.showing') }}: <b>{{ payments.length }}</b> {{ $t('general.of') }} <b>{{ totalPayments }}</b></p>
<sw-button
tag-name="router-link"
to="payments/create"
variant="primary"
size="lg"
class="ml-4"
>
<plus-icon class="w-6 h-6 mr-1 -ml-2" />
{{ $t('payments.add_payment') }}
</sw-button>
</template>
</sw-page-header>
<transition name="fade">
<v-dropdown v-if="selectedPayments.length" :show-arrow="false">
<span slot="activator" href="#" class="table-actions-button dropdown-toggle">
<slide-y-up-transition>
<sw-filter-wrapper v-show="showFilters" class="mt-3">
<sw-input-group
:label="$t('payments.customer')"
color="black-light"
class="flex-1 mt-2"
>
<base-customer-select
ref="customerSelect"
@select="onSelectCustomer"
@deselect="clearCustomerSearch"
/>
</sw-input-group>
<sw-input-group
:label="$t('payments.payment_number')"
class="flex-1 mt-2 lg:ml-6"
>
<sw-input
v-model="filters.payment_number"
:placeholder="$t(payments.payment_number)"
name="payment_number"
/>
</sw-input-group>
<sw-input-group
:label="$t('payments.payment_mode')"
class="flex-1 mt-2 lg:ml-6"
>
<sw-select
v-model="filters.payment_mode"
:options="paymentModes"
:searchable="true"
:show-labels="false"
:placeholder="$t('payments.payment_mode')"
label="name"
/>
</sw-input-group>
<label
class="absolute text-sm leading-snug text-gray-900 cursor-pointer"
style="top: 10px; right: 15px"
@click="clearFilter"
>{{ $t('general.clear_all') }}</label
>
</sw-filter-wrapper>
</slide-y-up-transition>
<sw-empty-table-placeholder
v-if="showEmptyScreen"
:title="$t('payments.no_payments')"
:description="$t('payments.list_of_payments')"
>
<capsule-icon class="mt-5 mb-4" />
<sw-button
slot="actions"
tag-name="router-link"
to="/admin/payments/create"
size="lg"
variant="primary-outline"
>
<plus-icon class="w-6 h-6 mr-1 -ml-2" />
{{ $t('payments.add_new_payment') }}
</sw-button>
</sw-empty-table-placeholder>
<div v-show="!showEmptyScreen" class="relative table-container">
<div
class="relative flex items-center justify-between h-10 mt-5 list-none border-b-2 border-gray-200 border-solid"
>
<p class="text-sm">
{{ $t('general.showing') }}: <b>{{ payments.length }}</b>
{{ $t('general.of') }} <b>{{ totalPayments }}</b>
</p>
<sw-transition type="fade">
<sw-dropdown v-if="selectedPayments.length">
<span
slot="activator"
class="flex block text-sm font-medium cursor-pointer select-none text-primary-400"
>
{{ $t('general.actions') }}
<chevron-down-icon class="h-5" />
</span>
<v-dropdown-item>
<div class="dropdown-item" @click="removeMultiplePayments">
<font-awesome-icon :icon="['fas', 'trash']" class="dropdown-item-icon" />
{{ $t('general.delete') }}
</div>
</v-dropdown-item>
</v-dropdown>
</transition>
<sw-dropdown-item @click="removeMultiplePayments">
<trash-icon class="h-5 mr-3 text-gray-600" />
{{ $t('general.delete') }}
</sw-dropdown-item>
</sw-dropdown>
</sw-transition>
</div>
<div class="custom-control custom-checkbox">
<input
id="select-all"
<div class="absolute z-10 items-center pl-4 mt-2 select-none md:mt-12">
<sw-checkbox
v-model="selectAllFieldStatus"
type="checkbox"
class="custom-control-input"
variant="primary"
size="sm"
class="hidden md:inline"
@change="selectAllPayments"
>
<label v-show="!isRequestOngoing" for="select-all" class="custom-control-label selectall">
<span class="select-all-label">{{ $t('general.select_all') }} </span>
</label>
/>
<sw-checkbox
v-model="selectAllFieldStatus"
:label="$t('general.select_all')"
variant="primary"
size="sm"
class="md:hidden"
@change="selectAllPayments"
/>
</div>
<table-component
<sw-table-component
ref="table"
:data="fetchData"
:show-filter="false"
table-class="table"
>
<table-column
<sw-table-column
:sortable="false"
:filterable="false"
cell-class="no-click"
>
<template slot-scope="row">
<div class="custom-control custom-checkbox">
<input
:id="row.id"
v-model="selectField"
:value="row.id"
type="checkbox"
class="custom-control-input"
>
<label :for="row.id" class="custom-control-label" />
</div>
</template>
</table-column>
<table-column
<div slot-scope="row" class="relative block">
<sw-checkbox
:id="row.id"
v-model="selectField"
:value="row.id"
variant="primary"
size="sm"
/>
</div>
</sw-table-column>
<sw-table-column
:sortable="true"
:label="$t('payments.date')"
sort-as="payment_date"
show="formattedPaymentDate"
/>
<table-column
<sw-table-column
:sortable="true"
:label="$t('payments.payment_number')"
show="payment_number"
>
<template slot-scope="row">
<span>{{ $t('payments.payment_number') }}</span>
<router-link
:to="{ path: `payments/${row.id}/view` }"
class="font-medium text-primary-500"
>
{{ row.payment_number }}
</router-link>
</template>
</sw-table-column>
<sw-table-column
:sortable="true"
:label="$t('payments.customer')"
show="name"
/>
<table-column
<sw-table-column
:sortable="true"
:label="$t('payments.payment_mode')"
show="payment_mode"
/>
<table-column
:label="$t('payments.payment_number')"
show="payment_number"
/>
<table-column
>
<template slot-scope="row">
<span>{{ $t('payments.payment_mode') }}</span>
<span>
{{ row.payment_mode ? row.payment_mode : 'Not selected' }}
</span>
</template>
</sw-table-column>
<sw-table-column
:sortable="true"
:label="$t('payments.invoice')"
sort-as="invoice_id"
show="invoice.invoice_number"
/>
<table-column
:label="$t('payments.amount')"
show="invoice_number"
>
<template slot-scope="row">
<span>{{ $t('invoices.invoice_number') }}</span>
<span>
{{ row.invoice_number ? row.invoice_number : 'No Invoice' }}
</span>
</template>
</sw-table-column>
<sw-table-column :sortable="true" :label="$t('payments.amount')">
<template slot-scope="row">
<span>{{ $t('payments.amount') }}</span>
<div v-html="$utils.formatMoney(row.amount, row.user.currency)" />
</template>
</table-column>
<table-column
</sw-table-column>
<sw-table-column
:sortable="false"
:filterable="false"
cell-class="action-dropdown no-click"
cell-class="action-dropdown"
>
<template slot-scope="row">
<span>{{ $t('payments.action') }}</span>
<v-dropdown>
<a slot="activator" href="#">
<dot-icon />
</a>
<v-dropdown-item>
<sw-dropdown>
<dot-icon slot="activator" />
<router-link :to="{path: `payments/${row.id}/edit`}" class="dropdown-item">
<font-awesome-icon :icon="['fas', 'pencil-alt']" class="dropdown-item-icon" />
{{ $t('general.edit') }}
</router-link>
<sw-dropdown-item
tag-name="router-link"
:to="`payments/${row.id}/edit`"
>
<pencil-icon class="h-5 mr-3 text-gray-600" />
{{ $t('general.edit') }}
</sw-dropdown-item>
</v-dropdown-item>
<v-dropdown-item>
<sw-dropdown-item
tag-name="router-link"
:to="`payments/${row.id}/view`"
>
<eye-icon class="h-5 mr-3 text-gray-600" />
{{ $t('general.view') }}
</sw-dropdown-item>
<router-link :to="{path: `payments/${row.id}/view`}" class="dropdown-item">
<font-awesome-icon icon="eye" class="dropdown-item-icon" />
{{ $t('general.view') }}
</router-link>
</v-dropdown-item>
<v-dropdown-item>
<div class="dropdown-item" @click="removePayment(row.id)">
<font-awesome-icon :icon="['fas', 'trash']" class="dropdown-item-icon" />
{{ $t('general.delete') }}
</div>
</v-dropdown-item>
</v-dropdown>
<sw-dropdown-item @click="removePayment(row.id)">
<trash-icon class="h-5 mr-3 text-gray-600" />
{{ $t('general.delete') }}
</sw-dropdown-item>
</sw-dropdown>
</template>
</table-column>
</table-component>
</sw-table-column>
</sw-table-component>
</div>
</div>
</base-page>
</template>
<script>
import { mapActions, mapGetters } from 'vuex'
import { SweetModal, SweetModalTab } from 'sweet-modal-vue'
import CapsuleIcon from '../../components/icon/CapsuleIcon'
import BaseButton from '../../../js/components/base/BaseButton'
import CapsuleIcon from '@/components/icon/CapsuleIcon'
import {
PlusIcon,
FilterIcon,
XIcon,
ChevronDownIcon,
EyeIcon,
PencilIcon,
TrashIcon,
} from '@vue-hero-icons/solid'
export default {
components: {
'capsule-icon': CapsuleIcon,
'SweetModal': SweetModal,
'SweetModalTab': SweetModalTab,
BaseButton
CapsuleIcon,
PlusIcon,
FilterIcon,
XIcon,
ChevronDownIcon,
EyeIcon,
PencilIcon,
TrashIcon,
},
data () {
data() {
return {
showFilters: false,
sortedBy: 'created_at',
filtersApplied: false,
isRequestOngoing: true,
filters: {
customer: null,
customer: '',
payment_mode: '',
payment_number: ''
}
payment_number: '',
},
}
},
computed: {
showEmptyScreen () {
return !this.totalPayments && !this.isRequestOngoing && !this.filtersApplied
showEmptyScreen() {
return !this.totalPayments && !this.isRequestOngoing
},
filterIcon () {
return (this.showFilters) ? 'times' : 'filter'
filterIcon() {
return this.showFilters ? 'x-icon' : 'filter-icon'
},
...mapGetters('customer', [
'customers'
]),
...mapGetters('customer', ['customers']),
...mapGetters('payment', [
'selectedPayments',
'totalPayments',
'payments',
'selectAllField',
'paymentModes'
'paymentModes',
]),
selectField: {
get: function () {
return this.selectedPayments
},
set: function (val) {
this.selectPayment(val)
}
},
},
selectAllFieldStatus: {
get: function () {
return this.selectAllField
},
set: function (val) {
this.setSelectAllState(val)
}
}
},
},
},
watch: {
filters: {
handler: 'setFilters',
deep: true
}
deep: true,
},
},
mounted () {
this.fetchCustomers()
mounted() {
this.fetchPaymentModes({ limit: 'all' })
},
destroyed () {
destroyed() {
if (this.selectAllField) {
this.selectAllPayments()
}
},
methods: {
...mapActions('payment', [
'fetchPayments',
@ -308,25 +367,25 @@ export default {
'selectPayment',
'deletePayment',
'deleteMultiplePayments',
'setSelectAllState'
'setSelectAllState',
'fetchPaymentModes',
]),
...mapActions('customer', [
'fetchCustomers'
]),
async fetchData ({ page, filter, sort }) {
async fetchData({ page, filter, sort }) {
let data = {
customer_id: this.filters.customer !== null ? this.filters.customer.id : '',
customer_id: this.filters.customer ? this.filters.customer.id : '',
payment_method_id:
this.filters.payment_mode !== null
? this.filters.payment_mode.id
: '',
payment_number: this.filters.payment_number,
payment_method_id: this.filters.payment_mode ? this.filters.payment_mode.id : '',
orderByField: sort.fieldName || 'created_at',
orderBy: sort.order || 'desc',
page
page,
}
this.isRequestOngoing = true
let response = await this.fetchPayments(data)
this.isRequestOngoing = false
return {
@ -334,71 +393,75 @@ export default {
pagination: {
totalPages: response.data.payments.last_page,
currentPage: page,
count: response.data.payments.scount
}
count: response.data.payments.count,
},
}
},
refreshTable () {
refreshTable() {
this.$refs.table.refresh()
},
setFilters () {
this.filtersApplied = true
setFilters() {
this.refreshTable()
},
clearFilter () {
clearFilter() {
if (this.filters.customer) {
this.$refs.customerSelect.$refs.baseSelect.removeElement(this.filters.customer)
this.$refs.customerSelect.$refs.baseSelect.removeElement(
this.filters.customer
)
}
this.filters = {
customer: null,
customer: '',
payment_mode: '',
payment_number: ''
payment_number: '',
}
this.$nextTick(() => {
this.filtersApplied = false
})
},
toggleFilter () {
if (this.showFilters && this.filtersApplied) {
toggleFilter() {
if (this.showFilters) {
this.clearFilter()
this.refreshTable()
}
this.showFilters = !this.showFilters
},
onSelectCustomer (customer) {
onSelectCustomer(customer) {
this.filters.customer = customer
},
async removePayment (id) {
this.id = id
async removePayment(id) {
swal({
title: this.$t('general.are_you_sure'),
text: this.$tc('payments.confirm_delete'),
icon: '/assets/icon/trash-solid.svg',
buttons: true,
dangerMode: true
dangerMode: true,
}).then(async (willDelete) => {
if (willDelete) {
let res = await this.deletePayment(this.id)
let res = await this.deletePayment({ ids: [id] })
if (res.data.success) {
window.toastr['success'](this.$tc('payments.deleted_message', 1))
this.$refs.table.refresh()
return true
} else if (res.data.error) {
window.toastr['error'](res.data.message)
}
window.toastr['error'](res.data.message)
return true
}
})
},
async removeMultiplePayments () {
async removeMultiplePayments() {
swal({
title: this.$t('general.are_you_sure'),
text: this.$tc('payments.confirm_delete', 2),
icon: '/assets/icon/trash-solid.svg',
buttons: true,
dangerMode: true
dangerMode: true,
}).then(async (willDelete) => {
if (willDelete) {
let request = await this.deleteMultiplePayments()
@ -411,21 +474,24 @@ export default {
}
})
},
async clearCustomerSearch (removedOption, id) {
async clearCustomerSearch(removedOption, id) {
this.filters.customer = ''
this.$refs.table.refresh()
this.refreshTable()
},
showModel (selectedRow) {
showModel(selectedRow) {
this.selectedRow = selectedRow
this.$refs.Delete_modal.open()
},
async removeSelectedItems () {
async removeSelectedItems() {
this.$refs.Delete_modal.close()
await this.selectedRow.forEach(row => {
await this.selectedRow.forEach((row) => {
this.deletePayment(this.id)
})
this.$refs.table.refresh()
}
}
},
},
}
</script>

View File

@ -1,176 +1,225 @@
<template>
<div v-if="payment" class="main-content payment-view-page">
<div class="page-header">
<h3 class="page-title">{{ payment.payment_number }}</h3>
<div class="page-actions row">
<base-button
:loading="isSendingEmail"
<base-page v-if="payment" class="xl:pl-96">
<sw-page-header :title="pageTitle">
<template slot="actions">
<sw-button
:disabled="isSendingEmail"
color="theme"
variant="primary"
@click="onPaymentSend"
>
{{ $t('payments.send_payment_receipt') }}
</base-button>
<v-dropdown
:close-on-select="true"
align="left"
class="filter-container"
>
<a slot="activator" href="#">
<base-button color="theme">
<font-awesome-icon icon="ellipsis-h" />
</base-button>
</a>
<v-dropdown-item>
<div class="dropdown-item" @click="copyPdfUrl">
<font-awesome-icon
:icon="['fas', 'link']"
class="dropdown-item-icon"
/>
{{ $t('general.copy_pdf_url') }}
</div>
<router-link
:to="{ path: `/admin/payments/${$route.params.id}/edit` }"
class="dropdown-item"
>
<font-awesome-icon
:icon="['fas', 'pencil-alt']"
class="dropdown-item-icon"
/>
{{ $t('general.edit') }}
</router-link>
<div class="dropdown-item" @click="removePayment($route.params.id)">
<font-awesome-icon
:icon="['fas', 'trash']"
class="dropdown-item-icon"
/>
{{ $t('general.delete') }}
</div>
</v-dropdown-item>
</v-dropdown>
</div>
</div>
<div class="payment-sidebar">
<div class="side-header">
<base-input
</sw-button>
<sw-dropdown class="ml-3">
<sw-button slot="activator" variant="primary" class="h-10">
<dots-horizontal-icon class="h-5" />
</sw-button>
<sw-dropdown-item @click="copyPdfUrl">
<link-icon class="h-5 mr-3 text-gray-600" />
{{ $t('general.copy_pdf_url') }}
</sw-dropdown-item>
<sw-dropdown-item
tag-name="router-link"
:to="`/admin/payments/${$route.params.id}/edit`"
>
<pencil-icon class="h-5 mr-3 text-gray-600" />
{{ $t('general.edit') }}
</sw-dropdown-item>
<sw-dropdown-item @click="removePayment($route.params.id)">
<trash-icon class="h-5 mr-3 text-gray-600" />
{{ $t('general.delete') }}
</sw-dropdown-item>
</sw-dropdown>
</template>
</sw-page-header>
<!-- sidebar -->
<div
class="fixed top-0 left-0 hidden h-full pt-16 pb-4 ml-56 bg-white xl:ml-64 w-88 xl:block"
>
<div
class="flex items-center justify-between px-4 pt-8 pb-2 border border-gray-200 border-solid height-full"
>
<sw-input
v-model="searchData.searchText"
:placeholder="$t('general.search')"
input-class="inv-search"
icon="search"
type="text"
align-icon="right"
class="mb-6"
variant="gray"
@input="onSearch"
/>
<div class="btn-group ml-3" role="group" aria-label="First group">
<v-dropdown
:close-on-select="false"
align="left"
class="filter-container"
>
<a slot="activator" href="#">
<base-button
class="inv-button inv-filter-fields-btn"
color="default"
size="medium"
>
<font-awesome-icon icon="filter" />
</base-button>
</a>
<div class="filter-title">
>
<search-icon slot="rightIcon" class="h-5" />
</sw-input>
<div class="flex mb-6 ml-3" role="group" aria-label="First group">
<sw-dropdown position="bottom-start">
<sw-button slot="activator" size="md" variant="gray-light">
<filter-icon class="h-5" />
</sw-button>
<div
class="px-2 pb-2 mb-1 text-sm border-b border-gray-200 border-solid"
>
{{ $t('general.sort_by') }}
</div>
<div class="filter-items">
<input
id="filter_invoice_number"
v-model="searchData.orderByField"
type="radio"
name="filter"
class="inv-radio"
value="invoice_number"
@change="onSearch"
/>
<label class="inv-label" for="filter_invoice_number">{{
$t('invoices.title')
}}</label>
</div>
<div class="filter-items">
<input
id="filter_payment_date"
v-model="searchData.orderByField"
type="radio"
name="filter"
class="inv-radio"
value="payment_date"
@change="onSearch"
/>
<label class="inv-label" for="filter_payment_date">{{
$t('payments.date')
}}</label>
</div>
<div class="filter-items">
<input
id="filter_payment_number"
v-model="searchData.orderByField"
type="radio"
name="filter"
class="inv-radio"
value="payment_number"
@change="onSearch"
/>
<label class="inv-label" for="filter_payment_number">{{
$t('payments.payment_number')
}}</label>
</div>
</v-dropdown>
<base-button
<sw-dropdown-item class="flex cursor-pointer">
<sw-input-group class="-mt-3 font-normal">
<sw-radio
:label="$t('invoices.title')"
size="sm"
id="filter_invoice_number"
v-model="searchData.orderByField"
name="filter"
value="invoice_number"
@change="onSearch"
/>
</sw-input-group>
</sw-dropdown-item>
<sw-dropdown-item class="flex cursor-pointer">
<sw-input-group class="-mt-3 font-normal">
<sw-radio
:label="$t('payments.date')"
size="sm"
id="filter_payment_date"
v-model="searchData.orderByField"
name="filter"
value="payment_date"
@change="onSearch"
/>
</sw-input-group>
</sw-dropdown-item>
<sw-dropdown-item class="flex cursor-pointer">
<sw-input-group class="-mt-3 font-normal">
<sw-radio
id="filter_payment_number"
:label="$t('payments.payment_number')"
v-model="searchData.orderByField"
size="sm"
name="filter"
value="payment_number"
@change="onSearch"
/>
</sw-input-group>
</sw-dropdown-item>
</sw-dropdown>
<sw-button
class="ml-1"
v-tooltip.top-center="{ content: getOrderName }"
class="inv-button inv-filter-sorting-btn"
color="default"
size="medium"
size="md"
variant="gray-light"
@click="sortData"
>
<font-awesome-icon v-if="getOrderBy" icon="sort-amount-up" />
<font-awesome-icon v-else icon="sort-amount-down" />
</base-button>
<sort-ascending-icon v-if="getOrderBy" class="h-5" />
<sort-descending-icon v-else class="h-5" />
</sw-button>
</div>
</div>
<base-loader v-if="isSearching" />
<div v-else class="side-content">
<base-loader v-if="isSearching" :show-bg-overlay="true" />
<div
v-else
class="h-full pb-32 overflow-y-scroll border-l border-gray-200 border-solid sw-scroll"
>
<router-link
v-for="(payment, index) in payments"
:to="`/admin/payments/${payment.id}/view`"
:id="'payment-' + payment.id"
:key="index"
class="side-payment"
:class="[
'flex justify-between p-4 items-center cursor-pointer hover:bg-gray-100 border-l-4 border-transparent',
{
'bg-gray-100 border-l-4 border-primary-500 border-solid': hasActiveUrl(
payment.id
),
},
]"
style="border-bottom: 1px solid rgba(185, 193, 209, 0.41)"
>
<div class="left">
<div class="inv-name">{{ payment.user.name }}</div>
<div class="inv-number">{{ payment.payment_number }}</div>
<div class="inv-number">{{ payment.invoice_number }}</div>
</div>
<div class="right">
<div class="flex-2">
<div
class="inv-amount"
class="pr-2 mb-2 text-sm not-italic font-normal leading-5 text-black capitalize truncate"
>
{{ payment.user.name }}
</div>
<div
class="mb-1 text-xs not-italic font-medium leading-5 text-gray-500 capitalize"
>
{{ payment.payment_number }}
</div>
<div
class="mb-1 text-xs not-italic font-medium leading-5 text-gray-500 capitalize"
>
{{ payment.invoice_number }}
</div>
</div>
<div class="flex-1 whitespace-no-wrap right">
<div
class="mb-2 text-xl not-italic font-semibold leading-8 text-right text-gray-900"
v-html="$utils.formatMoney(payment.amount, payment.user.currency)"
/>
<div class="inv-date">{{ payment.formattedPaymentDate }}</div>
<!-- <div class="inv-number">{{ payment.payment_method.name }}</div> -->
<div class="text-sm text-right text-gray-500 non-italic">
{{ payment.formattedPaymentDate }}
</div>
</div>
</router-link>
<p v-if="!payments.length" class="no-result">
<p
v-if="!payments.length"
class="flex justify-center px-4 mt-5 text-sm text-gray-600"
>
{{ $t('payments.no_matching_payments') }}
</p>
</div>
</div>
<div class="payment-view-page-container">
<iframe :src="`${shareableLink}`" class="frame-style" />
<!-- pdf -->
<div
class="flex flex-col min-h-0 mt-8 overflow-hidden"
style="height: 75vh"
>
<iframe
:src="`${shareableLink}`"
class="flex-1 border border-gray-400 border-solid rounded-md"
/>
</div>
</div>
</base-page>
</template>
<script>
import {
DotsHorizontalIcon,
FilterIcon,
SortAscendingIcon,
SortDescendingIcon,
SearchIcon,
LinkIcon,
TrashIcon,
PencilIcon,
} from '@vue-hero-icons/solid'
import { mapActions, mapGetters } from 'vuex'
const _ = require('lodash')
export default {
data () {
components: {
DotsHorizontalIcon,
FilterIcon,
SortAscendingIcon,
SortDescendingIcon,
SearchIcon,
TrashIcon,
PencilIcon,
LinkIcon,
},
data() {
return {
id: null,
count: null,
@ -180,82 +229,109 @@ export default {
searchData: {
orderBy: null,
orderByField: null,
searchText: null
searchText: null,
},
isRequestOnGoing: false,
isSearching: false,
isSendingEmail: false,
isMarkingAsSent: false
isMarkingAsSent: false,
}
},
computed: {
getOrderBy () {
if (this.searchData.orderBy === 'asc' || this.searchData.orderBy == null) {
pageTitle() {
return this.payment.payment_number
},
getOrderBy() {
if (
this.searchData.orderBy === 'asc' ||
this.searchData.orderBy == null
) {
return true
}
return false
},
getOrderName () {
getOrderName() {
if (this.getOrderBy) {
return this.$t('general.ascending')
}
return this.$t('general.descending')
},
shareableLink () {
shareableLink() {
return `/payments/pdf/${this.payment.unique_hash}`
}
},
},
watch: {
$route (to, from) {
$route(to, from) {
this.loadPayment()
}
},
},
created () {
created() {
this.loadPayments()
this.loadPayment()
this.onSearch = _.debounce(this.onSearch, 500)
},
methods: {
// ...mapActions('invoice', [
// 'fetchInvoices',
// 'getRecord',
// 'searchInvoice',
// 'markAsSent',
// 'sendEmail',
// 'deleteInvoice',
// 'fetchViewInvoice'
// ]),
...mapActions('payment', [
'fetchPayments',
'fetchPayment',
'sendEmail',
'deletePayment',
'searchPayment'
'searchPayment',
]),
async loadPayments () {
let response = await this.fetchPayments()
...mapActions('modal', ['openModal']),
hasActiveUrl(id) {
return this.$route.params.id == id
},
async loadPayments() {
let response = await this.fetchPayments({ limit: 'all' })
if (response.data) {
this.payments = response.data.payments.data
}
setTimeout(() => {
this.scrollToPayment()
}, 500)
},
async loadPayment () {
scrollToPayment() {
const el = document.getElementById(`payment-${this.$route.params.id}`)
if (el) {
el.scrollIntoView({ behavior: 'smooth' })
el.classList.add('shake')
}
},
async loadPayment() {
let response = await this.fetchPayment(this.$route.params.id)
if (response.data) {
this.payment = response.data.payment
}
},
async onSearch () {
async onSearch() {
let data = ''
if (this.searchData.searchText !== '' && this.searchData.searchText !== null && this.searchData.searchText !== undefined) {
if (
this.searchData.searchText !== '' &&
this.searchData.searchText !== null &&
this.searchData.searchText !== undefined
) {
data += `search=${this.searchData.searchText}&`
}
if (this.searchData.orderBy !== null && this.searchData.orderBy !== undefined) {
if (
this.searchData.orderBy !== null &&
this.searchData.orderBy !== undefined
) {
data += `orderBy=${this.searchData.orderBy}&`
}
if (this.searchData.orderByField !== null && this.searchData.orderByField !== undefined) {
if (
this.searchData.orderByField !== null &&
this.searchData.orderByField !== undefined
) {
data += `orderByField=${this.searchData.orderByField}`
}
this.isSearching = true
@ -265,7 +341,7 @@ export default {
this.payments = response.data.payments.data
}
},
sortData () {
sortData() {
if (this.searchData.orderBy === 'asc') {
this.searchData.orderBy = 'desc'
this.onSearch()
@ -275,57 +351,44 @@ export default {
this.onSearch()
return true
},
async onPaymentSend () {
window.swal({
title: this.$tc('general.are_you_sure'),
text: this.$tc('payments.confirm_send_payment'),
icon: '/assets/icon/paper-plane-solid.svg',
buttons: true,
dangerMode: true
}).then(async (value) => {
if (value) {
this.isSendingEmail = true
let response = await this.sendEmail({id: this.payment.id})
this.isSendingEmail = false
if (response.data.success) {
window.toastr['success'](this.$tc('payments.send_payment_successfully'))
return true
}
if (response.data.error === 'user_email_does_not_exist') {
window.toastr['error'](this.$tc('payments.user_email_does_not_exist'))
return false
}
window.toastr['error'](this.$tc('payments.something_went_wrong'))
}
async onPaymentSend() {
this.openModal({
title: this.$t('payments.send_payment'),
componentName: 'SendPaymentModal',
id: this.payment.id,
data: this.payment,
variant: 'lg',
})
},
copyPdfUrl () {
copyPdfUrl() {
let pdfUrl = `${window.location.origin}/payments/pdf/${this.payment.unique_hash}`
let response = this.$utils.copyTextToClipboard(pdfUrl)
window.toastr['success'](this.$tc('Copied PDF url to clipboard!'))
window.toastr['success'](this.$t('general.copied_pdf_url_clipboard'))
},
async removePayment (id) {
async removePayment(id) {
this.id = id
window.swal({
title: 'Deleted',
text: 'you will not be able to recover this payment!',
icon: '/assets/icon/trash-solid.svg',
buttons: true,
dangerMode: true
}).then(async (value) => {
if (value) {
let request = await this.deletePayment(this.id)
if (request.data.success) {
window.toastr['success'](this.$tc('payments.deleted_message', 1))
this.$router.push('/admin/payments')
} else if (request.data.error) {
window.toastr['error'](request.data.message)
window
.swal({
title: this.$t('general.are_you_sure'),
text: 'you will not be able to recover this payment!',
icon: '/assets/icon/trash-solid.svg',
buttons: true,
dangerMode: true,
})
.then(async (value) => {
if (value) {
let request = await this.deletePayment({ ids: [id] })
if (request.data.success) {
window.toastr['success'](this.$tc('payments.deleted_message', 1))
this.$router.push('/admin/payments')
} else if (request.data.error) {
window.toastr['error'](request.data.message)
}
}
}
})
}
}
})
},
},
}
</script>