Ticket basic data #474
|
@ -0,0 +1,245 @@
|
|||
<script setup>
|
||||
import { ref, computed, onMounted, onUnmounted } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
|
||||
import FetchedTags from 'components/ui/FetchedTags.vue';
|
||||
import RightMenu from 'src/components/common/RightMenu.vue';
|
||||
import FetchData from 'components/FetchData.vue';
|
||||
import { useVnConfirm } from 'composables/useVnConfirm';
|
||||
|
||||
import { useStateStore } from 'stores/useStateStore';
|
||||
import { toCurrency } from 'filters/index';
|
||||
import { useRole } from 'src/composables/useRole';
|
||||
|
||||
const $props = defineProps({
|
||||
ticketData: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
const stateStore = useStateStore();
|
||||
const { t } = useI18n();
|
||||
const { hasAny } = useRole();
|
||||
const { openConfirmationModal } = useVnConfirm();
|
||||
|
||||
const _ticketData = ref($props.ticketData);
|
||||
const ticketUpdateActions = ref(null);
|
||||
const haveNegatives = ref(false);
|
||||
const rows = computed(() => _ticketData.value?.sale?.items || []);
|
||||
|
||||
const columns = computed(() => [
|
||||
{
|
||||
label: t('basicData.item'),
|
||||
name: 'item',
|
||||
align: 'left',
|
||||
format: (val) => val.name,
|
||||
},
|
||||
{
|
||||
label: t('basicData.description'),
|
||||
name: 'description',
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
label: t('basicData.movable'),
|
||||
name: 'movable',
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
label: t('basicData.quantity'),
|
||||
name: 'quantity',
|
||||
field: 'quantity',
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
label: t('basicData.pricePPU'),
|
||||
name: 'price',
|
||||
field: 'price',
|
||||
jsegarra marked this conversation as resolved
|
||||
align: 'left',
|
||||
format: (val) => toCurrency(val),
|
||||
},
|
||||
{
|
||||
label: t('basicData.newPricePPU'),
|
||||
name: 'newPrice',
|
||||
field: (row) => row.component.newPrice,
|
||||
align: 'left',
|
||||
format: (val) => toCurrency(val),
|
||||
},
|
||||
{
|
||||
label: t('basicData.difference'),
|
||||
name: 'difference',
|
||||
field: (row) => row.component.difference,
|
||||
align: 'left',
|
||||
format: (val) => toCurrency(val),
|
||||
},
|
||||
]);
|
||||
|
||||
const loadDefaultTicketAction = () => {
|
||||
const isSalesAssistant = hasAny(['salesAssistant']);
|
||||
_ticketData.value.option = isSalesAssistant ? 'mana' : 'renewPrices';
|
||||
};
|
||||
|
||||
const totalPrice = computed(() => {
|
||||
return rows.value.reduce((acc, item) => acc + item.price * item.quantity, 0);
|
||||
});
|
||||
|
||||
const totalNewPrice = computed(() => {
|
||||
return rows.value.reduce(
|
||||
(acc, item) => acc + item.component.newPrice * item.quantity,
|
||||
0
|
||||
);
|
||||
});
|
||||
|
||||
const totalDifference = computed(() => {
|
||||
return rows.value.reduce(
|
||||
(acc, item) => acc + item.component.difference * item.quantity,
|
||||
0
|
||||
);
|
||||
});
|
||||
|
||||
const ticketHaveNegatives = () => {
|
||||
let _haveNegatives = false;
|
||||
let haveNotNegatives = false;
|
||||
_ticketData.value.withoutNegatives = false;
|
||||
const haveDifferences = _ticketData.value.sale.haveDifferences;
|
||||
|
||||
_ticketData.value.sale.items.forEach((item) => {
|
||||
if (item.quantity > item.movable) _haveNegatives = true;
|
||||
jsegarra marked this conversation as resolved
jsegarra
commented
revisar porque se muestra un resultado diferente revisar porque se muestra un resultado diferente
jsegarra
commented
Hay que eliminar * item.quantity Hay que eliminar * item.quantity
jsegarra
commented
El cambio anterior, con el registro 31 ✅, pero con el 7 ❌ El cambio anterior, con el registro 31 ✅, pero con el 7 ❌
wbuezas
commented
Fixed. Commit: Fixed.
Commit: https://gitea.verdnatura.es/verdnatura/salix-front/commit/266657fab5bd31f330b4a18bfbbf66dc238bf5a5
|
||||
else haveNotNegatives = true;
|
||||
});
|
||||
|
||||
haveNegatives.value = _haveNegatives && haveNotNegatives && haveDifferences;
|
||||
if (haveNegatives.value) _ticketData.value.withoutNegatives = true;
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
stateStore.rightDrawer = true;
|
||||
loadDefaultTicketAction();
|
||||
ticketHaveNegatives();
|
||||
console.log('ticketData: ', _ticketData.value);
|
||||
});
|
||||
|
||||
onUnmounted(() => (stateStore.rightDrawer = false));
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<FetchData
|
||||
url="TicketUpdateActions"
|
||||
@on-fetch="(data) => (ticketUpdateActions = data)"
|
||||
auto-load
|
||||
/>
|
||||
<RightMenu>
|
||||
<template #right-panel>
|
||||
<QCard
|
||||
class="q-pa-md q-mb-md q-ma-md color-vn-text"
|
||||
bordered
|
||||
flat
|
||||
style="border-color: black"
|
||||
>
|
||||
<QCardSection horizontal>
|
||||
<span class="text-weight-bold text-subtitle1 text-center full-width">
|
||||
{{ t('basicData.total') }}
|
||||
</span>
|
||||
</QCardSection>
|
||||
<QCardSection class="column items-center" horizontal>
|
||||
<span>
|
||||
{{ t('basicData.price') }}:
|
||||
{{ toCurrency(totalPrice) }}
|
||||
</span>
|
||||
</QCardSection>
|
||||
<QCardSection class="column items-center" horizontal>
|
||||
<span>
|
||||
{{ t('basicData.newPrice') }}: {{ toCurrency(totalNewPrice) }}
|
||||
</span>
|
||||
</QCardSection>
|
||||
<QCardSection class="column items-center" horizontal>
|
||||
<span>
|
||||
{{ t('basicData.difference') }}: {{ toCurrency(totalDifference) }}
|
||||
</span>
|
||||
</QCardSection>
|
||||
</QCard>
|
||||
<QCard
|
||||
v-if="totalDifference"
|
||||
class="q-pa-md q-mb-md q-ma-md color-vn-text"
|
||||
bordered
|
||||
flat
|
||||
style="border-color: black"
|
||||
>
|
||||
<QCardSection horizontal>
|
||||
<span class="text-weight-bold text-subtitle1 text-center full-width">
|
||||
{{ t('basicData.chargeDifference') }}
|
||||
</span>
|
||||
</QCardSection>
|
||||
<QCardSection
|
||||
v-for="(action, index) in ticketUpdateActions"
|
||||
:key="index"
|
||||
horizontal
|
||||
>
|
||||
<QRadio
|
||||
v-model="_ticketData.option"
|
||||
:val="action.code"
|
||||
:label="action.description"
|
||||
dense
|
||||
/>
|
||||
</QCardSection>
|
||||
</QCard>
|
||||
<QCard
|
||||
jsegarra
commented
Creo que falta añadir una condición de show según el valor totalPriceDifference Creo que falta añadir una condición de show según el valor totalPriceDifference
Idem, con el registro 31 ✅ y con el 7 ❌
|
||||
v-if="haveNegatives"
|
||||
class="q-pa-md q-mb-md q-ma-md color-vn-text"
|
||||
bordered
|
||||
flat
|
||||
style="border-color: black"
|
||||
>
|
||||
<QCardSection horizontal class="flex row items-center">
|
||||
<QCheckbox
|
||||
:label="t('basicData.withoutNegatives')"
|
||||
v-model="_ticketData.withoutNegatives"
|
||||
:toggle-indeterminate="false"
|
||||
/>
|
||||
<QIcon name="info" size="xs" class="q-ml-sm">
|
||||
<QTooltip max-width="350px">
|
||||
{{ t('basicData.withoutNegativesInfo') }}
|
||||
</QTooltip>
|
||||
</QIcon>
|
||||
</QCardSection>
|
||||
</QCard>
|
||||
</template>
|
||||
</RightMenu>
|
||||
<QTable
|
||||
:rows="rows"
|
||||
:columns="columns"
|
||||
row-key="id"
|
||||
:pagination="{ rowsPerPage: 0 }"
|
||||
class="full-width q-mt-md"
|
||||
:no-data-label="t('globals.noResults')"
|
||||
>
|
||||
<template #body-cell-item="{ row }">
|
||||
<QTd>
|
||||
<QBtn flat color="primary">
|
||||
{{ row.itemFk }}
|
||||
<ItemDescriptorProxy :id="row.itemFk" />
|
||||
</QBtn>
|
||||
</QTd>
|
||||
</template>
|
||||
<template #body-cell-description="{ row }">
|
||||
<QTd>
|
||||
<div class="column">
|
||||
<span>{{ row.item.name }}</span>
|
||||
<span class="color-vn-label">{{ row.item.subName }}</span>
|
||||
<FetchedTags :item="row.item" :max-length="6" />
|
||||
</div>
|
||||
</QTd>
|
||||
</template>
|
||||
<template #body-cell-movable="{ row }">
|
||||
<QTd>
|
||||
<QBadge
|
||||
v-if="row.haveDifferences"
|
||||
:text-color="row.quantity > row.movable ? 'black' : 'white'"
|
||||
:color="row.quantity > row.movable ? 'negative' : 'transparent'"
|
||||
:label="row.movable"
|
||||
/>
|
||||
</QTd>
|
||||
</template>
|
||||
</QTable>
|
||||
</template>
|
|
@ -10,6 +10,7 @@ import VnSelect from 'src/components/common/VnSelect.vue';
|
|||
import VnInput from 'src/components/common/VnInput.vue';
|
||||
import VnInputDate from 'src/components/common/VnInputDate.vue';
|
||||
import VnInputTime from 'components/common/VnInputTime.vue';
|
||||
import BasicDataTable from './BasicDataTable.vue';
|
||||
|
||||
import axios from 'axios';
|
||||
import useNotify from 'src/composables/useNotify.js';
|
||||
|
@ -289,6 +290,43 @@ const redirectToCustomerAddress = () => {
|
|||
params: { id: clientId.value, addressId: addressId.value },
|
||||
});
|
||||
};
|
||||
|
||||
const isFormInvalid = (formData) => {
|
||||
return (
|
||||
!formData.clientFk ||
|
||||
!formData.addressFk ||
|
||||
!formData.agencyModeFk ||
|
||||
!formData.companyFk ||
|
||||
!formData.shipped ||
|
||||
!formData.landed ||
|
||||
!formData.zoneFk
|
||||
);
|
||||
};
|
||||
|
||||
const onNextStep = async () => {
|
||||
if (step.value === 1) {
|
||||
const formData = formModelRef.value.formData;
|
||||
if (isFormInvalid(formData))
|
||||
return notify(t('basicData.someFieldsAreInvalid'), 'negative');
|
||||
|
||||
if (!formData.sale || formModelRef.value.hasChanges) {
|
||||
const params = {
|
||||
landed: formData.landed,
|
||||
addressId: formData.addressFk,
|
||||
agencyModeId: formData.agencyModeFk,
|
||||
zoneId: formData.zoneFk,
|
||||
warehouseId: formData.warehouseFk,
|
||||
shipped: formData.shipped,
|
||||
};
|
||||
const { data } = await axios.post(
|
||||
`tickets/${formData.id}/priceDifference`,
|
||||
params
|
||||
);
|
||||
formData.sale = data;
|
||||
stepperRef.value.next();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<FetchData
|
||||
|
@ -336,7 +374,7 @@ const redirectToCustomerAddress = () => {
|
|||
animated
|
||||
keep-alive
|
||||
>
|
||||
<QStep :name="1" title="Select campaign settings" :done="step > 1">
|
||||
<QStep :name="1" :title="t('globals.pageTitles.basicData')" :done="step > 1">
|
||||
<FormModel
|
||||
ref="formModelRef"
|
||||
:url="`Tickets/${route.params.id}`"
|
||||
|
@ -502,14 +540,14 @@ const redirectToCustomerAddress = () => {
|
|||
</template>
|
||||
</FormModel>
|
||||
</QStep>
|
||||
<QStep :name="2" title="Create an ad group" caption="Optional">
|
||||
An ad group contains one or more ads which target a shared set of keywords.
|
||||
<QStep :name="2" :title="t('basicData.priceDifference')">
|
||||
<BasicDataTable :ticket-data="formModelRef.formData" />
|
||||
</QStep>
|
||||
|
||||
<template #navigation>
|
||||
<QStepperNavigation>
|
||||
<QBtn
|
||||
@click="stepperRef.next()"
|
||||
@click="onNextStep()"
|
||||
color="primary"
|
||||
:label="step === 2 ? t('basicData.finalize') : t('basicData.next')"
|
||||
/>
|
|
@ -15,3 +15,20 @@ basicData:
|
|||
shipped: Shipped
|
||||
landed: Landed
|
||||
shippedHour: Shipped hour
|
||||
priceDifference: Price difference
|
||||
someFieldsAreInvalid: Some fields are invalid
|
||||
item: Item
|
||||
description: Description
|
||||
movable: Movable
|
||||
quantity: Quantity
|
||||
pricePPU: Price (PPU)
|
||||
newPricePPU: New (PPU)
|
||||
difference: Difference
|
||||
total: Total
|
||||
price: Price
|
||||
newPrice: New price
|
||||
chargeDifference: Charge difference to
|
||||
withoutNegatives: Create without negatives
|
||||
withoutNegativesInfo: Clone this ticket with the changes and only sales availables
|
||||
negativesConfirmTitle: Edit basic data
|
||||
negativesConfirmMessage: Negatives are going to be generated, are you sure you want to advance all the lines?
|
||||
|
|
|
@ -15,5 +15,22 @@ basicData:
|
|||
shipped: F. Envío
|
||||
landed: F. Entrega
|
||||
shippedHour: Hora de envío
|
||||
priceDifference: Diferencia de precio
|
||||
someFieldsAreInvalid: Algunos campos no son válidos
|
||||
item: Artículo
|
||||
description: Descripción
|
||||
movable: Movible
|
||||
quantity: Cantidad
|
||||
pricePPU: Precio (Ud.)
|
||||
newPricePPU: Nuevo (Ud.)
|
||||
difference: Diferencia
|
||||
total: Total
|
||||
price: Precio
|
||||
newPrice: Nuevo precio
|
||||
chargeDifference: Cargar diferencia a
|
||||
withoutNegatives: Crear sin negativos
|
||||
withoutNegativesInfo: Clonar este ticket con los cambios y solo ventas disponibles
|
||||
negativesConfirmTitle: Editar datos básicos
|
||||
negativesConfirmMessage: Se van a generar negativos, ¿seguro que quieres adelantar todas las líneas?
|
||||
Search ticket: Buscar ticket
|
||||
You can search by ticket id or alias: Puedes buscar por id o alias del ticket
|
||||
|
|
|
@ -64,7 +64,8 @@ export default {
|
|||
title: 'basicData',
|
||||
icon: 'vn:settings',
|
||||
},
|
||||
component: () => import('src/pages/Ticket/Card/TicketBasicData.vue'),
|
||||
component: () =>
|
||||
import('src/pages/Ticket/Card/BasicData/TicketBasicDataView.vue'),
|
||||
},
|
||||
{
|
||||
name: 'TicketSale',
|
||||
|
|
Loading…
Reference in New Issue
esta columna tiene que ser condicional en base al campo priceDifferences.haveDifferences