6157-actionClaim #106

Merged
carlossa merged 22 commits from 6157-actionClaim into dev 2023-11-24 07:46:30 +00:00
8 changed files with 526 additions and 16 deletions
Showing only changes of commit f230fcbca2 - Show all commits

View File

@ -4,7 +4,7 @@ const emit = defineEmits(['update:modelValue', 'update:options']);
const $props = defineProps({
modelValue: {
type: [String, Number],
type: [String, Number, Object],
default: null,
},
options: {

View File

@ -2,6 +2,7 @@
import { onMounted, useSlots, ref, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import axios from 'axios';
import { useArrayData } from 'src/composables/useArrayData';
import SkeletonDescriptor from 'components/ui/SkeletonDescriptor.vue';
const $props = defineProps({
@ -26,18 +27,21 @@ const $props = defineProps({
default: 0,
},
});
const arrayData = useArrayData('claimData');
const store = arrayData.store;
console.log('eee', store.data);
const slots = useSlots();
const { t } = useI18n();
const entity = ref();
const entity = ref(null);
let lastUrl = ref(null);
carlossa marked this conversation as resolved
Review

Esta tb borrala

Esta tb borrala
onMounted(async () => {
await fetch();
entity.value = await store.data;
});
const emit = defineEmits(['onFetch']);
async function fetch() {
lastUrl.value = $props.url;
const params = {};
if ($props.filter) params.filter = JSON.stringify($props.filter);
@ -49,6 +53,7 @@ async function fetch() {
}
watch($props, async () => {
if (lastUrl.value == $props.url) return;
entity.value = null;
await fetch();
});

View File

@ -269,6 +269,7 @@ export default {
development: 'Development',
log: 'Audit logs',
notes: 'Notes',
action: 'Action',
},
list: {
customer: 'Customer',

View File

@ -268,6 +268,7 @@ export default {
photos: 'Fotos',
log: 'Registros de auditoría',
notes: 'Notas',
action: 'Action',
},
list: {
customer: 'Cliente',

View File

@ -0,0 +1,454 @@
<script setup>
import { ref, computed, watchEffect, onMounted, onUnmounted } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRoute } from 'vue-router';
import axios from 'axios';
import { useStateStore } from 'src/stores/useStateStore';
import { toDate, toPercentage, toCurrency } from 'filters/index';
import CrudModel from 'src/components/CrudModel.vue';
import FetchData from 'src/components/FetchData.vue';
import TicketDescriptorProxy from 'src/pages/Ticket/Card/TicketDescriptorProxy.vue';
import VnSelectFilter from 'src/components/common/VnSelectFilter.vue';
import { useArrayData } from 'src/composables/useArrayData';
const { t } = useI18n();
const route = useRoute();
const stateStore = computed(() => useStateStore());
const claimId = route.params.id;
const dialog = ref(false);
const dialogOption = ref(null);
const resolvedStateId = ref(null);
const claimActionsForm = ref();
const rows = ref([]);
const selectedRows = ref([]);
const destinationTypes = ref([]);
const destinations = ref([]);
const totalClaimed = ref(null);
const responsibility = ref(5); // pending to get from ClaimDescriptor
const manaCharger = ref(false); // pending to get from ClaimDescriptor
const claimData = useArrayData('claimData');
// ClaimEnds/filter?filter={ claimFk: route.param.id}
carlossa marked this conversation as resolved Outdated
Outdated
Review

Si es un numero li pots possar const maxResponsibility = 5;

Si es un numero li pots possar const maxResponsibility = 5;

Si que puedes,
Sin embargo, te diría que ese 5, quizás moverlo a un const DEFAULT_MAX_RESPONSABILITY = 5.

Ya me dices

Si que puedes, Sin embargo, te diría que ese 5, quizás moverlo a un const DEFAULT_MAX_RESPONSABILITY = 5. Ya me dices
// for update responsability and mana /Claims/id/updateClaimAction
// onMounted(() => (stateStore.value.rightDrawer = true));
// onUnmounted(() => (stateStore.value.rightDrawer = false));
const columns = computed(() => [
{
name: 'Id',
label: t('Id'),
field: (row) => row.itemFk,
},
{
name: 'ticket',
label: t('Ticket'),
field: (row) => row.ticketFk,
align: 'center',
},
{
carlossa marked this conversation as resolved
Review

Pq no pots possar row.claimDestinationFk ?

Pq no pots possar row.claimDestinationFk ?
name: 'destination',
label: t('Destination'),
field: (row) => getDestination(row.claimDestinationFk),
align: 'left',
},
{
name: 'Landed',
label: t('Landed'),
field: (row) => toDate(row.landed),
},
{
name: 'quantity',
label: t('Quantity'),
field: (row) => row.quantity,
},
{
name: 'concept',
label: t('Description'),
field: (row) => row.concept,
align: 'left',
},
{
name: 'price',
label: t('Price'),
field: (row) => row.price,
format: (value) => value,
align: 'center',
},
{
name: 'discount',
label: t('Discount'),
field: (row) => row.discount,
format: (value) => toPercentage(value / 100),
align: 'left',
},
{
name: 'total',
label: t('Total'),
field: (row) => row.total,
format: (value) => value,
align: 'center',
},
{
name: 'delete',
},
carlossa marked this conversation as resolved Outdated
Outdated
Review

? si lo que fas es sumar no seria mes facil sumar en el onmouted y quan afegixes o borres una linea?

? si lo que fas es sumar no seria mes facil sumar en el onmouted y quan afegixes o borres una linea?
]);
console.log(claimData.store.data);
watchEffect(() => {
if (rows.value.length) {
destinations.value = rows.value.map((row) =>
getDestination(row.claimDestinationFk)
);
totalClaimed.value = rows.value.reduce((total, row) => total + row.total, 0);
}
});
function getDestination(destinationId) {
return destinationTypes.value.find((type) => type.id == destinationId);
carlossa marked this conversation as resolved Outdated
Outdated
Review

Esta funcio no se crida mai

Esta funcio no se crida mai
}
async function updateDestination(claimDestinationFk, row) {
if (claimDestinationFk) {
await axios.post('Claims/updateClaimDestination', {
carlossa marked this conversation as resolved Outdated

Lo revisamos!!

**Lo revisamos!!**
claimDestinationFk,
rows: [row],
});
}
}
async function deleteSale(sale) {
await axios.post(`ClaimEnds/deleteClamedSales`, { sales: [sale] });
claimActionsForm.value.reload();
}
carlossa marked this conversation as resolved
Review

Y esto también!!

Y esto también!!
async function updateDestinations(claimDestinationFk) {
if (claimDestinationFk) {
await axios.post('Claims/updateClaimDestination', {
claimDestinationFk,
rows: [...selectedRows.value],
});
claimActionsForm.value.reload();
}
}
</script>
<template>
<template v-if="stateStore.isHeaderMounted()">
<Teleport to="#actions-append">
<div class="row q-gutter-x-sm">
<QBtn
flat
carlossa marked this conversation as resolved Outdated

Lo que le pasas a notify podría ser una constante, no? Porque lo hacemos en la línea 148, 166, 195

Lo que le pasas a notify podría ser una constante, no? Porque lo hacemos en la línea 148, 166, 195
@click="stateStore.toggleRightDrawer()"
round
dense
icon="menu"
>
<QTooltip bottom anchor="bottom right">
{{ t('globals.collapseMenu') }}
</QTooltip>
</QBtn>
</div>
</Teleport>
</template>
<QDrawer v-model="stateStore.rightDrawer" side="right" :width="300" show-if-above>
<QScrollArea class="fit text-grey-8 q-mt-lg">
<div class="totalClaim q-mb-md">
{{ `${t('Total claimed')}: ${toCurrency(totalClaimed)}` }}
</div>
<QCard class="q-mb-md q-pa-sm">
<QItem class="justify-between">
<QItemLabel class="slider-container">
<p class="text-primary">
{{ t('claim.summary.actions') }}
</p>
<QSlider
class="responsability"
v-model="responsibility"
label
:label-value="t('claim.summary.responsibility')"
label-always
color="primary"
markers
:marker-labels="[
{ value: 1, label: t('claim.summary.company') },
{ value: 5, label: t('claim.summary.person') },
]"
:min="1"
:max="5"
/>
</QItemLabel>
</QItem>
</QCard>
<QItemLabel class="mana q-mb-md">
<QCheckbox v-model="manaCharger" />
<span>{{ t('mana') }}</span>
</QItemLabel>
</QScrollArea>
</QDrawer>
<FetchData
url="ClaimDestinations"
auto-load
@on-fetch="(data) => (destinationTypes = data)"
/>
<FetchData
:url="`ClaimStates/findOne`"
:where="{ code: 'resolved' }"
auto-load
@on-fetch="(data) => (resolvedStateId = data)"
/>
<Teleport to="#st-data" v-if="stateStore.isSubToolbarShown()">
<QToolbar>
<QBtn
color="primary"
text-color="white"
class="q-mx-sm"
:unelevated="true"
:disable="!selectedRows.length"
:label="t('Change destination')"
@click="dialog = !dialog"
/>
</QToolbar>
</Teleport>
<div class="claim-action">
<CrudModel
data-key="ClaimEnds"
url="ClaimEnds/filter"
save-url="ClaimEnds/crud"
ref="claimActionsForm"
v-model:selected="selectedRows"
:filter="{ where: { claimFk: claimId } }"
:default-remove="true"
:default-save="false"
:default-reset="false"
@on-fetch="(data) => (rows = data)"
auto-load
>
<template #body>
<QTable
:columns="columns"
:rows="rows"
:dense="$q.screen.lt.md"
:pagination="{ rowsPerPage: 0 }"
row-key="id"
selection="multiple"
v-model:selected="selectedRows"
hide-pagination
:grid="$q.screen.lt.md"
>
<template #body-cell-ticket="{ value }">
<QTd align="center">
<span class="link">
{{ value }}
<TicketDescriptorProxy :id="value" />
</span>
</QTd>
</template>
<template #body-cell-destination="{ rowIndex }">
<QTd>
<VnSelectFilter
v-model="destinations[rowIndex]"
:options="destinationTypes"
option-value="id"
option-label="description"
@update:model-value="
(value) => updateDestination(value, rows[rowIndex])
"
/>
</QTd>
</template>
<template #body-cell-price="{ value }">
<QTd align="center">
{{ toCurrency(value) }}
</QTd>
</template>
carlossa marked this conversation as resolved
Review

Si, los labels cambian, tienes que venir hasta el HTML?
Quizás, mejor definirlo en el apartado de

Si, los labels cambian, tienes que venir hasta el HTML? Quizás, mejor definirlo en el apartado de <script setup>
<template #body-cell-total="{ value }">
<QTd align="center">
{{ toCurrency(value) }}
</QTd>
carlossa marked this conversation as resolved
Review

Podemos definir este valor como constante?
Tipo
DEFAULT_MIN_SLIDER =1
DEFAULT_MAX_SLIDER =5

Podemos definir este valor como constante? Tipo DEFAULT_MIN_SLIDER =1 DEFAULT_MAX_SLIDER =5
</template>
<template #body-cell-delete="{ rowIndex }">
<QTd>
<QBtn
icon="delete"
color="primary"
padding="xs"
round
flat
@click="deleteSale(rows[rowIndex])"
>
<QTooltip>
{{ t('Remove line') }}
</QTooltip>
</QBtn>
</QTd>
</template>
<!-- View for grid mode -->
<template #item="props">
<div class="q-mb-md col-12 grid-style-transition">
<QCard>
<QCardSection class="row justify-between">
<QCheckbox v-model="props.selected" />
<QBtn color="primary" icon="delete" flat round />
</QCardSection>
<QSeparator inset />
<QList dense>
<QItem
v-for="column of props.cols"
:key="column.name"
>
<QItemSection>
<QItemLabel caption>
{{ column.label }}
</QItemLabel>
</QItemSection>
<QItemSection side>
<QItemLabel
v-if="column.name === 'destination'"
>
{{ column.value.description }}
</QItemLabel>
<QItemLabel v-else>
{{ column.value }}
</QItemLabel>
</QItemSection>
</QItem>
</QList>
</QCard>
</div>
</template>
</QTable>
</template>
<template #moreActions>
<QBtn
color="primary"
text-color="white"
class="q-mx-sm"
:unelevated="true"
:label="t('Regularize')"
/>
<!--disabled="(ClaimDescriptor)claimStateFk == resolvedStateId"-->
<QBtn
color="primary"
text-color="white"
class="q-mx-sm"
:unelevated="true"
:disable="!selectedRows.length"
:label="t('Change destination')"
@click="dialog = !dialog"
/>
<QBtn
color="primary"
text-color="white"
class="q-mx-sm"
:unelevated="true"
:label="t('Import claim')"
/>
<!--disabled="(ClaimDescriptor)claimStateFk == resolvedStateId"-->
</template>
</CrudModel>
<QDialog v-model="dialog">
<QCard>
<QCardSection>
<QItem class="q-pa-none">
<span class="q-dialog__title text-white">
{{ t('dialog title') }}
</span>
<QBtn icon="close" flat round dense v-close-popup />
</QItem>
</QCardSection>
<QCardSection>
<VnSelectFilter
v-model="dialogOption"
:options="destinationTypes"
option-label="description"
option-value="id"
/>
</QCardSection>
<QCardActions class="justify-end q-mr-sm">
<QBtn
flat
:label="t('globals.close')"
color="primary"
v-close-popup
/>
<QBtn
:disable="!dialogOption"
:label="t('globals.save')"
color="primary"
v-close-popup
@click="updateDestinations(dialogOption)"
/>
</QCardActions>
</QCard>
</QDialog>
</div>
</template>
<style lang="scss">
.claim-action {
.q-table {
.q-select .q-field__input {
display: none !important;
}
}
}
</style>
<style lang="scss" scoped>
.slider-container {
width: 50%;
}
@media (max-width: $breakpoint-xs) {
.slider-container {
width: 90%;
}
}
.q-table {
.q-item {
min-height: min-content;
height: 0;
}
}
.q-dialog {
.q-btn {
height: min-content;
}
}
.totalClaim {
border: 3px solid black;
color: white;
padding: 10px;
margin: 5px;
}
.responsability {
max-width: 100%;
margin-left: 40px;
}
.mana {
color: white;
float: inline-start;
}
.qdrawer {
}
</style>
<i18n>
en:
mana: Is paid with mana
dialog title: Change destination to all selected rows
es:
mana: Cargado al maná
Delivered: Descripción
Quantity: Cantidad
Claimed: Rec
Description: Description
Price: Precio
Discount: Dto.
Destination: Destino
Landed: F.entrega
Remove line: Eliminar línea
Total claimed: Total reclamado
Regularize: Regularizar
Change destination: Cambiar destino
Import claim: Importar reclamación
dialog title: Cambiar destino en todas las filas seleccionadas
Remove: Eliminar
</i18n>

View File

@ -1,17 +1,58 @@
<script setup>
import LeftMenu from 'components/LeftMenu.vue';
import { onMounted, computed } from 'vue';
import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import { useStateStore } from 'stores/useStateStore';
import { useArrayData } from 'src/composables/useArrayData';
import { getUrl } from 'composables/getUrl';
import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
import { useStateStore } from 'stores/useStateStore';
import { computed } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRoute } from 'vue-router';
import LeftMenu from 'components/LeftMenu.vue';
import ClaimDescriptor from './ClaimDescriptor.vue';
import { onMounted } from 'vue';
const stateStore = useStateStore();
const { t } = useI18n();
const route = useRoute();
const filter = {
include: [
{
relation: 'client',
scope: {
include: { relation: 'salesPersonUser' },
},
},
carlossa marked this conversation as resolved
Review

esto no se usa, no?

esto no se usa, no?
{
relation: 'claimState',
},
{
relation: 'ticket',
scope: {
include: [
{ relation: 'zone' },
{
relation: 'address',
scope: {
include: { relation: 'province' },
},
},
],
},
},
{
relation: 'worker',
scope: {
include: { relation: 'user' },
},
},
],
};
const arrayData = useArrayData('claimData', {
url: `Claims/${route.params.id}`,
filter,
});
const entityId = computed(() => {
return $props.id || route.params.id;
});
const $props = defineProps({
id: {
type: Number,
@ -19,13 +60,11 @@ const $props = defineProps({
default: null,
},
});
const entityId = computed(() => {
return $props.id || route.params.id;
});
let salixUrl;
onMounted(async () => {
salixUrl = await getUrl(`claim/${entityId.value}`);
await arrayData.fetch({ append: false });
});
</script>
<template>

View File

@ -68,7 +68,7 @@ function viewSummary(id) {
</div>
</Teleport>
</template>
<QDrawer v-model="stateStore.rightDrawer" side="right" :width="256" show-if-above>
<QDrawer v-model="stateStore.rightDrawer" side="right" :width="256">
<QScrollArea class="fit text-grey-8">
<TicketFilter data-key="TicketList" />
</QScrollArea>

View File

@ -19,6 +19,7 @@ export default {
'ClaimLog',
'ClaimNotes',
'ClaimDevelopment',
'ClaimAction',
],
},
children: [
@ -130,6 +131,15 @@ export default {
},
component: () => import('src/pages/Claim/Card/ClaimNotes.vue'),
},
{
name: 'ClaimAction',
path: 'action',
meta: {
title: 'action',
icon: 'vn:actions',
},
component: () => import('src/pages/Claim/Card/ClaimAction.vue'),
},
],
},
],