Merge pull request 'Item Basic data' (!346) from hyervoni/salix-front-mindshore:feature/ItemBasicData into dev
gitea/salix-front/pipeline/head This commit looks good
Details
gitea/salix-front/pipeline/head This commit looks good
Details
Reviewed-on: #346 Reviewed-by: Javier Segarra <jsegarra@verdnatura.es> Reviewed-by: Alex Moreno <alexm@verdnatura.es>
This commit is contained in:
commit
175746a4a4
|
@ -1,7 +1,6 @@
|
|||
<script setup>
|
||||
import { ref, reactive, computed } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useRoute } from 'vue-router';
|
||||
|
||||
import VnRow from 'components/ui/VnRow.vue';
|
||||
import FetchData from 'components/FetchData.vue';
|
||||
|
@ -12,10 +11,16 @@ import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
|
|||
import axios from 'axios';
|
||||
import { dashIfEmpty } from 'src/filters';
|
||||
|
||||
const props = defineProps({
|
||||
url: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['itemSelected']);
|
||||
|
||||
const { t } = useI18n();
|
||||
const route = useRoute();
|
||||
|
||||
const itemFilter = {
|
||||
include: [
|
||||
|
@ -73,7 +78,7 @@ const tableColumns = computed(() => [
|
|||
{
|
||||
label: t('entry.buys.color'),
|
||||
name: 'ink',
|
||||
field: 'inkName',
|
||||
field: (row) => row?.ink?.name,
|
||||
align: 'left',
|
||||
},
|
||||
]);
|
||||
|
@ -100,7 +105,7 @@ const fetchResults = async () => {
|
|||
}
|
||||
filter.where = where;
|
||||
|
||||
const { data } = await axios.get(`Entries/${route.params.id}/lastItemBuys`, {
|
||||
const { data } = await axios.get(props.url, {
|
||||
params: { filter: JSON.stringify(filter) },
|
||||
});
|
||||
tableRows.value = data;
|
||||
|
|
|
@ -52,6 +52,11 @@ const focus = () => {
|
|||
defineExpose({
|
||||
focus,
|
||||
});
|
||||
|
||||
const inputRules = (val) => {
|
||||
const { min } = vnInputRef.value.$attrs;
|
||||
if (min >= 0) if (Math.floor(val) < min) return t('inputMin', { value: min });
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -68,6 +73,8 @@ defineExpose({
|
|||
:class="{ required: $attrs.required }"
|
||||
@keyup.enter="onEnterPress()"
|
||||
:clearable="false"
|
||||
:rules="[inputRules]"
|
||||
:lazy-rules="true"
|
||||
>
|
||||
<template v-if="$slots.prepend" #prepend>
|
||||
<slot name="prepend" />
|
||||
|
@ -85,3 +92,9 @@ defineExpose({
|
|||
</QInput>
|
||||
</div>
|
||||
</template>
|
||||
<i18n>
|
||||
en:
|
||||
inputMin: Must be more than {value}
|
||||
es:
|
||||
inputMin: Debe ser mayor a {value}
|
||||
</i18n>
|
||||
|
|
|
@ -251,6 +251,7 @@ const redirectToBuysView = () => {
|
|||
>
|
||||
<template #form>
|
||||
<FilterItemForm
|
||||
:url="`Entries/${route.params.id}/lastItemBuys`"
|
||||
@item-selected="row[col.field] = $event"
|
||||
/>
|
||||
</template>
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
<script setup>
|
||||
import { reactive, ref, onMounted, nextTick } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useRoute } from 'vue-router';
|
||||
|
||||
import VnInput from 'src/components/common/VnInput.vue';
|
||||
import VnRow from 'components/ui/VnRow.vue';
|
||||
import FormModelPopup from 'components/FormModelPopup.vue';
|
||||
|
||||
const { t } = useI18n();
|
||||
const emit = defineEmits(['onDataSaved']);
|
||||
const route = useRoute();
|
||||
|
||||
const identifierInputRef = ref(null);
|
||||
const intrastatFormData = reactive({});
|
||||
|
||||
const onDataSaved = (formData, requestResponse) => {
|
||||
emit('onDataSaved', formData, requestResponse);
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
await nextTick();
|
||||
identifierInputRef.value.focus();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<FormModelPopup
|
||||
:url-update="`Items/${route.params.id}/createIntrastat`"
|
||||
model="itemGenus"
|
||||
:title="t('createIntrastatForm.title')"
|
||||
:form-initial-data="intrastatFormData"
|
||||
@on-data-saved="onDataSaved"
|
||||
>
|
||||
<template #form-inputs="{ data }">
|
||||
<VnRow class="row q-gutter-md q-mb-md">
|
||||
<VnInput
|
||||
ref="identifierInputRef"
|
||||
:label="t('createIntrastatForm.identifier')"
|
||||
type="number"
|
||||
v-model.number="data.intrastatId"
|
||||
:required="true"
|
||||
/>
|
||||
<VnInput
|
||||
:label="t('createIntrastatForm.description')"
|
||||
v-model="data.description"
|
||||
:required="true"
|
||||
/>
|
||||
</VnRow>
|
||||
</template>
|
||||
</FormModelPopup>
|
||||
</template>
|
|
@ -1 +1,233 @@
|
|||
<template>Item basic data</template>
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import FetchData from 'components/FetchData.vue';
|
||||
import FormModel from 'components/FormModel.vue';
|
||||
import VnRow from 'components/ui/VnRow.vue';
|
||||
import VnInput from 'src/components/common/VnInput.vue';
|
||||
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||
import VnSelectDialog from 'src/components/common/VnSelectDialog.vue';
|
||||
import FilterItemForm from 'src/components/FilterItemForm.vue';
|
||||
import CreateIntrastatForm from './CreateIntrastatForm.vue';
|
||||
|
||||
const route = useRoute();
|
||||
const { t } = useI18n();
|
||||
|
||||
const itemTypesOptions = ref([]);
|
||||
const itemsWithNameOptions = ref([]);
|
||||
const intrastatsOptions = ref([]);
|
||||
const expensesOptions = ref([]);
|
||||
|
||||
const onIntrastatCreated = (response, formData) => {
|
||||
intrastatsOptions.value = [...intrastatsOptions.value, response];
|
||||
formData.intrastatFk = response.id;
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<FetchData
|
||||
url="ItemTypes"
|
||||
:filter="{
|
||||
fields: ['id', 'name', 'categoryFk'],
|
||||
include: 'category',
|
||||
order: 'name ASC',
|
||||
}"
|
||||
@on-fetch="(data) => (itemTypesOptions = data)"
|
||||
auto-load
|
||||
/>
|
||||
<FetchData
|
||||
url="Items/withName"
|
||||
:filter="{
|
||||
fields: ['id', 'name'],
|
||||
order: 'id DESC',
|
||||
}"
|
||||
@on-fetch="(data) => (itemsWithNameOptions = data)"
|
||||
auto-load
|
||||
/>
|
||||
<FetchData
|
||||
url="Intrastats"
|
||||
:filter="{
|
||||
fields: ['id', 'description'],
|
||||
order: 'description ASC',
|
||||
}"
|
||||
@on-fetch="(data) => (intrastatsOptions = data)"
|
||||
auto-load
|
||||
/>
|
||||
<FetchData
|
||||
url="Expenses"
|
||||
:filter="{
|
||||
fields: ['id', 'name'],
|
||||
order: 'name ASC',
|
||||
}"
|
||||
@on-fetch="(data) => (expensesOptions = data)"
|
||||
auto-load
|
||||
/>
|
||||
<FormModel
|
||||
:url="`Items/${route.params.id}`"
|
||||
:url-update="`Items/${route.params.id}`"
|
||||
model="item"
|
||||
auto-load
|
||||
:clear-store-on-unmount="false"
|
||||
>
|
||||
<template #form="{ data }">
|
||||
<VnRow class="row q-gutter-md q-mb-md">
|
||||
<VnSelect
|
||||
:label="t('basicData.type')"
|
||||
v-model="data.typeFk"
|
||||
:options="itemTypesOptions"
|
||||
option-value="id"
|
||||
option-label="name"
|
||||
hide-selected
|
||||
map-options
|
||||
>
|
||||
<template #option="scope">
|
||||
<QItem v-bind="scope.itemProps">
|
||||
<QItemSection>
|
||||
<QItemLabel>{{ scope.opt?.name }}</QItemLabel>
|
||||
<QItemLabel caption>
|
||||
{{ scope.opt?.category?.name }}
|
||||
</QItemLabel>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
</template>
|
||||
</VnSelect>
|
||||
<VnInput :label="t('basicData.reference')" v-model="data.comment" />
|
||||
<VnInput :label="t('basicData.relevancy')" v-model="data.relevancy" />
|
||||
</VnRow>
|
||||
<VnRow class="row q-gutter-md q-mb-md">
|
||||
<VnInput :label="t('basicData.stems')" v-model="data.stems" />
|
||||
<VnInput
|
||||
:label="t('basicData.multiplier')"
|
||||
v-model="data.stemMultiplier"
|
||||
/>
|
||||
<VnSelectDialog
|
||||
:label="t('basicData.generic')"
|
||||
v-model="data.genericFk"
|
||||
:options="itemsWithNameOptions"
|
||||
option-value="id"
|
||||
option-label="name"
|
||||
map-options
|
||||
hide-selected
|
||||
action-icon="filter_alt"
|
||||
>
|
||||
<template #form>
|
||||
<FilterItemForm
|
||||
url="Items/withName"
|
||||
@item-selected="data.genericFk = $event"
|
||||
/>
|
||||
</template>
|
||||
<template #option="scope">
|
||||
<QItem v-bind="scope.itemProps">
|
||||
<QItemSection>
|
||||
<QItemLabel>{{ scope.opt?.name }}</QItemLabel>
|
||||
<QItemLabel caption> #{{ scope.opt?.id }} </QItemLabel>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
</template>
|
||||
</VnSelectDialog>
|
||||
</VnRow>
|
||||
<VnRow class="row q-gutter-md q-mb-md">
|
||||
<VnSelectDialog
|
||||
:label="t('basicData.intrastat')"
|
||||
v-model="data.intrastatFk"
|
||||
:options="intrastatsOptions"
|
||||
option-value="id"
|
||||
option-label="description"
|
||||
map-options
|
||||
hide-selected
|
||||
>
|
||||
<template #form>
|
||||
<CreateIntrastatForm
|
||||
@on-data-saved="
|
||||
(_, requestResponse) =>
|
||||
onIntrastatCreated(requestResponse, data)
|
||||
"
|
||||
/>
|
||||
</template>
|
||||
<template #option="scope">
|
||||
<QItem v-bind="scope.itemProps">
|
||||
<QItemSection>
|
||||
<QItemLabel>{{ scope.opt?.description }}</QItemLabel>
|
||||
<QItemLabel caption> #{{ scope.opt?.id }} </QItemLabel>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
</template>
|
||||
</VnSelectDialog>
|
||||
<div class="col">
|
||||
<VnSelect
|
||||
:label="t('basicData.expense')"
|
||||
v-model="data.expenseFk"
|
||||
:options="expensesOptions"
|
||||
option-value="id"
|
||||
option-label="name"
|
||||
hide-selected
|
||||
map-options
|
||||
/>
|
||||
</div>
|
||||
</VnRow>
|
||||
<VnRow class="row q-gutter-md q-mb-md">
|
||||
<VnInput
|
||||
:label="t('basicData.weightByPiece')"
|
||||
v-model.number="data.weightByPiece"
|
||||
:min="0"
|
||||
type="number"
|
||||
/>
|
||||
<VnInput
|
||||
:label="t('basicData.boxUnits')"
|
||||
v-model.number="data.packingOut"
|
||||
:min="0"
|
||||
type="number"
|
||||
/>
|
||||
<VnInput
|
||||
:label="t('basicData.recycledPlastic')"
|
||||
v-model.number="data.recycledPlastic"
|
||||
:min="0"
|
||||
type="number"
|
||||
/>
|
||||
<VnInput
|
||||
:label="t('basicData.nonRecycledPlastic')"
|
||||
v-model.number="data.nonRecycledPlastic"
|
||||
:min="0"
|
||||
type="number"
|
||||
/>
|
||||
</VnRow>
|
||||
<VnRow class="row q-gutter-md q-mb-md">
|
||||
<QCheckbox v-model="data.isActive" :label="t('basicData.isActive')" />
|
||||
<QCheckbox v-model="data.hasKgPrice" :label="t('basicData.hasKgPrice')" />
|
||||
<div>
|
||||
<QCheckbox
|
||||
v-model="data.isFragile"
|
||||
:label="t('basicData.isFragile')"
|
||||
class="q-mr-sm"
|
||||
/>
|
||||
<QIcon name="info" class="cursor-pointer" size="xs">
|
||||
<QTooltip max-width="300px">
|
||||
{{ t('basicData.isFragileTooltip') }}
|
||||
</QTooltip>
|
||||
</QIcon>
|
||||
</div>
|
||||
<div>
|
||||
<QCheckbox
|
||||
v-model="data.isPhotoRequested"
|
||||
:label="t('basicData.isPhotoRequested')"
|
||||
class="q-mr-sm"
|
||||
/>
|
||||
<QIcon name="info" class="cursor-pointer" size="xs">
|
||||
<QTooltip>
|
||||
{{ t('basicData.isPhotoRequestedTooltip') }}
|
||||
</QTooltip>
|
||||
</QIcon>
|
||||
</div>
|
||||
</VnRow>
|
||||
<VnRow class="row q-gutter-md q-mb-md">
|
||||
<QInput
|
||||
:label="t('basicData.description')"
|
||||
type="textarea"
|
||||
v-model="data.description"
|
||||
fill-input
|
||||
/>
|
||||
</VnRow>
|
||||
</template>
|
||||
</FormModel>
|
||||
</template>
|
||||
|
|
|
@ -11,6 +11,30 @@ itemDiary:
|
|||
showBefore: Show what's before the inventory
|
||||
since: Since
|
||||
warehouse: Warehouse
|
||||
basicData:
|
||||
type: Type
|
||||
reference: Reference
|
||||
relevancy: Relevancy
|
||||
stems: Stems
|
||||
multiplier: Multiplier
|
||||
generic: Generic
|
||||
intrastat: Intrastat
|
||||
expense: Expense
|
||||
weightByPiece: Weight/Piece
|
||||
boxUnits: Units/Box
|
||||
recycledPlastic: Recycled plastic
|
||||
nonRecycledPlastic: Non recycled plastic
|
||||
description: Description
|
||||
isActive: Active
|
||||
hasKgPrice: Price in kg
|
||||
isFragile: Fragile
|
||||
isFragileTooltip: Is shown at website, app that this item cannot travel (wreath, palms, ...)
|
||||
isPhotoRequested: Do photo
|
||||
isPhotoRequestedTooltip: This item does need a photo
|
||||
createIntrastatForm:
|
||||
title: New intrastat
|
||||
identifier: Identifier
|
||||
description: Description
|
||||
tax:
|
||||
country: Country
|
||||
class: Class
|
||||
|
|
|
@ -11,6 +11,30 @@ itemDiary:
|
|||
showBefore: Mostrar lo anterior al inventario
|
||||
since: Desde
|
||||
warehouse: Almacén
|
||||
basicData:
|
||||
type: Tipo
|
||||
reference: Referencia
|
||||
relevancy: Relevancia
|
||||
stems: Tallos
|
||||
multiplier: Multiplicador
|
||||
generic: Genérico
|
||||
intrastat: Intrastat
|
||||
expense: Gasto
|
||||
weightByPiece: Peso (gramos)/tallo
|
||||
boxUnits: Unidades/caja
|
||||
recycledPlastic: Plástico reciclado
|
||||
nonRecycledPlastic: Plástico no reciclado
|
||||
description: Descripción
|
||||
isActive: Activo
|
||||
hasKgPrice: Precio en kg
|
||||
isFragile: Frágil
|
||||
isFragileTooltip: Se muestra en la web app, que este artículo no puede viajar (coronas, palmas, ...)
|
||||
isPhotoRequested: Hacer foto
|
||||
isPhotoRequestedTooltip: Este artículo necesita una foto
|
||||
createIntrastatForm:
|
||||
title: Nuevo intrastat
|
||||
identifier: Identificador
|
||||
description: Descripción
|
||||
tax:
|
||||
country: País
|
||||
class: Clase
|
||||
|
|
Loading…
Reference in New Issue