forked from verdnatura/salix-front
231 lines
7.0 KiB
Vue
231 lines
7.0 KiB
Vue
<script setup>
|
|
import { ref, watch, computed, onMounted } from 'vue';
|
|
import { useRoute, useRouter } from 'vue-router';
|
|
import { useI18n } from 'vue-i18n';
|
|
|
|
import CrudModel from 'components/CrudModel.vue';
|
|
import VnSelectDialog from 'src/components/common/VnSelectDialog.vue';
|
|
import FetchData from 'components/FetchData.vue';
|
|
import TicketCreateServiceType from './TicketCreateServiceType.vue';
|
|
import VnInput from 'src/components/common/VnInput.vue';
|
|
|
|
import { useArrayData } from 'src/composables/useArrayData';
|
|
import useNotify from 'src/composables/useNotify.js';
|
|
import axios from 'axios';
|
|
|
|
const route = useRoute();
|
|
const router = useRouter();
|
|
const { t } = useI18n();
|
|
const ticketServiceTypeFetchRef = ref(null);
|
|
const ticketServiceCrudRef = ref(null);
|
|
const ticketServiceOptions = ref([]);
|
|
const arrayData = useArrayData('TicketNotes');
|
|
const { store } = arrayData;
|
|
const { notify } = useNotify();
|
|
|
|
const selected = ref([]);
|
|
const defaultTaxClass = ref(null);
|
|
const isSaving = ref(false);
|
|
const crudModelFilter = computed(() => ({
|
|
where: { ticketFk: route.params.id },
|
|
}));
|
|
|
|
const crudModelRequiredData = computed(() => ({
|
|
ticketFk: route.params.id,
|
|
taxClassFk: defaultTaxClass.value?.id,
|
|
}));
|
|
|
|
watch(
|
|
() => route.params.id,
|
|
async () => {
|
|
store.filter = crudModelFilter.value;
|
|
await ticketServiceCrudRef.value.reload();
|
|
}
|
|
);
|
|
|
|
onMounted(async () => await getDefaultTaxClass());
|
|
|
|
const createRefund = async () => {
|
|
if (!selected.value.length) return;
|
|
|
|
const params = {
|
|
servicesIds: selected.value.map((s) => +s.id),
|
|
withWarehouse: false,
|
|
negative: true,
|
|
};
|
|
const { data } = await axios.post('Sales/clone', params);
|
|
const [refundTicket] = data;
|
|
notify(
|
|
t('service.createRefundSuccess', {
|
|
ticketId: refundTicket.id,
|
|
}),
|
|
'positive'
|
|
);
|
|
router.push({ name: 'TicketSale', params: { id: refundTicket.id } });
|
|
};
|
|
|
|
const getDefaultTaxClass = async () => {
|
|
let filter = {
|
|
where: { code: 'G' },
|
|
};
|
|
const { data } = await axios.get('TaxClasses/findOne', {
|
|
params: { filter: JSON.stringify(filter) },
|
|
});
|
|
defaultTaxClass.value = data;
|
|
};
|
|
|
|
const columns = computed(() => [
|
|
{
|
|
name: 'description',
|
|
label: t('service.description'),
|
|
field: (row) => row.ticketServiceTypeFk,
|
|
sortable: true,
|
|
align: 'left',
|
|
},
|
|
{
|
|
name: 'quantity',
|
|
label: t('service.quantity'),
|
|
field: (row) => row.quantity,
|
|
sortable: true,
|
|
align: 'left',
|
|
},
|
|
{
|
|
name: 'price',
|
|
label: t('service.price'),
|
|
field: (row) => row.price,
|
|
sortable: true,
|
|
align: 'left',
|
|
},
|
|
{
|
|
label: '',
|
|
name: 'actions',
|
|
align: 'left',
|
|
columnFilter: null,
|
|
},
|
|
]);
|
|
|
|
async function deleteService(row) {
|
|
const serviceId = row.id;
|
|
if (!row.id) ticketServiceCrudRef.value.reset();
|
|
else {
|
|
const { data } = await axios.delete(`TicketServices/${serviceId}`);
|
|
if (data) notify('Service deleted successfully', 'positive');
|
|
ticketServiceCrudRef.value.reload();
|
|
}
|
|
}
|
|
|
|
async function handleSave() {
|
|
if (!isSaving.value) {
|
|
isSaving.value = true;
|
|
await ticketServiceCrudRef.value?.saveChanges();
|
|
isSaving.value = false;
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<FetchData
|
|
ref="ticketServiceTypeFetchRef"
|
|
@on-fetch="(data) => (ticketServiceOptions = data)"
|
|
auto-load
|
|
url="TicketServiceTypes"
|
|
/>
|
|
<CrudModel
|
|
ref="ticketServiceCrudRef"
|
|
data-key="TicketService"
|
|
url="TicketServices"
|
|
model="TicketService"
|
|
:filter="crudModelFilter"
|
|
:data-required="crudModelRequiredData"
|
|
auto-load
|
|
v-model:selected="selected"
|
|
:order="['description ASC']"
|
|
:default-remove="false"
|
|
>
|
|
<template #moreBeforeActions>
|
|
<QBtn
|
|
color="primary"
|
|
:label="t('service.pay')"
|
|
:disabled="!selected.length"
|
|
@click.stop="createRefund()"
|
|
/>
|
|
</template>
|
|
<template #body="{ rows }">
|
|
<QTable
|
|
:columns="columns"
|
|
:rows="rows"
|
|
row-key="$index"
|
|
selection="multiple"
|
|
v-model:selected="selected"
|
|
table-header-class="text-left"
|
|
>
|
|
<template #body-cell-description="{ row, col }">
|
|
<QTd auto-width>
|
|
<VnSelectDialog
|
|
:label="col.label"
|
|
v-model="row.ticketServiceTypeFk"
|
|
:options="ticketServiceOptions"
|
|
option-label="name"
|
|
option-value="id"
|
|
hide-selected
|
|
>
|
|
<template #form>
|
|
<TicketCreateServiceType
|
|
@on-data-saved="ticketServiceTypeFetchRef.fetch()"
|
|
/>
|
|
</template>
|
|
</VnSelectDialog>
|
|
</QTd>
|
|
</template>
|
|
<template #body-cell-quantity="{ row, col }">
|
|
<QTd auto-width>
|
|
<VnInput
|
|
:label="col.label"
|
|
v-model.number="row.quantity"
|
|
type="number"
|
|
min="0"
|
|
:info="t('service.quantityInfo')"
|
|
/>
|
|
</QTd>
|
|
</template>
|
|
<template #body-cell-price="{ row, col }">
|
|
<QTd auto-width>
|
|
<VnInput
|
|
:label="col.label"
|
|
v-model.number="row.price"
|
|
type="number"
|
|
min="0"
|
|
@keyup.enter="handleSave"
|
|
/>
|
|
</QTd>
|
|
</template>
|
|
<template #body-cell-actions="{ row }">
|
|
<QTd auto-width>
|
|
<QIcon
|
|
color="primary"
|
|
name="delete"
|
|
class="cursor-pointer"
|
|
size="sm"
|
|
@click.stop="deleteService(row)"
|
|
>
|
|
<QTooltip class="text-no-wrap">
|
|
{{ t('globals.delete') }}
|
|
</QTooltip>
|
|
</QIcon>
|
|
</QTd>
|
|
</template>
|
|
</QTable>
|
|
</template>
|
|
</CrudModel>
|
|
<QPageSticky position="bottom-right" :offset="[25, 25]">
|
|
<QBtn
|
|
fab
|
|
color="primary"
|
|
icon="add"
|
|
@click="ticketServiceCrudRef.insert()"
|
|
shortcut="+"
|
|
/>
|
|
</QPageSticky>
|
|
</template>
|
|
ñ
|