-
-
-
-
- #{{ scope.opt?.id }}
- {{ scope.opt?.nickname }}
-
-
-
-
-
O
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ #{{ scope.opt?.id }} -
+ {{ scope.opt?.name }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{
+ `${
+ !scope.opt?.isActive
+ ? t('inactive')
+ : ''
+ } `
+ }}
+ {{
+ scope.opt?.nickname
+ }}
+
+ , {{ scope.opt?.street }},
+ {{ scope.opt?.city }},
+ {{
+ scope.opt?.province?.name
+ }}
+ -
+ {{
+ scope.opt?.agencyMode
+ ?.name
+ }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ scope.opt?.code }} -
+ {{ scope.opt?.description }}
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
-en:
- searchInvoice: Search issued invoice
- fileDenied: Browser denied file download...
- fileAllowed: Successful download of CSV file
- youCanSearchByInvoiceReference: You can search by invoice reference
- createInvoice: Make invoice
- Create manual invoice: Create manual invoice
-es:
- searchInvoice: Buscar factura emitida
- fileDenied: El navegador denegó la descarga de archivos...
- fileAllowed: Descarga exitosa de archivo CSV
- youCanSearchByInvoiceReference: Puedes buscar por referencia de la factura
- createInvoice: Crear factura
- Create manual invoice: Crear factura manual
+ en:
+ invoiceId: Invoice ID
+ youCanSearchByInvoiceReference: You can search by invoice reference
+ createManualInvoice: Create Manual Invoice
+ inactive: (Inactive)
+
+ es:
+ invoiceId: ID de factura
+ youCanSearchByInvoiceReference: Puedes buscar por referencia de la factura
+ createManualInvoice: Crear factura manual
+ inactive: (Inactivo)
diff --git a/src/pages/InvoiceOut/locale/en.yml b/src/pages/InvoiceOut/locale/en.yml
index 5ad92ed0973..8cefe8bdca8 100644
--- a/src/pages/InvoiceOut/locale/en.yml
+++ b/src/pages/InvoiceOut/locale/en.yml
@@ -2,6 +2,7 @@ invoiceOutModule:
customer: Client
amount: Amount
company: Company
+ address: Address
invoiceOutList:
tableVisibleColumns:
id: ID
@@ -15,11 +16,11 @@ invoiceOutList:
DownloadPdf: Download PDF
InvoiceOutSummary: Summary
negativeBases:
- country: Country
- clientId: Client ID
- base: Base
- ticketId: Ticket
- active: Active
- hasToInvoice: Has to invoice
- verifiedData: Verified data
- commercial: Commercial
\ No newline at end of file
+ country: Country
+ clientId: Client ID
+ base: Base
+ ticketId: Ticket
+ active: Active
+ hasToInvoice: Has to invoice
+ verifiedData: Verified data
+ commercial: Commercial
diff --git a/src/pages/InvoiceOut/locale/es.yml b/src/pages/InvoiceOut/locale/es.yml
index 192f5b26fd9..106168a5d70 100644
--- a/src/pages/InvoiceOut/locale/es.yml
+++ b/src/pages/InvoiceOut/locale/es.yml
@@ -4,13 +4,14 @@ invoiceOutModule:
customer: Cliente
amount: Importe
company: Empresa
+ address: Consignatario
invoiceOutList:
tableVisibleColumns:
id: ID
ref: Referencia
issued: Fecha emisión
created: F. creación
- dueDate: F. máxima
+ dueDate: Fecha vencimiento
invoiceOutSerial: Serial
ticket: Ticket
taxArea: Area
diff --git a/src/pages/Item/Card/ItemBarcode.vue b/src/pages/Item/Card/ItemBarcode.vue
index 197e9142f0f..6db5943c77b 100644
--- a/src/pages/Item/Card/ItemBarcode.vue
+++ b/src/pages/Item/Card/ItemBarcode.vue
@@ -2,12 +2,15 @@
import { ref, nextTick } from 'vue';
import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
+import axios from 'axios';
import CrudModel from 'src/components/CrudModel.vue';
import VnInput from 'src/components/common/VnInput.vue';
+import useNotify from 'src/composables/useNotify.js';
const route = useRoute();
const { t } = useI18n();
+const { notify } = useNotify();
const itemBarcodeRef = ref(null);
@@ -23,6 +26,24 @@ const focusLastInput = () => {
if (lastInput) lastInput.focus();
});
};
+
+const removeRow = (row) => {
+ itemBarcodeRef.value.remove([row]);
+};
+
+const submit = async (rows) => {
+ const params = rows[rows.length - 1];
+ let { data } = await axios.get('ItemBarcodes');
+ const code = params.code;
+
+ if (data.some((codes) => codes.code === code)) {
+ notify(t('Codes can not be repeated'), 'negative');
+ itemBarcodeRef.value.reset();
+ return;
+ }
+ await axios.patch(`ItemBarcodes`, params);
+ notify(t('globals.dataSaved'), 'positive');
+};
@@ -39,6 +60,7 @@ const focusLastInput = () => {
ref="itemBarcodeRef"
url="ItemBarcodes"
auto-load
+ :save-fn="submit"
>
@@ -54,7 +76,7 @@ const focusLastInput = () => {
focusable-input
/>
diff --git a/src/pages/Item/Card/ItemBasicData.vue b/src/pages/Item/Card/ItemBasicData.vue
index 1b0342668cc..a1788617fdc 100644
--- a/src/pages/Item/Card/ItemBasicData.vue
+++ b/src/pages/Item/Card/ItemBasicData.vue
@@ -70,6 +70,7 @@ const onIntrastatCreated = (response, formData) => {
option-label="name"
hide-selected
map-options
+ required
>
diff --git a/src/pages/Item/Card/ItemBotanical.vue b/src/pages/Item/Card/ItemBotanical.vue
index c4b56177259..57774f75ed0 100644
--- a/src/pages/Item/Card/ItemBotanical.vue
+++ b/src/pages/Item/Card/ItemBotanical.vue
@@ -1,5 +1,5 @@
-
@@ -192,27 +202,43 @@ onUnmounted(() => (stateStore.rightDrawer = false));
dense
v-model="from"
class="q-mr-lg"
+ data-cy="from"
+ />
+
-
-
-
+
+
+
+ {{ row.warehouse }}
+
+
+
+
+
+
+
@@ -221,32 +247,37 @@ onUnmounted(() => (stateStore.rightDrawer = false));
+
+
+ {{ value }}
+ {{ t('lastEntries.grouping') }}/Packing
+
+
+
+
+ {{ row.printedStickers }}
+
+
{{ dashIfEmpty(row.packing) }}
- {{ t('lastEntries.packing') }}
+ Packing
-
- {{ value }}
-
- {{ t('lastEntries.grouping') }}/{{ t('lastEntries.packing') }}
-
-
{{ dashIfEmpty(row.grouping) }}
{{ t('lastEntries.grouping') }}
@@ -254,7 +285,7 @@ onUnmounted(() => (stateStore.rightDrawer = false));
-
+
{{ toCurrency(row.cost, 'EUR', 3) }}
@@ -272,10 +303,28 @@ onUnmounted(() => (stateStore.rightDrawer = false));
+
+
+
+
+
+ {{ row.supplier }}
+
+
+
+
-
+
+ es:
+ Hide inventory supplier: Ocultar proveedor inventario
+
diff --git a/src/pages/Item/Card/ItemShelving.vue b/src/pages/Item/Card/ItemShelving.vue
index 27e265e6b73..7ad60c9e0c6 100644
--- a/src/pages/Item/Card/ItemShelving.vue
+++ b/src/pages/Item/Card/ItemShelving.vue
@@ -1,19 +1,15 @@
@@ -203,7 +152,7 @@ onMounted(async () => {
{
-
-
-
-
-
-
-
-
-
-
-
- {{ row.longName }}
+
+
+ {{ row.longName }}
-
+
-
+
diff --git a/src/pages/Item/Card/ItemSummary.vue b/src/pages/Item/Card/ItemSummary.vue
index db90ba06f7c..e1b97d7c994 100644
--- a/src/pages/Item/Card/ItemSummary.vue
+++ b/src/pages/Item/Card/ItemSummary.vue
@@ -46,7 +46,7 @@ const getUrl = (id, param) => `#/Item/${id}/${param}`;
`#/Item/${id}/${param}`;
{
itemTagsRef.value.formData[itemTagsRef.value.formData.length - 1].priority =
getHighestPriority(rows);
};
+
+const submitTags = async (data) => {
+ itemTagsRef.value.onSubmit(data);
+};
(tagOptions = data)"
auto-load
/>
@@ -76,7 +80,6 @@ const insertTag = (rows) => {
data-key="ItemTags"
model="ItemTags"
url="ItemTags"
- update-url="Tags/onSubmit"
:data-required="{
$index: undefined,
itemFk: route.params.id,
@@ -125,7 +128,7 @@ const insertTag = (rows) => {
{
:required="false"
:rules="validate('itemTag.tagFk')"
:use-like="false"
+ sort-by="value"
/>
{
v-model="row.priority"
:required="true"
:rules="validate('itemTag.priority')"
+ @keyup.enter.stop="submitTags(row)"
/>
{
+
+
+es:
+ Tags can not be repeated: Las etiquetas no pueden repetirse
+
diff --git a/src/pages/Item/Card/ItemTax.vue b/src/pages/Item/Card/ItemTax.vue
index 84b5f63f49c..8060481f0f7 100644
--- a/src/pages/Item/Card/ItemTax.vue
+++ b/src/pages/Item/Card/ItemTax.vue
@@ -28,7 +28,7 @@ const taxesFilter = {
],
};
-const ItemTaxRef = ref(null);
+const ItemTaxRef = ref();
const taxesOptions = ref([]);
const submitTaxes = async (data) => {
@@ -36,7 +36,10 @@ const submitTaxes = async (data) => {
id: tax.id,
taxClassFk: tax.taxClassFk,
}));
-
+ if (payload.some((item) => item.taxClassFk === null)) {
+ notify(t('Tax class cannot be blank'), 'negative');
+ return;
+ }
await axios.post(`Items/updateTaxes`, payload);
notify(t('globals.dataSaved'), 'positive');
};
diff --git a/src/pages/Item/ItemFixedPrice.vue b/src/pages/Item/ItemFixedPrice.vue
index 8bf5d33bdca..37490b35fbc 100644
--- a/src/pages/Item/ItemFixedPrice.vue
+++ b/src/pages/Item/ItemFixedPrice.vue
@@ -1,5 +1,5 @@
+
+
+
+
+
{
:columns="columns"
:user-params="userParams"
:is-editable="true"
+ :right-search="false"
auto-load
:disable-option="{ card: true }"
chip-locale="item.params"
@@ -297,39 +291,40 @@ onMounted(async () => {
handleScopeDays(evt.target.value)"
@remove="handleScopeDays()"
class="q-px-xs q-pr-lg"
filled
dense
+ lazy-rules
+ is-outlined
/>
+
-
-
-
- {{ row.response }}
-
-
-
-
- {{ t('Discard') }}
-
-
-
+
+
+ {{ row.response }}
+
+
+
+
+ {{ t('Discard') }}
+
+
diff --git a/src/pages/Item/ItemRequestFilter.vue b/src/pages/Item/ItemRequestFilter.vue
index 64bc0e57596..f23cadcad52 100644
--- a/src/pages/Item/ItemRequestFilter.vue
+++ b/src/pages/Item/ItemRequestFilter.vue
@@ -1,12 +1,13 @@
@@ -79,8 +80,7 @@ const decrement = (paramsObj, key) => {
{{ t(`params.${tag.label}`) }}:
- {{ formatFn(tag.value) }}
- {{ t(`${tag.value}`) }}
+ {{ formatFn(tag.value) }}
@@ -145,109 +145,16 @@ const decrement = (paramsObj, key) => {
-
-
-
-
- {{ scope.opt?.name }}
- {{ scope.opt?.nickname }},
- {{ scope.opt?.code }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ t('dateFiltersTooltip') }}
-
-
-
-
-
-
@@ -267,6 +174,16 @@ const decrement = (paramsObj, key) => {
/>
+
+
+
+
+
@@ -284,6 +201,7 @@ en:
to: To
mine: For me
state: State
+ daysOnward: Days onward
myTeam: My team
dateFiltersTooltip: Cannot choose a range of dates and days onward at the same time
denied: Denied
@@ -301,6 +219,7 @@ es:
to: Hasta
mine: Para mi
state: Estado
+ daysOnward: Días en adelante
myTeam: Mi equipo
dateFiltersTooltip: No se puede seleccionar un rango de fechas y días en adelante a la vez
denied: Denegada
diff --git a/src/pages/Item/ItemType/Card/ItemTypeSummary.vue b/src/pages/Item/ItemType/Card/ItemTypeSummary.vue
index c51d59e137b..9ba774ca462 100644
--- a/src/pages/Item/ItemType/Card/ItemTypeSummary.vue
+++ b/src/pages/Item/ItemType/Card/ItemTypeSummary.vue
@@ -78,29 +78,32 @@ async function setItemTypeData(data) {
{{ t('globals.summary.basicData') }}
-
-
-
-
+
+
+
+
{{ itemType.worker?.firstName }}
-
+
-
-
+
+
diff --git a/src/pages/Item/ItemType/ItemTypeSearchbar.vue b/src/pages/Item/ItemType/ItemTypeSearchbar.vue
index 87903a517aa..749033d435d 100644
--- a/src/pages/Item/ItemType/ItemTypeSearchbar.vue
+++ b/src/pages/Item/ItemType/ItemTypeSearchbar.vue
@@ -10,7 +10,6 @@ const { t } = useI18n();
url="ItemTypes"
:label="t('Search item type')"
:info="t('Search itemType by id, name or code')"
- search-url="table"
/>
diff --git a/src/pages/Item/ItemType/locale/en.yml b/src/pages/Item/ItemType/locale/en.yml
index 575d5e40277..99c6791f2ed 100644
--- a/src/pages/Item/ItemType/locale/en.yml
+++ b/src/pages/Item/ItemType/locale/en.yml
@@ -1,16 +1,17 @@
-shared:
- code: Code
- name: Name
- worker: Worker
- category: Category
- temperature: Temperature
- life: Life
- itemPackingType: Item packing type
- maxRefs: Maximum references
- fragile: Fragile
-summary:
- id: id
- life: Life
- promo: Promo
- itemPackingType: Item packing type
- isUnconventionalSize: Is unconventional size
+itemType:
+ shared:
+ code: Code
+ name: Name
+ worker: Worker
+ category: Category
+ temperature: Temperature
+ life: Life
+ itemPackingType: Item packing type
+ maxRefs: Maximum references
+ fragile: Fragile
+ summary:
+ id: id
+ life: Life
+ promo: Promo
+ itemPackingType: Item packing type
+ isUnconventionalSize: Is unconventional size
diff --git a/src/pages/Item/ItemType/locale/es.yml b/src/pages/Item/ItemType/locale/es.yml
index 93f8b0d0e0a..c91fb405833 100644
--- a/src/pages/Item/ItemType/locale/es.yml
+++ b/src/pages/Item/ItemType/locale/es.yml
@@ -1,16 +1,17 @@
-shared:
- code: Código
- name: Nombre
- worker: Trabajador
- category: Reino
- temperature: Temperatura
- life: Vida
- itemPackingType: Tipo de embalaje
- maxRefs: Referencias máximas
- fragile: Frágil
-summary:
- id: id
- life: Vida
- promo: Promoción
- itemPackingType: Tipo de embalaje
- isUnconventionalSize: Es de tamaño poco convencional
+itemType:
+ shared:
+ code: Código
+ name: Nombre
+ worker: Trabajador
+ category: Reino
+ temperature: Temperatura
+ life: Vida
+ itemPackingType: Tipo de embalaje
+ maxRefs: Referencias máximas
+ fragile: Frágil
+ summary:
+ id: id
+ life: Vida
+ promo: Promoción
+ itemPackingType: Tipo de embalaje
+ isUnconventionalSize: Es de tamaño poco convencional
diff --git a/src/pages/Item/ItemTypeList.vue b/src/pages/Item/ItemTypeList.vue
index 149de482d5b..4cea931e285 100644
--- a/src/pages/Item/ItemTypeList.vue
+++ b/src/pages/Item/ItemTypeList.vue
@@ -6,6 +6,7 @@ import VnTable from 'components/VnTable/VnTable.vue';
import FetchData from 'components/FetchData.vue';
import RightMenu from 'src/components/common/RightMenu.vue';
import ItemTypeFilter from './ItemType/ItemTypeFilter.vue';
+import WorkerDescriptorProxy from '../Worker/Card/WorkerDescriptorProxy.vue';
const { t } = useI18n();
const tableRef = ref();
@@ -31,13 +32,14 @@ const columns = computed(() => [
{
align: 'left',
name: 'name',
- label: t('name'),
+ label: t('globals.name'),
cardVisible: true,
create: true,
},
{
align: 'left',
label: t('worker'),
+ name: 'workerFk',
create: true,
component: 'select',
attrs: {
@@ -45,20 +47,20 @@ const columns = computed(() => [
optionLabel: 'nickname',
optionValue: 'id',
},
+ format: (row) => row.worker?.user?.name,
cardVisible: true,
- visible: true,
- columnField: {
- component: 'userLink',
- attrs: ({ row }) => {
- return {
- workerId: row?.worker?.id,
- name: row.worker?.user?.name,
- defaultName: true,
- };
- },
- },
+ columnField: { component: null },
columnFilter: {
- name: 'workerFk',
+ attrs: {
+ url: 'Workers/activeWithInheritedRole',
+ fields: ['id', 'name'],
+ where: { role: 'buyer' },
+ optionFilter: 'firstName',
+ optionLabel: 'name',
+ optionValue: 'id',
+ useLike: false,
+ },
+ inWhere: true,
},
},
{
@@ -135,24 +137,27 @@ const columns = computed(() => [
:columns="columns"
auto-load
:right-search="false"
- :is-editable="false"
- :use-model="true"
redirect="item/item-type"
- />
+ >
+
+
+ {{ row.worker?.user?.name }}
+
+
+
+
es:
id: Id
code: Código
- name: Nombre
worker: Trabajador
ItemCategory: Reino
Temperature: Temperatura
Create ItemTypes: Crear familia
en:
code: Code
- name: Name
worker: Worker
ItemCategory: ItemCategory
Temperature: Temperature
diff --git a/src/pages/Item/locale/en.yml b/src/pages/Item/locale/en.yml
index 78a1c3ff069..bd91ef745b9 100644
--- a/src/pages/Item/locale/en.yml
+++ b/src/pages/Item/locale/en.yml
@@ -66,6 +66,7 @@ lastEntries:
package: Package
freight: Freight
comission: Comission
+ printedStickers: Pri.
itemTags:
removeTag: Remove tag
addTag: Add tag
@@ -95,6 +96,15 @@ item:
mine: For me
state: State
myTeam: My team
+ shipped: Shipped
+ description: Description
+ quantity: Quantity
+ price: Price
+ item: Item
+ achieved: Achieved
+ concept: Concept
+ denyOptions: Deny
+ scopeDays: Scope days
searchbar:
label: Search item
descriptor:
@@ -112,7 +122,7 @@ item:
title: All its properties will be copied
subTitle: Do you want to clone this item?
list:
- id: Identifier
+ id: Id
grouping: Grouping
packing: Packing
description: Description
@@ -122,8 +132,9 @@ item:
intrastat: Intrastat
isActive: Active
size: Size
- origin: Origin
+ origin: Orig.
userName: Buyer
+ weight: Weight
weightByPiece: Weight/Piece
stemMultiplier: Multiplier
producer: Producer
diff --git a/src/pages/Item/locale/es.yml b/src/pages/Item/locale/es.yml
index 5498f445820..b821d276a69 100644
--- a/src/pages/Item/locale/es.yml
+++ b/src/pages/Item/locale/es.yml
@@ -56,7 +56,7 @@ lastEntries:
landed: F. Entrega
entry: Entrada
pvp: PVP
- label: Etiquetas
+ label: Eti.
grouping: Grouping
quantity: Cantidad
cost: Coste
@@ -66,6 +66,7 @@ lastEntries:
package: Embalaje
freight: Porte
comission: Comisión
+ printedStickers: Imp.
itemTags:
removeTag: Quitar etiqueta
addTag: Añadir etiqueta
@@ -97,6 +98,15 @@ item:
mine: Para mi
state: Estado
myTeam: Mi equipo
+ shipped: Enviado
+ description: Descripción
+ quantity: Cantidad
+ price: Precio
+ item: Artículo
+ achieved: Conseguido
+ concept: Concepto
+ denyOptions: Denegado
+ scopeDays: Días en adelante
searchbar:
label: Buscar artículo
descriptor:
@@ -114,7 +124,7 @@ item:
title: Todas sus propiedades serán copiadas
subTitle: ¿Desea clonar este artículo?
list:
- id: Identificador
+ id: Id
grouping: Grouping
packing: Packing
description: Descripción
@@ -124,7 +134,8 @@ item:
intrastat: Intrastat
isActive: Activo
size: Medida
- origin: Origen
+ origin: Orig.
+ weight: Peso
weightByPiece: Peso (gramos)/tallo
userName: Comprador
stemMultiplier: Multiplicador
diff --git a/src/pages/Monitor/Ticket/MonitorTicketFilter.vue b/src/pages/Monitor/Ticket/MonitorTicketFilter.vue
index 3247da014f0..82578a61fbe 100644
--- a/src/pages/Monitor/Ticket/MonitorTicketFilter.vue
+++ b/src/pages/Monitor/Ticket/MonitorTicketFilter.vue
@@ -9,6 +9,7 @@ import VnInput from 'src/components/common/VnInput.vue';
import VnInputNumber from 'src/components/common/VnInputNumber.vue';
import FetchData from 'src/components/FetchData.vue';
import { dateRange } from 'src/filters';
+import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
defineProps({ dataKey: { type: String, required: true } });
const { t, te } = useI18n();
@@ -59,7 +60,11 @@ const getLocale = (label) => {
@@ -108,33 +113,16 @@ const getLocale = (label) => {
-
-
-
-
- {{ opt.name }}
-
- {{ `${opt.nickname}, ${opt.code}` }}
-
-
-
-
-
+
@@ -146,6 +134,7 @@ const getLocale = (label) => {
/>
+
{
/>
+
+
+
+
+
{
/>
+
+
+
+
+
+
+
+
+
+
-import { ref, computed } from 'vue';
+import { ref, computed, onMounted } from 'vue';
import { useI18n } from 'vue-i18n';
import FetchData from 'components/FetchData.vue';
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
@@ -10,22 +10,39 @@ import ZoneDescriptorProxy from 'src/pages/Zone/Card/ZoneDescriptorProxy.vue';
import TicketSummary from 'src/pages/Ticket/Card/TicketSummary.vue';
import VnTable from 'components/VnTable/VnTable.vue';
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
-import { toDateFormat } from 'src/filters/date.js';
import { toCurrency, dateRange, dashIfEmpty } from 'src/filters';
import RightMenu from 'src/components/common/RightMenu.vue';
import MonitorTicketSearchbar from './MonitorTicketSearchbar.vue';
import MonitorTicketFilter from './MonitorTicketFilter.vue';
+import TicketProblems from 'src/components/TicketProblems.vue';
+import VnDateBadge from 'src/components/common/VnDateBadge.vue';
+import { useStateStore } from 'src/stores/useStateStore';
-const DEFAULT_AUTO_REFRESH = 2 * 60 * 1000; // 2min in ms
+const DEFAULT_AUTO_REFRESH = 2 * 60 * 1000;
const { t } = useI18n();
const autoRefresh = ref(false);
const tableRef = ref(null);
const provinceOpts = ref([]);
const stateOpts = ref([]);
const zoneOpts = ref([]);
-const visibleColumns = ref([]);
+const DepartmentOpts = ref([]);
+const PayMethodOpts = ref([]);
+const ItemPackingTypeOpts = ref([]);
+const stateStore = useStateStore();
const { viewSummary } = useSummaryDialog();
+
const [from, to] = dateRange(Date.vnNew());
+const stateColors = {
+ notice: 'info',
+ success: 'positive',
+ warning: 'warning',
+ alert: 'negative',
+};
+
+onMounted(() => {
+ stateStore.leftDrawer = false;
+ stateStore.rightDrawer = false;
+});
function exprBuilder(param, value) {
switch (param) {
@@ -44,6 +61,8 @@ function exprBuilder(param, value) {
case 'nickname':
return { [`t.nickname`]: { like: `%${value}%` } };
case 'zoneFk':
+ case 'department':
+ return { 'd.name': value };
case 'totalWithVat':
return { [`t.${param}`]: value };
}
@@ -130,6 +149,7 @@ const columns = computed(() => [
align: 'left',
format: (row) => row.practicalHour,
columnFilter: false,
+ dense: true,
},
{
label: t('salesTicketsTable.preparation'),
@@ -183,6 +203,7 @@ const columns = computed(() => [
'false-value': 0,
'true-value': 1,
},
+ component: false,
},
{
label: t('salesTicketsTable.zone'),
@@ -199,6 +220,21 @@ const columns = computed(() => [
},
},
},
+ {
+ label: t('salesTicketsTable.payMethod'),
+ name: 'payMethod',
+ align: 'left',
+ columnFilter: {
+ component: 'select',
+ url: 'PayMethods',
+ attrs: {
+ options: PayMethodOpts.value,
+ optionValue: 'id',
+ optionLabel: 'name',
+ dense: true,
+ },
+ },
+ },
{
label: t('salesTicketsTable.total'),
name: 'totalWithVat',
@@ -212,6 +248,33 @@ const columns = computed(() => [
},
},
},
+ {
+ label: t('salesTicketsTable.department'),
+ name: 'department',
+ align: 'left',
+ columnFilter: {
+ component: 'select',
+ attrs: {
+ options: DepartmentOpts.value,
+ dense: true,
+ },
+ },
+ },
+ {
+ label: t('salesTicketsTable.packing'),
+ name: 'packing',
+ align: 'left',
+ columnFilter: {
+ component: 'select',
+ url: 'ItemPackingTypes',
+ attrs: {
+ options: ItemPackingTypeOpts.value,
+ 'option-value': 'code',
+ 'option-label': 'code',
+ dense: true,
+ },
+ },
+ },
{
align: 'right',
name: 'tableActions',
@@ -220,7 +283,7 @@ const columns = computed(() => [
{
title: t('salesTicketsTable.goToLines'),
icon: 'vn:lines',
- color: 'priamry',
+ color: 'primary',
action: (row) => openTab(row.id),
isPrimary: true,
attrs: {
@@ -231,7 +294,7 @@ const columns = computed(() => [
{
title: t('salesTicketsTable.preview'),
icon: 'preview',
- color: 'priamry',
+ color: 'primary',
action: (row) => viewSummary(row.id, TicketSummary),
isPrimary: true,
attrs: {
@@ -243,19 +306,6 @@ const columns = computed(() => [
},
]);
-const getBadgeAttrs = (date) => {
- let today = Date.vnNew();
- today.setHours(0, 0, 0, 0);
- let timeTicket = new Date(date);
- timeTicket.setHours(0, 0, 0, 0);
-
- let comparation = today - timeTicket;
-
- if (comparation == 0) return { color: 'warning', 'text-color': 'black' };
- if (comparation < 0) return { color: 'success', 'text-color': 'black' };
- return { color: 'transparent', 'text-color': 'white' };
-};
-
let refreshTimer = null;
const autoRefreshHandler = (value) => {
@@ -267,26 +317,11 @@ const autoRefreshHandler = (value) => {
}
};
-const stateColors = {
- notice: 'info',
- success: 'positive',
- warning: 'warning',
- alert: 'negative',
-};
-
const totalPriceColor = (ticket) => {
const total = parseInt(ticket.totalWithVat);
if (total > 0 && total < 50) return 'warning';
};
-const formatShippedDate = (date) => {
- if (!date) return '-';
- const split1 = date.split('T');
- const [year, month, day] = split1[0].split('-');
- const _date = new Date(year, month - 1, day);
- return toDateFormat(_date);
-};
-
const openTab = (id) =>
window.open(`#/ticket/${id}/sale`, '_blank', 'noopener, noreferrer');
@@ -318,6 +353,33 @@ const openTab = (id) =>
auto-load
@on-fetch="(data) => (zoneOpts = data)"
/>
+ (ItemPackingTypeOpts = data)"
+ />
+ (DepartmentOpts = data)"
+ />
+ (PayMethodOpts = data)"
+ />
@@ -332,7 +394,6 @@ const openTab = (id) =>
:expr-builder="exprBuilder"
:offset="50"
:columns="columns"
- :visible-columns="visibleColumns"
:right-search="false"
default-mode="table"
auto-load
@@ -362,61 +423,7 @@ const openTab = (id) =>
-
-
- {{ $t('salesTicketsTable.noVerifiedData') }}
-
-
- {{ $t('salesTicketsTable.purchaseRequest') }}
-
-
- {{ $t('salesTicketsTable.notVisible') }}
-
-
- {{ $t('salesTicketsTable.clientFrozen') }}
-
-
- {{ $t('salesTicketsTable.risk') }}: {{ row.risk }}
-
-
- {{ $t('salesTicketsTable.componentLack') }}
-
-
- {{ $t('salesTicketsTable.tooLittle') }}
-
-
+
@@ -437,13 +444,7 @@ const openTab = (id) =>
-
- {{ formatShippedDate(row.shippedDate) }}
-
+
@@ -471,7 +472,7 @@ const openTab = (id) =>
-
+
{{ row.zoneName }}
diff --git a/src/pages/Monitor/locale/en.yml b/src/pages/Monitor/locale/en.yml
index ff4031654ef..e61a249797f 100644
--- a/src/pages/Monitor/locale/en.yml
+++ b/src/pages/Monitor/locale/en.yml
@@ -26,8 +26,8 @@ salesTicketsTable:
componentLack: Component lack
tooLittle: Ticket too little
identifier: Identifier
- theoretical: Theoretical
- practical: Practical
+ theoretical: H.Theor
+ practical: H.Prac
province: Province
state: State
isFragile: Is fragile
@@ -35,7 +35,10 @@ salesTicketsTable:
goToLines: Go to lines
preview: Preview
total: Total
- preparation: Preparation
+ preparation: H.Prep
+ payMethod: Pay method
+ department: Department
+ packing: ITP
searchBar:
label: Search tickets
info: Search tickets by id or alias
diff --git a/src/pages/Monitor/locale/es.yml b/src/pages/Monitor/locale/es.yml
index a2ed3bb1aec..30afb1904ba 100644
--- a/src/pages/Monitor/locale/es.yml
+++ b/src/pages/Monitor/locale/es.yml
@@ -26,8 +26,8 @@ salesTicketsTable:
componentLack: Faltan componentes
tooLittle: Ticket demasiado pequeño
identifier: Identificador
- theoretical: Teórica
- practical: Práctica
+ theoretical: H.Teór
+ practical: H.Prác
province: Provincia
state: Estado
isFragile: Es frágil
@@ -35,7 +35,10 @@ salesTicketsTable:
goToLines: Ir a líneas
preview: Vista previa
total: Total
- preparation: Preparación
+ preparation: H.Prep
+ payMethod: Método de pago
+ department: Departamento
+ packing: ITP
searchBar:
label: Buscar tickets
info: Buscar tickets por identificador o alias
diff --git a/src/pages/Order/Card/CatalogFilterValueDialog.vue b/src/pages/Order/Card/CatalogFilterValueDialog.vue
index 53bb87f8d50..b91e7d229bf 100644
--- a/src/pages/Order/Card/CatalogFilterValueDialog.vue
+++ b/src/pages/Order/Card/CatalogFilterValueDialog.vue
@@ -49,7 +49,7 @@ const getSelectedTagValues = async (tag) => {
-
+
{
:emit-value="false"
use-input
@update:model-value="getSelectedTagValues"
+ data-cy="catalogFilterValueDialogTagSelect"
/>
{
:disable="!value"
is-outlined
class="col"
+ data-cy="catalogFilterValueDialogValueInput"
/>
import { useStateStore } from 'stores/useStateStore';
import { useRoute, useRouter } from 'vue-router';
-import { onMounted, onUnmounted, ref, computed, watch } from 'vue';
+import { onMounted, ref, computed, watch } from 'vue';
import axios from 'axios';
import { useI18n } from 'vue-i18n';
import VnPaginate from 'src/components/ui/VnPaginate.vue';
@@ -18,6 +18,7 @@ const dataKey = 'OrderCatalogList';
const arrayData = useArrayData(dataKey);
const store = arrayData.store;
const tags = ref([]);
+const itemRefs = ref({});
let catalogParams = {
orderFk: route.params.id,
@@ -29,8 +30,6 @@ onMounted(() => {
checkOrderConfirmation();
});
-onUnmounted(() => (stateStore.rightDrawer = false));
-
async function checkOrderConfirmation() {
const response = await axios.get(`Orders/${route.params.id}`);
if (response.data.isConfirmed === 1) {
@@ -87,18 +86,17 @@ watch(
url="Orders/CatalogFilter"
:label="t('Search items')"
:info="t('You can search items by name or id')"
+ :search-remove-params="false"
/>
-
-
-
-
-
-
+
+
+
+
diff --git a/src/pages/Order/Card/OrderCatalogFilter.vue b/src/pages/Order/Card/OrderCatalogFilter.vue
index 6202a6f903a..39627595d5a 100644
--- a/src/pages/Order/Card/OrderCatalogFilter.vue
+++ b/src/pages/Order/Card/OrderCatalogFilter.vue
@@ -65,7 +65,6 @@ const selectCategory = async (params, category, search) => {
params.typeFk = null;
params.categoryFk = category.id;
await loadTypes(category?.id);
- await search();
};
const loadTypes = async (id) => {
@@ -178,6 +177,7 @@ function addOrder(value, field, params) {
? resetCategory(params, searchFn)
: removeTagGroupParam(params, searchFn, valIndex)
"
+ data-cy="catalogFilterCustomTag"
>
{{
@@ -211,6 +211,7 @@ function addOrder(value, field, params) {
:name="category.icon"
class="category-icon"
@click="selectCategory(params, category, searchFn)"
+ data-cy="catalogFilterCategory"
>
{{ t(category.name) }}
@@ -234,6 +235,7 @@ function addOrder(value, field, params) {
sort-by="name ASC"
:disable="!params.categoryFk"
@update:model-value="searchFn()"
+ data-cy="catalogFilterType"
>
@@ -285,6 +287,7 @@ function addOrder(value, field, params) {
:is-clearable="false"
v-model="searchByTag"
@keyup.enter="(val) => onSearchByTag(val, params)"
+ data-cy="catalogFilterValueInput"
>
@@ -297,6 +300,7 @@ function addOrder(value, field, params) {
color="primary"
size="md"
dense
+ data-cy="catalogFilterValueDialogBtn"
/>
-import toCurrency from '../../../filters/toCurrency';
-import { ref } from 'vue';
+import toCurrency from 'src/filters/toCurrency';
+import { computed, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import axios from 'axios';
import { useRoute } from 'vue-router';
import useNotify from 'composables/useNotify';
-import { useArrayData } from 'composables/useArrayData';
+import VnInputNumber from 'src/components/common/VnInputNumber.vue';
+import { useState } from 'src/composables/useState';
const { t } = useI18n();
const { notify } = useNotify();
const emit = defineEmits(['added']);
const route = useRoute();
const props = defineProps({
- prices: {
+ item: {
type: Array,
required: true,
},
});
+const state = useState();
-const fields = ref((props.prices || []).map((item) => ({ ...item, quantity: 0 })));
-const descriptorData = useArrayData('orderData');
+const orderData = computed(() => state.get('orderData'));
+
+const prices = ref((props.item.prices || []).map((item) => ({ ...item, quantity: 0 })));
const isLoading = ref(false);
+
+const totalQuantity = (items) =>
+ items.reduce((acc, item) => {
+ return acc + item.quantity;
+ }, 0);
const addToOrder = async () => {
if (isLoading.value) return;
isLoading.value = true;
- const items = (fields.value || []).filter((item) => Number(item.quantity) > 0);
+ const items = (prices.value || []).filter((item) => Number(item.quantity) > 0);
await axios.post('/OrderRows/addToOrder', {
items,
orderFk: Number(route.params.id),
});
+
+ const { data: orderTotal } = await axios.get(
+ `Orders/${Number(route.params.id)}/getTotal`
+ );
+
+ state.set('orderTotal', orderTotal);
+ const rows = orderData.value.rows.push(...items) || [];
+ state.set('orderData', {
+ ...orderData.value,
+ rows,
+ });
notify(t('globals.dataSaved'), 'positive');
- emit('added');
- descriptorData.fetch({});
+ emit('added', -totalQuantity(items));
isLoading.value = false;
};
const canAddToOrder = () => {
- return (fields.value || []).some((item) => Number(item.quantity) > 0);
+ let canAddToOrder = (prices.value || []).some((price) => Number(price.quantity) > 0);
+ if (canAddToOrder) {
+ const excedQuantity = prices.value.reduce(
+ (acc, { quantity }) => acc + quantity,
+ 0
+ );
+ if (excedQuantity > props.item.available) {
+ canAddToOrder = false;
+ }
+ }
+ return canAddToOrder;
};
@@ -44,30 +72,33 @@ const canAddToOrder = () => {
-
+
- {{ item.warehouse }}
+ {{ price.warehouse }}
|
{
- item.quantity += item.grouping;
+ price.quantity -= price.grouping;
+ }
+ "
+ @click.exact="
+ () => {
+ price.quantity += price.grouping;
}
"
>
- {{ item.grouping }}
+ {{ price.grouping }}
- x {{ toCurrency(item.price) }}
+ x {{ toCurrency(price.price) }}
|
-
|
diff --git a/src/pages/Order/Card/OrderCreateDialog.vue b/src/pages/Order/Card/OrderCreateDialog.vue
index 3f6cc914b5e..9a53b9e308e 100644
--- a/src/pages/Order/Card/OrderCreateDialog.vue
+++ b/src/pages/Order/Card/OrderCreateDialog.vue
@@ -1,40 +1,21 @@
@@ -128,10 +64,9 @@ onMounted(async () => {
option-value="id"
option-label="name"
:filter="{
- fields: ['id', 'name', 'defaultAddressFk'],
+ fields: ['id', 'name'],
}"
hide-selected
- @update:model-value="onClientChange"
>
@@ -148,7 +83,7 @@ onMounted(async () => {
:label="t('order.form.addressFk')"
v-model="data.addressId"
url="addresses"
- :fields="['id', 'nickname', 'defaultAddressFk', 'street', 'city']"
+ :fields="['id', 'nickname', 'street', 'city']"
sort-by="id"
option-value="id"
option-label="street"
diff --git a/src/pages/Order/Card/OrderDescriptor.vue b/src/pages/Order/Card/OrderDescriptor.vue
index 138fcc40f33..e0c613aedc1 100644
--- a/src/pages/Order/Card/OrderDescriptor.vue
+++ b/src/pages/Order/Card/OrderDescriptor.vue
@@ -63,21 +63,26 @@ const setData = (entity) => {
if (!entity) return;
getTotalRef.value && getTotalRef.value.fetch();
data.value = useCardDescription(entity?.client?.name, entity?.id);
- state.set('orderData', entity);
+ state.set('orderTotal', total);
};
const getConfirmationValue = (isConfirmed) => {
return t(isConfirmed ? 'globals.confirmed' : 'order.summary.notConfirmed');
};
-const total = ref(null);
+const orderTotal = computed(() => state.get('orderTotal') ?? 0);
+const total = ref(0);
(total = response)"
+ @on-fetch="
+ (response) => {
+ total = response;
+ }
+ "
/>
-
+
diff --git a/src/pages/Order/Card/OrderFilter.vue b/src/pages/Order/Card/OrderFilter.vue
index 9173699191b..fcd1ef2e4ad 100644
--- a/src/pages/Order/Card/OrderFilter.vue
+++ b/src/pages/Order/Card/OrderFilter.vue
@@ -6,6 +6,7 @@ import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
import VnSelect from 'components/common/VnSelect.vue';
import VnInputDate from 'components/common/VnInputDate.vue';
import VnInput from 'components/common/VnInput.vue';
+import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
const { t } = useI18n();
const props = defineProps({
@@ -61,28 +62,16 @@ const sourceList = ref([]);
outlined
rounded
/>
-
-
-
-
- {{ opt.name }}
-
- {{ opt.nickname }},{{ opt.code }}
-
-
-
-
-
+ />
(orderSummary.vat = data)"
auto-load
/>
-
+
-
+
-
+
{{ props.row.quantity }}
diff --git a/src/pages/Order/OrderList.vue b/src/pages/Order/OrderList.vue
index c47a9b2ec73..dfeb0f6e253 100644
--- a/src/pages/Order/OrderList.vue
+++ b/src/pages/Order/OrderList.vue
@@ -1,7 +1,7 @@
(bankEntitiesOptions = data)"
+ @on-fetch="
+ (data) => {
+ (bankEntitiesOptions = data), (filteredBankEntitiesOptions = data);
+ }
+ "
auto-load
/>
{
findBankFk(value, row)"
:required="true"
>
@@ -109,7 +134,9 @@ const setWireTransfer = async () => {
bankEntityFilter(val, update)"
option-label="bic"
option-value="id"
hide-selected
diff --git a/src/pages/Supplier/Card/SupplierBasicData.vue b/src/pages/Supplier/Card/SupplierBasicData.vue
index 70f6432dd84..842109656d3 100644
--- a/src/pages/Supplier/Card/SupplierBasicData.vue
+++ b/src/pages/Supplier/Card/SupplierBasicData.vue
@@ -5,6 +5,7 @@ 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 VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
const route = useRoute();
const { t } = useI18n();
@@ -30,31 +31,11 @@ const companySizes = [
:rules="validate('supplier.nickname')"
clearable
/>
-
-
-
- {{
- t('Responsible for approving invoices')
- }}
-
-
-
-
-
- {{ scope.opt?.name }}
-
- {{ scope.opt?.nickname }}, {{ scope.opt?.id }}
-
-
-
-
-
+ />
es:
- Responsible for approving invoices: Responsable de aprobar las facturas
Small(1-5), Medium(6-50), Big(> 50): Pequeño(1-5), Mediano(6-50), Grande(> 50)
diff --git a/src/pages/Supplier/Card/SupplierConsumption.vue b/src/pages/Supplier/Card/SupplierConsumption.vue
index fe1cec260ea..8a7021fb341 100644
--- a/src/pages/Supplier/Card/SupplierConsumption.vue
+++ b/src/pages/Supplier/Card/SupplierConsumption.vue
@@ -8,7 +8,7 @@ import SendEmailDialog from 'components/common/SendEmailDialog.vue';
import SupplierConsumptionFilter from './SupplierConsumptionFilter.vue';
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
-import { toDate } from 'src/filters';
+import { dateRange, toDate } from 'src/filters';
import { dashIfEmpty } from 'src/filters';
import { usePrintService } from 'composables/usePrintService';
import useNotify from 'src/composables/useNotify.js';
@@ -35,14 +35,17 @@ const store = arrayData.store;
onUnmounted(() => state.unset('SupplierConsumption'));
const dateRanges = computed(() => {
- const { from, to } = arrayData.store?.userParams || {};
+ let { from, to } = arrayData.store?.userParams || {};
return { from, to };
});
-const reportParams = computed(() => ({
- recipientId: Number(route.params.id),
- ...dateRanges.value,
-}));
+const reportParams = computed(() => {
+ return {
+ recipientId: Number(route.params.id),
+ to: dateRange(dateRanges.value.to)[1],
+ from: dateRange(dateRanges.value.from)[1],
+ };
+});
async function getSupplierConsumptionData() {
await arrayData.fetch({ append: false });
@@ -171,11 +174,9 @@ onMounted(async () => {
-
-
-
-
-
+
+
+
en:
params:
+ supplierFk: Supplier
search: General search
itemId: Item id
buyerId: Buyer
@@ -143,6 +144,7 @@ en:
to: To
es:
params:
+ supplierFk: Proveedor
search: Búsqueda general
itemId: Id Artículo
buyerId: Comprador
diff --git a/src/pages/Supplier/Card/SupplierFiscalData.vue b/src/pages/Supplier/Card/SupplierFiscalData.vue
index 54784296096..44235717f86 100644
--- a/src/pages/Supplier/Card/SupplierFiscalData.vue
+++ b/src/pages/Supplier/Card/SupplierFiscalData.vue
@@ -9,6 +9,7 @@ import VnRow from 'components/ui/VnRow.vue';
import VnInput from 'src/components/common/VnInput.vue';
import VnSelect from 'src/components/common/VnSelect.vue';
import VnLocation from 'src/components/common/VnLocation.vue';
+import VnAccountNumber from 'src/components/common/VnAccountNumber.vue';
const route = useRoute();
const { t } = useI18n();
@@ -100,10 +101,13 @@ function handleLocation(data, location) {
/>
-
-
+
{{
diff --git a/src/pages/Supplier/Card/SupplierSummary.vue b/src/pages/Supplier/Card/SupplierSummary.vue
index b808b3e3ed6..a08561933c6 100644
--- a/src/pages/Supplier/Card/SupplierSummary.vue
+++ b/src/pages/Supplier/Card/SupplierSummary.vue
@@ -149,7 +149,7 @@ const getUrl = (section) => `#/supplier/${entityId.value}/${section}`;
-
+
[
-en:
- Search suppliers: Search suppliers
-es:
+ es:
Search suppliers: Buscar proveedores
+ Create Supplier: Crear proveedor
diff --git a/src/pages/Supplier/SupplierListFilter.vue b/src/pages/Supplier/SupplierListFilter.vue
index 7f838d3f537..b170a35cc8b 100644
--- a/src/pages/Supplier/SupplierListFilter.vue
+++ b/src/pages/Supplier/SupplierListFilter.vue
@@ -23,13 +23,13 @@ const countriesOptions = ref([]);
(provincesOptions = data)"
auto-load
/>
(countriesOptions = data)"
auto-load
/>
diff --git a/src/pages/Ticket/Card/BasicData/TicketBasicData.vue b/src/pages/Ticket/Card/BasicData/TicketBasicData.vue
index ab96a6e7570..c6a85c287d4 100644
--- a/src/pages/Ticket/Card/BasicData/TicketBasicData.vue
+++ b/src/pages/Ticket/Card/BasicData/TicketBasicData.vue
@@ -1,5 +1,5 @@
@@ -191,7 +173,7 @@ onUnmounted(() => (stateStore.rightDrawer = false));
horizontal
>
(stateStore.rightDrawer = false));
@@ -225,7 +207,7 @@ onUnmounted(() => (stateStore.rightDrawer = false));
:columns="columns"
row-key="id"
:pagination="{ rowsPerPage: 0 }"
- class="full-width q-mt-md"
+ class="full-width"
:no-data-label="t('globals.noResults')"
flat
>
@@ -238,21 +220,27 @@ onUnmounted(() => (stateStore.rightDrawer = false));
-
-
+
+
{{ row.item.name }}
- {{ row.item.subName }}
-
+
-
+
- {{ row.item.subName }}
+
+
+
+
+
diff --git a/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue b/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue
index 1fc54f48693..cf44815374b 100644
--- a/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue
+++ b/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue
@@ -1,5 +1,5 @@
-
-
-
-
-
-
- {{ t('ticket.boxing.selectTime') }} ({{ time.min }}-{{
- time.max
- }})
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- #{{ expedition.id }}
-
-
- {{ t('globals.created') }}
-
- {{
- date.formatDate(expedition.created, 'YYYY-MM-DD HH:mm:ss')
- }}
-
- {{ t('globals.item') }}
- {{ expedition.packagingItemFk }}
- {{ t('ticket.boxing.worker') }}
- {{ expedition.userName }}
-
-
-
-
-
-
+
+
+
+
+
+ {{ t('ticket.boxing.selectTime') }} ({{ time.min }}-{{
+ time.max
+ }})
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ #{{ expedition.id }}
+
+
+ {{ t('globals.created') }}
+
+ {{ date.formatDate(expedition.created, 'YYYY-MM-DD HH:mm:ss') }}
+
+ {{ t('globals.item') }}
+ {{ expedition.packagingItemFk }}
+ {{ t('ticket.boxing.worker') }}
+ {{ expedition.userName }}
+
+
+
+
-import { useI18n } from 'vue-i18n';
-
-import VnCard from 'components/common/VnCard.vue';
+import VnCardBeta from 'components/common/VnCardBeta.vue';
import TicketDescriptor from './TicketDescriptor.vue';
-import TicketFilter from '../TicketFilter.vue';
-
-const { t } = useI18n();
-
+
diff --git a/src/pages/Ticket/Card/TicketComponents.vue b/src/pages/Ticket/Card/TicketComponents.vue
index f45bde2d178..64815752ab8 100644
--- a/src/pages/Ticket/Card/TicketComponents.vue
+++ b/src/pages/Ticket/Card/TicketComponents.vue
@@ -1,5 +1,5 @@
@@ -180,7 +178,7 @@ onUnmounted(() => (stateStore.rightDrawer = false));
@on-fetch="(data) => (components = data)"
auto-load
/>
-
+
@@ -266,7 +264,7 @@ onUnmounted(() => (stateStore.rightDrawer = false));
{{ toCurrency(theoricalCost, 'EUR', 2) }}
-
+
(stateStore.rightDrawer = false));
{{ toCurrency(saleComponent.value * row.quantity, 'EUR', 3) }}
-
diff --git a/src/pages/Ticket/Card/TicketCreateTracking.vue b/src/pages/Ticket/Card/TicketCreateTracking.vue
index 3ea762c6c36..5c1e916f244 100644
--- a/src/pages/Ticket/Card/TicketCreateTracking.vue
+++ b/src/pages/Ticket/Card/TicketCreateTracking.vue
@@ -9,6 +9,7 @@ import VnSelect from 'src/components/common/VnSelect.vue';
import FetchData from 'components/FetchData.vue';
import { useState } from 'src/composables/useState';
+import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
const emit = defineEmits(['onRequestCreated']);
@@ -46,29 +47,7 @@ const onStateFkChange = (formData) => (formData.userFk = user.value.id);
option-label="name"
option-value="id"
/>
-
-
-
-
-
- {{ opt.name }}
-
-
- {{ opt.nickname }}, {{ opt.code }}
-
-
-
-
+
diff --git a/src/pages/Ticket/Card/TicketDescriptor.vue b/src/pages/Ticket/Card/TicketDescriptor.vue
index f8ffb43ed78..4e77b633ff8 100644
--- a/src/pages/Ticket/Card/TicketDescriptor.vue
+++ b/src/pages/Ticket/Card/TicketDescriptor.vue
@@ -130,6 +130,7 @@ function ticketFilter(ticket) {
{{ entity.ticketState.state.name }}
@@ -174,7 +175,7 @@ function ticketFilter(ticket) {
{{ t('Client Frozen') }}
import axios from 'axios';
-import { computed, ref, toRefs } from 'vue';
+import { computed, onMounted, ref, toRefs, watch } from 'vue';
import { useQuasar } from 'quasar';
import { useI18n } from 'vue-i18n';
import { useRouter } from 'vue-router';
@@ -24,6 +24,15 @@ const props = defineProps({
},
});
+onMounted(() => {
+ restoreTicket();
+});
+
+watch(
+ () => props.ticket,
+ () => restoreTicket
+);
+
const { push, currentRoute } = useRouter();
const { dialog, notify } = useQuasar();
const { t } = useI18n();
@@ -42,6 +51,7 @@ const hasPdf = ref();
const weight = ref();
const hasDocuwareFile = ref();
const quasar = useQuasar();
+const canRestoreTicket = ref(false);
const actions = {
clone: async () => {
const opts = { message: t('Ticket cloned'), type: 'positive' };
@@ -373,6 +383,54 @@ async function uploadDocuware(force) {
if (data) notify({ message: t('PDF sent!'), type: 'positive' });
}
+
+const restoreTicket = async () => {
+ const filter = {
+ fields: ['id', 'originFk', 'creationDate', 'newInstance'],
+ where: {
+ originFk: ticketId.value,
+ newInstance: { like: '%"isDeleted":true%' },
+ },
+ order: 'creationDate DESC',
+ limit: 1,
+ };
+ const params = { filter: JSON.stringify(filter) };
+
+ const { data } = await axios.get(`TicketLogs`, { params });
+
+ if (data && data.length) {
+ const now = Date.vnNew();
+ const maxDate = new Date(data[0].creationDate);
+ maxDate.setHours(maxDate.getHours() + 1);
+ if (now <= maxDate) {
+ return (canRestoreTicket.value = true);
+ }
+ return (canRestoreTicket.value = false);
+ }
+ return (canRestoreTicket.value = false);
+};
+
+async function openRestoreConfirmation(force) {
+ if (!force)
+ return quasar
+ .dialog({
+ component: VnConfirm,
+ componentProps: {
+ title: t('Are you sure you want to restore the ticket?'),
+ message: t('You are going to restore this ticket'),
+ },
+ })
+ .onOk(async () => {
+ ticketToRestore();
+ });
+}
+
+async function ticketToRestore() {
+ const { data } = await axios.post(`Tickets/${ticketId.value}/restore`);
+ if (data) {
+ notify({ message: t('Ticket restored'), type: 'positive' });
+ }
+}
{{ t('Show Proforma') }}
+
+
+
+
+ {{ t('Restore ticket') }}
+
@@ -741,10 +805,13 @@ es:
Ticket invoiced: Ticket facturado
Set weight: Establecer peso
Weight set: Peso establecido
- This ticket may be invoiced, do you want to continue?: Es posible que se facture este ticket, desea continuar?
invoiceIds: "Se han generado las facturas con los siguientes ids: {invoiceIds}"
This ticket will be removed from current route! Continue anyway?: ¡Se eliminará el ticket de la ruta actual! ¿Continuar de todas formas?
You are going to delete this ticket: Vas a eliminar este ticket
as PDF signed: como PDF firmado
Are you sure you want to replace this delivery note?: ¿Seguro que quieres reemplazar este albarán?
+ Restore ticket: Restaurar ticket
+ Are you sure you want to restore the ticket?: ¿Seguro que quieres restaurar el ticket?
+ You are going to restore this ticket: Vas a restaurar este ticket
+ Ticket restored: Ticket restaurado
diff --git a/src/pages/Ticket/Card/TicketEditMana.vue b/src/pages/Ticket/Card/TicketEditMana.vue
index 3d5b04a412e..693875712d1 100644
--- a/src/pages/Ticket/Card/TicketEditMana.vue
+++ b/src/pages/Ticket/Card/TicketEditMana.vue
@@ -75,6 +75,7 @@ const cancel = () => {
dense
style="width: 50%"
@click="save()"
+ data-cy="saveManaBtn"
>
{{ t('globals.save') }}
diff --git a/src/pages/Ticket/Card/TicketExpedition.vue b/src/pages/Ticket/Card/TicketExpedition.vue
index b7f1f4dd090..7da04912471 100644
--- a/src/pages/Ticket/Card/TicketExpedition.vue
+++ b/src/pages/Ticket/Card/TicketExpedition.vue
@@ -1,5 +1,5 @@
diff --git a/src/pages/Ticket/Card/TicketNotes.vue b/src/pages/Ticket/Card/TicketNotes.vue
index 6861cf000f3..f558b71cc2b 100644
--- a/src/pages/Ticket/Card/TicketNotes.vue
+++ b/src/pages/Ticket/Card/TicketNotes.vue
@@ -80,12 +80,14 @@ async function handleSave() {
option-value="id"
v-model="row.observationTypeFk"
:disable="!!row.id"
+ data-cy="ticketNotesObservationType"
/>
{{ t('ticketNotes.removeNote') }}
@@ -107,6 +110,7 @@ async function handleSave() {
class="fill-icon-on-hover q-ml-md"
color="primary"
@click="ticketNotesCrudRef.insert()"
+ data-cy="ticketNotesAddNoteBtn"
>
{{ t('ticketNotes.addNote') }}
diff --git a/src/pages/Ticket/Card/TicketPurchaseRequest.vue b/src/pages/Ticket/Card/TicketPurchaseRequest.vue
index 3b9d6a25b92..4e77c727725 100644
--- a/src/pages/Ticket/Card/TicketPurchaseRequest.vue
+++ b/src/pages/Ticket/Card/TicketPurchaseRequest.vue
@@ -275,4 +275,5 @@ onMounted(() => (stateStore.rightDrawer = false));
New: Nueva
Denied: Denegada
Accepted: Aceptada
+ Create request: Crear petición de compra
diff --git a/src/pages/Ticket/Card/TicketSale.vue b/src/pages/Ticket/Card/TicketSale.vue
index 95ef3118e9d..8aa785c74bf 100644
--- a/src/pages/Ticket/Card/TicketSale.vue
+++ b/src/pages/Ticket/Card/TicketSale.vue
@@ -1,5 +1,5 @@
-
+
@@ -72,6 +74,7 @@ defineExpose({ transferSales });
color="primary"
class="full-width q-my-lg"
@click="transferSales()"
+ data-cy="ticketTransferNewTicketBtn"
/>
diff --git a/src/pages/Ticket/Card/TicketVolume.vue b/src/pages/Ticket/Card/TicketVolume.vue
index 7aeeec95299..3c9f579d483 100644
--- a/src/pages/Ticket/Card/TicketVolume.vue
+++ b/src/pages/Ticket/Card/TicketVolume.vue
@@ -1,5 +1,5 @@
@@ -102,11 +100,9 @@ onUnmounted(() => (stateStore.rightDrawer = false));
@on-fetch="(data) => applyVolumes(data)"
auto-load
/>
-
(stateStore.rightDrawer = false));
{{ t('volume.volume') }}: {{ packingType.volume }}
-
-
+
[
@@ -215,7 +216,7 @@ const requestComponentUpdate = async (ticket, isWithoutNegatives) => {
if (!newLanded) {
notify(t('advanceTickets.noDeliveryZone'), 'negative');
- return;
+ throw new Error(t('advanceTickets.noDeliveryZone'));
}
ticket.landed = newLanded.landed;
@@ -299,10 +300,10 @@ const splitTickets = async () => {
const { query, params } = await requestComponentUpdate(ticket, true);
await axios.post(query, params);
progressAdd(ticket.futureId);
- } catch (error) {
+ } catch (e) {
splitErrors.value.push({
id: ticket.futureId,
- reason: error.response?.data?.error?.message,
+ reason: e.message || e.response?.data?.error?.message,
});
progressAdd(ticket.futureId);
}
@@ -441,6 +442,7 @@ watch(
@@ -482,6 +485,14 @@ watch(
+
+ {{ t('advanceTickets.clonedSales') }}
+
diff --git a/src/pages/Ticket/TicketAdvanceFilter.vue b/src/pages/Ticket/TicketAdvanceFilter.vue
index a1d301f3521..6d5c7726e17 100644
--- a/src/pages/Ticket/TicketAdvanceFilter.vue
+++ b/src/pages/Ticket/TicketAdvanceFilter.vue
@@ -57,7 +57,6 @@ onMounted(async () => await getItemPackingTypes());
search-url="advanceTickets"
:data-key="props.dataKey"
:search-button="true"
- :hidden-tags="['search']"
:unremovable-params="['warehouseFk', 'dateFuture', 'dateToAdvance']"
>
@@ -169,6 +168,16 @@ onMounted(async () => await getItemPackingTypes());
+
+
+
+
+
@@ -183,6 +192,7 @@ en:
ipt: Destination IPT
isFullMovable: 100% movable
warehouseFk: Warehouse
+ onlyWithDestination: Only with destination
es:
Horizontal: Horizontal
Vertical: Vertical
@@ -194,4 +204,5 @@ es:
ipt: IPT destino
isFullMovable: 100% movible
warehouseFk: Almacén
+ onlyWithDestination: Solo con destino
diff --git a/src/pages/Ticket/TicketFilter.vue b/src/pages/Ticket/TicketFilter.vue
index bde27f30efc..9c8b9f1a3be 100644
--- a/src/pages/Ticket/TicketFilter.vue
+++ b/src/pages/Ticket/TicketFilter.vue
@@ -298,14 +298,19 @@ en:
to: To
salesPersonFk: Salesperson
stateFk: State
+ groupedStates: Grouped State
refFk: Invoice Ref.
+ scopeDays: Days onward
+ nickname: Nickname
myTeam: My team
pending: Pending
hasInvoice: Invoiced
hasRoute: Routed
+ problems: With problems
provinceFk: Province
agencyModeFk: Agency
warehouseFk: Warehouse
+ collectionFk: Collection
FREE: Free
ON_PREPARATION: On preparation
PACKED: Packed
@@ -320,11 +325,19 @@ es:
to: Hasta
salesPersonFk: Comercial
stateFk: Estado
+ groupedStates: Estado agrupado
refFk: Ref. Factura
+ scopeDays: Días en adelante
+ nickname: Nombre mostrado
myTeam: Mi equipo
pending: Pendiente
hasInvoice: Facturado
hasRoute: Enrutado
+ problems: Con problemas
+ provinceFk: Provincia
+ agencyModeFk: Agencia
+ warehouseFk: Almacén
+ collectionFk: Colección
Customer ID: ID Cliente
Order ID: ID Pedido
From: Desde
diff --git a/src/pages/Ticket/TicketFutureFilter.vue b/src/pages/Ticket/TicketFutureFilter.vue
index ffe96727260..d28b0af71e9 100644
--- a/src/pages/Ticket/TicketFutureFilter.vue
+++ b/src/pages/Ticket/TicketFutureFilter.vue
@@ -59,7 +59,6 @@ onMounted(async () => {
/>
diff --git a/src/pages/Ticket/TicketList.vue b/src/pages/Ticket/TicketList.vue
index 6f6c556ca13..823f74fc51a 100644
--- a/src/pages/Ticket/TicketList.vue
+++ b/src/pages/Ticket/TicketList.vue
@@ -1,6 +1,6 @@
diff --git a/src/pages/Ticket/locale/en.yml b/src/pages/Ticket/locale/en.yml
index 56cc798ba37..f11b32c3a5e 100644
--- a/src/pages/Ticket/locale/en.yml
+++ b/src/pages/Ticket/locale/en.yml
@@ -53,6 +53,7 @@ advanceTickets:
errorsList: Errors list
search: Search advance tickets
searchInfo: Search advance tickets by ID or client ID
+ clonedSales: Has turn lines
futureTickets:
problems: Problems
shipped: Date
diff --git a/src/pages/Ticket/locale/es.yml b/src/pages/Ticket/locale/es.yml
index bb068ac5bf2..945da8367f8 100644
--- a/src/pages/Ticket/locale/es.yml
+++ b/src/pages/Ticket/locale/es.yml
@@ -91,6 +91,7 @@ advanceTickets:
errorsList: Lista de errores
search: Buscar por tickets adelantados
searchInfo: Buscar tickets adelantados por el identificador o el identificador del cliente
+ clonedSales: Tiene líneas de turno
futureTickets:
problems: Problemas
shipped: Fecha
diff --git a/src/pages/Travel/Card/TravelBasicData.vue b/src/pages/Travel/Card/TravelBasicData.vue
index fd02b28cdfb..4b9aa28ed06 100644
--- a/src/pages/Travel/Card/TravelBasicData.vue
+++ b/src/pages/Travel/Card/TravelBasicData.vue
@@ -104,7 +104,7 @@ const warehousesOptionsIn = ref([]);
es:
- raidDays: Si se marca "Redada", la fecha de entrega se moverá automáticamente los días indicados.
+ raidDays: El travel se desplaza automáticamente cada día para estar desde hoy al número de días indicado. Si se deja vacio no se moverá
en:
- raidDays: If "Raid" is checked, the landing date will automatically shift by the specified number of days.
+ raidDays: The travel adjusts itself daily to match the number of days set, starting from today. If left blank, it won’t move
diff --git a/src/pages/Travel/Card/TravelCard.vue b/src/pages/Travel/Card/TravelCard.vue
index 50cecef3456..fd442d58bff 100644
--- a/src/pages/Travel/Card/TravelCard.vue
+++ b/src/pages/Travel/Card/TravelCard.vue
@@ -7,13 +7,13 @@ import filter from './TravelFilter.js';
diff --git a/src/pages/Travel/Card/TravelSummary.vue b/src/pages/Travel/Card/TravelSummary.vue
index f4331ccb22c..cfc082ad9dc 100644
--- a/src/pages/Travel/Card/TravelSummary.vue
+++ b/src/pages/Travel/Card/TravelSummary.vue
@@ -8,7 +8,7 @@ import VnLv from 'src/components/ui/VnLv.vue';
import VnTitle from 'src/components/common/VnTitle.vue';
import EntryDescriptorProxy from 'src/pages/Entry/Card/EntryDescriptorProxy.vue';
import FetchData from 'src/components/FetchData.vue';
-
+import VnRow from 'components/ui/VnRow.vue';
import { toDate, toCurrency } from 'src/filters';
import axios from 'axios';
@@ -256,16 +256,20 @@ const getLink = (param) => `#/travel/${entityId.value}/${param}`;
:label="t('globals.warehouseOut')"
:value="travel.warehouseOut?.name"
/>
-
-
+
+
+
+
+
+
@@ -300,10 +304,6 @@ const getLink = (param) => `#/travel/${entityId.value}/${param}`;
-
@@ -324,7 +324,6 @@ const getLink = (param) => `#/travel/${entityId.value}/${param}`;
[
align: 'left',
showValue: false,
sortable: true,
+ style: 'min-width: 170px;',
},
{
label: t('globals.packages'),
@@ -237,7 +238,7 @@ const columns = computed(() => [
format: (value) => toDate(value),
},
{
- label: t('globals.wareHhuseIn'),
+ label: t('globals.warehouseIn'),
field: 'warehouseInName',
name: 'warehouseInName',
align: 'left',
@@ -506,7 +507,7 @@ const getColor = (percentage) => {
:key="col.name"
:props="props"
@click="stopEventPropagation($event, col)"
- auto-width
+ :style="col.style"
>
{
}"
>
- {{ entry.id }}
+ {{ entry.id }}
@@ -637,6 +638,18 @@ const getColor = (percentage) => {
:deep(.q-table) {
border-collapse: collapse;
+
+ th {
+ padding: 0;
+ }
+ tbody tr td {
+ &:nth-child(1) {
+ max-width: 65px;
+ }
+ &:nth-child(4) {
+ padding: 0;
+ }
+ }
}
.q-td :deep(input) {
@@ -684,7 +697,6 @@ const getColor = (percentage) => {
width: max-content;
}
-
en:
searchExtraCommunity: Search for extra community shipping
@@ -692,6 +704,7 @@ en:
physicKg: Phy. KG
shipped: W. shipped
landed: W. landed
+ notes: Notes
es:
searchExtraCommunity: Buscar por envío extra comunitario
@@ -699,5 +712,6 @@ es:
physicKg: KG físico
shipped: F. envío
landed: F. llegada
+ notes: Notas
Open as PDF: Abrir como PDF
diff --git a/src/pages/Travel/TravelFilter.vue b/src/pages/Travel/TravelFilter.vue
index 1ac83b9e073..287ac5ad293 100644
--- a/src/pages/Travel/TravelFilter.vue
+++ b/src/pages/Travel/TravelFilter.vue
@@ -77,7 +77,6 @@ defineExpose({ states });
:label="t('travel.shipped')"
v-model="params.shipped"
@update:model-value="searchFn()"
- dense
outlined
rounded
/>
@@ -153,7 +152,7 @@ es:
Id: Id
ref: Referencia
agency: Agencia
- warehouseInFk: Alm.Salida
+ warehouseInFk: Alm.Entrada
shipped: F.Envío
shipmentHour: Hora de envío
warehouseOut: Alm.Entrada
diff --git a/src/pages/Travel/TravelList.vue b/src/pages/Travel/TravelList.vue
index 852003a9578..f77beff2187 100644
--- a/src/pages/Travel/TravelList.vue
+++ b/src/pages/Travel/TravelList.vue
@@ -26,7 +26,6 @@ const $props = defineProps({
});
const entityId = computed(() => $props.id || route.params.id);
-const travelFilterRef = ref();
onMounted(async () => {
stateStore.rightDrawer = true;
});
@@ -54,7 +53,9 @@ const columns = computed(() => [
name: 'id',
label: t('globals.id'),
isId: true,
- cardVisible: true,
+ chip: {
+ condition: () => true,
+ },
},
{
align: 'left',
@@ -64,7 +65,7 @@ const columns = computed(() => [
columnField: {
component: null,
},
- cardVisible: true,
+ isTitle: true,
create: true,
},
{
@@ -103,14 +104,14 @@ const columns = computed(() => [
},
{
align: 'left',
- name: 'shipped',
label: t('globals.shipped'),
+ name: 'shipped',
+ create: true,
+ cardVisible: true,
component: 'date',
columnField: {
component: null,
},
- cardVisible: true,
- create: true,
format: (row, dashIfEmpty) => dashIfEmpty(toDate(row.shipped)),
},
{
@@ -201,13 +202,14 @@ const columns = computed(() => [
/>
-
+
@@ -294,6 +294,7 @@ es:
Search travel: Buscar envio
Clone: Clonar
Add entry: Añadir Entrada
+ Create Travels: Crear envíos