diff --git a/CHANGELOG.md b/CHANGELOG.md
index e110e4cd6..6908d764a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,167 @@
+# Version 24.52 - 2024-01-07
+
+### Added 🆕
+
+- chore: refs #8197 remove console log by:alexm
+- chore: refs #8197 replace name by:alexm
+- chore: refs #8197 unnecessary file by:alexm
+- feat: #8110 apply mixin in quasar components by:Javier Segarra
+- feat(Account & AccountRole): refs #8197 add VnCardMain by:alexm
+- feat: addDptoLink by:Jtubau
+- feat: added restore ticket function in ticket descriptor menu by:Jon
+- feat: add support service wip by:jorgep
+- feat: focus menu searchbar by:jorgep
+- feat: make additional data object by:jorgep
+- feat: message to grant access by:jorgep
+- feat: refs #6583 add default param by:jorgep
+- feat: refs #6583 add destination opt filter by:jorgep
+- feat: refs #6583 add icon by:jorgep
+- feat: refs #6583 add locale by:jorgep
+- feat: refs #7072 added test to computed fn total by:Jtubau
+- feat: refs #7235 update invoice out global form to fetch config based on serial type by:jgallego
+- feat: refs #7301 add exclude inventory supplier from list by:pablone
+- feat: refs #7301 enhance VnDateBadge styling and improve ItemLastEntries component by:pablone
+- feat: refs #7882 Added distribution point by:guillermo
+- feat: refs #7882 Added longitude & latitude by:guillermo
+- feat: refs #7936 add autocomplete on tab fn by:jorgep
+- feat: refs #7936 add company filter by:jorgep
+- feat: refs #7936 add currency check before fetching by:jorgep
+- feat: refs #7936 add dueDated field by:jorgep
+- feat: refs #7936 add number validation to VnInputNumber & new daysAgo filter in InvoiceInFilter by:jorgep
+- feat: refs #7936 add optionCaption by:jorgep
+- feat: refs #7936 add row click navigation to InvoiceInSerial by:jorgep
+- feat: refs #7936 add unit tests by:jorgep
+- feat: refs #7936 add useAccountShortToStandard composable by:jorgep
+- feat: refs #7936 calculate exchange & update taxable base by:jorgep
+- feat: refs #7936 enhance downloadFile function to support opening in a new tab by:jorgep
+- feat: refs #7936 enhance getTotal fn & add unit tests by:jorgep
+- feat: refs #7936 enhance vn-select by:jorgep
+- feat: refs #7936 improve optionLabel logic in InvoiceInVat component for better handling of numeric values by:jorgep
+- feat: refs #7936 limit decimal places by:jorgep
+- feat: refs #7936 make fields required by:jorgep
+- feat: refs #7936 show country code & isVies fields by:jorgep
+- feat: refs #7936 show id & value by:jorgep
+- feat: refs #7936 simplify optionLabel wip by:jorgep
+- feat: refs #7936 update 'isVies' label to use global translation key by:jorgep
+- feat: refs #7936 update option labels in InvoiceIn components for better clarity by:jorgep
+- feat: refs #7936 use default invoice data by:jorgep
+- feat: refs #8001 change request by:robert
+- feat: refs #8001 ticketExpeditionGrafana by:robert
+- feat: refs #8194 created VnSelectWorker component and use it in Lilium by:Jon
+- feat: refs #8197 better leftMenu and VnCardMain improvements by:alexm
+- feat: refs #8197 default leftMenu by:alexm
+- feat: refs #8197 default sectionName by:alexm
+- feat: refs #8197 keepData in VnSection by:alexm
+- feat: refs #8197 vnTableFilter by:alexm
+- feat: refs #8197 working rightMenu by:alexm
+- feat: remove re-fetch when add element by:Javier Segarra
+- feat: remove search after category by:Javier Segarra
+- feat: requested changes in item module by:Jon
+- feat: update quantity by:Javier Segarra
+- feat(VnPaginate): refs #8197 hold data when change to Card by:alexm
+
+### Changed 📦
+
+- perf: #6896 REMOVE COMMENTS by:Javier Segarra
+- perf: qFormMixin by:Javier Segarra
+- perf: qFormMixin improvement by:Javier Segarra
+- perf: refs #8194 select worker component by:Jon
+- perf: refs #8197 perf by:alexm
+- perf: remove comments by:Javier Segarra
+- perf: remove unused variables (origin/warmfix_noUsedVars) by:Javier Segarra
+- refactor: added again search emit by:Jon
+- refactor: add useCau composable by:jorgep
+- refactor: deleted log by:Jon
+- refactor: deleted onUnmounted code by:Jon
+- refactor: deleted useless hidden tag by:Jon
+- refactor: deleted warnings and corrected itemTag by:Jon
+- refactor: drop logic by:jorgep
+- refactor: ignore params when searching by id on searchbar (origin/VnSearchbar-SearchRemoveParams) by:Jon
+- refactor: log error by:Jon
+- refactor: refs #7936 locale by:jorgep
+- refactor: refs #7936 simplify getTotal fn by:jorgep
+- refactor: refs #7936 update label capitalization and replace invoice type options by:jorgep
+- refactor: refs #8194 deleted unnecessary label by:Jon
+- refactor: refs #8194 modified select worker template by:Jon
+- refactor: refs #8194 modified select worker to allow no one filter from monitor ticket by:Jon
+- refactor: refs #8194 moved translation to the correct place by:Jon
+- refactor: refs #8194 requested changes by:Jon
+- refactor: refs #8194 structure changes in component and related files by:Jon
+- refactor: refs #8197 adapt AccountAcls to VnCardMain by:alexm
+- refactor: refs #8197 adapt AccountAlias by:alexm
+- refactor: refs #8197 adapt Ticket to VnCardMain by:alexm
+- refactor: refs #8197 backward compatible (8197-VnCardMain_backwardCompatibility) by:alexm
+- refactor: refs #8197 rename VnSectionMain to VnModule and VnCardMain to VnSection by:alexm
+- refactor: refs #8288 changed invoice out spanish translation by:provira
+- refactor: use locale keys by:jorgep
+- refactor: use teleport to avoid qdrawer overlapping by:Jon
+- refactor: use VnSelectWorker by:Jon
+
+### Fixed 🛠️
+
+- fix: account by:carlossa
+- fix: account create by:carlossa
+- fix: accountList create by:carlossa
+- fix(AccountList): use $refs by:alexm
+- fix: add data-key by:alexm
+- fix: addLocales by:Jtubau
+- fix: dated field by:Jon
+- fix: e2e by:jorgep
+- fix: fix department filter by:carlossa
+- fix: fixed translations by:Javier Segarra
+- fix: fixed translations by:provira
+- fix: get total from api by:Javier Segarra
+- fix: handle non-object options by:jorgep
+- fix: monitorPayMethodFilter by:carlossa
+- fix: orderBy priority by:Javier Segarra
+- fix: prevent null by:jorgep
+- fix: redirection vnTable VnTableFilter by:alexm
+- fix: refs #6389 fix filter trad by:carlossa
+- fix: refs #6389 fix front, filters, itp by:carlossa
+- fix: refs #6389 front add packing filter by:carlossa
+- fix: refs #6389 front by:carlossa
+- fix: refs #6389 front filters by:carlossa
+- fix: refs #6389 ipt by:carlossa
+- fix: refs #6389 packing by:carlossa
+- fix: refs #6583 update checkbox for filtering by destination in TicketAdvanceFilter by:jorgep
+- fix: refs #7031 add test e2e by:carlossa
+- fix: refs #7031 fix zoneTest by:carlossa
+- fix: refs #7301 unnecessary console logs from ItemLastEntries.vue by:pablone
+- fix: refs #7936 changes by:jorgep
+- fix: refs #7936 decimal places & locale by:jorgep
+- fix: refs #7936 descriptor & dueday by:jorgep
+- fix: refs #7936 exclude disabled els on tab by:jorgep
+- fix: refs #7936 format tax calculation to two decimal places by:jorgep
+- fix: refs #7936 improve error handling by:jorgep
+- fix: refs #7936 redirection by:jorgep
+- fix: refs #7936 rollback by:jorgep
+- fix: refs #7936 serial by:jorgep
+- fix: refs #7936 tabulation wip by:jorgep
+- fix: refs #7936 test by:jorgep
+- fix: refs #8114 clean by:carlossa
+- fix: refs #8114 fix agencyList by:carlossa
+- fix: refs #8114 fix lifeCycle hooks by:carlossa
+- fix: refs #8114 fix pr by:carlossa
+- fix: refs #8114 fix removeAddress by:carlossa
+- fix: refs #8114 orderList by:carlossa
+- fix: refs #8114 remove logs by:carlossa
+- fix: refs #8197 mapKey (origin/8197-perf_vnTableInside, 8197-perf_vnTableInside) by:alexm
+- fix: refs #8197 redirection (8197-perf_redirection) by:alexm
+- fix: refs #8197 staticParams and redirect by:alexm
+- fix: refs #8197 vnPaginate onFetch emit by:alexm
+- fix: refs #8197 vnPaginate when change :id by:alexm
+- fix: refs #8197 vnTableFilter in vnTable by:alexm
+- fix: refs #8315 ticketBoxing test by:alexm
+- fix: remove url by:carlossa
+- fix: rollback by:jorgep
+- fix: test by:jorgep
+- fix(VnDmsList): refs #8197 add mapKey by:alexm
+- revert: refs #8197 arrayData changes by:alexm
+- test: refs #8197 fix e2e by:alexm
+- test: refs #8315 fix claimDevelopment fixtures by:alexm
+- test: refs #8315 fix clientList by:alexm
+- test: refs #8315 fix VnSelect in e2e by:alexm
+
# Version 24.50 - 2024-12-10
### Added 🆕
diff --git a/package.json b/package.json
index 04b75a0b0..39d49519b 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "salix-front",
- "version": "24.50.0",
+ "version": "24.52.0",
"description": "Salix frontend",
"productName": "Salix",
"author": "Verdnatura",
@@ -64,4 +64,4 @@
"vite": "^5.1.4",
"vitest": "^0.31.1"
}
-}
\ No newline at end of file
+}
diff --git a/src/boot/mainShortcutMixin.js b/src/boot/mainShortcutMixin.js
new file mode 100644
index 000000000..481077e37
--- /dev/null
+++ b/src/boot/mainShortcutMixin.js
@@ -0,0 +1,36 @@
+import routes from 'src/router/modules';
+import { useRouter } from 'vue-router';
+
+let isNotified = false;
+
+export default {
+ created: function () {
+ const router = useRouter();
+ const keyBindingMap = routes
+ .filter((route) => route.meta.keyBinding)
+ .reduce((map, route) => {
+ map['Key' + route.meta.keyBinding.toUpperCase()] = route.path;
+ return map;
+ }, {});
+
+ const handleKeyDown = (event) => {
+ const { ctrlKey, altKey, code } = event;
+
+ if (ctrlKey && altKey && keyBindingMap[code] && !isNotified) {
+ event.preventDefault();
+ router.push(keyBindingMap[code]);
+ isNotified = true;
+ }
+ };
+
+ const handleKeyUp = (event) => {
+ const { ctrlKey, altKey } = event;
+ if (!ctrlKey || !altKey) {
+ isNotified = false;
+ }
+ };
+
+ window.addEventListener('keydown', handleKeyDown);
+ window.addEventListener('keyup', handleKeyUp);
+ },
+};
diff --git a/src/boot/qformMixin.js b/src/boot/qformMixin.js
index 8d009dbea..187ca6dbc 100644
--- a/src/boot/qformMixin.js
+++ b/src/boot/qformMixin.js
@@ -1,30 +1,51 @@
-import { getCurrentInstance } from 'vue';
-
+function focusFirstInput(input) {
+ input.focus();
+}
export default {
mounted: function () {
- const vm = getCurrentInstance();
- if (vm.type.name === 'QForm') {
- if (!['searchbarForm', 'filterPanelForm'].includes(this.$el?.id)) {
- // TODO: AUTOFOCUS IS NOT FOCUSING
- const that = this;
- this.$el.addEventListener('keyup', function (evt) {
- if (evt.key === 'Enter' && !that.$attrs['prevent-submit']) {
- const input = evt.target;
- if (input.type == 'textarea' && evt.shiftKey) {
- evt.preventDefault();
- let { selectionStart, selectionEnd } = input;
- input.value =
- input.value.substring(0, selectionStart) +
- '\n' +
- input.value.substring(selectionEnd);
- selectionStart = selectionEnd = selectionStart + 1;
- return;
- }
- evt.preventDefault();
- that.onSubmit();
- }
- });
+ const that = this;
+
+ const form = document.querySelector('.q-form#formModel');
+ if (!form) return;
+ try {
+ const inputsFormCard = form.querySelectorAll(
+ `input:not([disabled]):not([type="checkbox"])`
+ );
+ if (inputsFormCard.length) {
+ focusFirstInput(inputsFormCard[0]);
}
+ const textareas = document.querySelectorAll(
+ 'textarea:not([disabled]), [contenteditable]:not([disabled])'
+ );
+ if (textareas.length) {
+ focusFirstInput(textareas[textareas.length - 1]);
+ }
+ const inputs = document.querySelectorAll(
+ 'form#formModel input:not([disabled]):not([type="checkbox"])'
+ );
+ const input = inputs[0];
+ if (!input) return;
+
+ focusFirstInput(input);
+ } catch (error) {
+ console.error(error);
}
+ form.addEventListener('keyup', function (evt) {
+ if (evt.key === 'Enter') {
+ const input = evt.target;
+ if (input.type == 'textarea' && evt.shiftKey) {
+ evt.preventDefault();
+ let { selectionStart, selectionEnd } = input;
+ input.value =
+ input.value.substring(0, selectionStart) +
+ '\n' +
+ input.value.substring(selectionEnd);
+ selectionStart = selectionEnd = selectionStart + 1;
+ return;
+ }
+ evt.preventDefault();
+ that.onSubmit();
+ }
+ });
},
};
diff --git a/src/boot/quasar.js b/src/boot/quasar.js
index 01fe68d8b..547517682 100644
--- a/src/boot/quasar.js
+++ b/src/boot/quasar.js
@@ -1,15 +1,18 @@
+import axios from 'axios';
import { boot } from 'quasar/wrappers';
import qFormMixin from './qformMixin';
import keyShortcut from './keyShortcut';
-import useNotify from 'src/composables/useNotify.js';
-import { CanceledError } from 'axios';
-
-const { notify } = useNotify();
+import { QForm } from 'quasar';
+import { QLayout } from 'quasar';
+import mainShortcutMixin from './mainShortcutMixin';
+import { useCau } from 'src/composables/useCau';
export default boot(({ app }) => {
- app.mixin(qFormMixin);
+ QForm.mixins = [qFormMixin];
+ QLayout.mixins = [mainShortcutMixin];
+
app.directive('shortcut', keyShortcut);
- app.config.errorHandler = (error) => {
+ app.config.errorHandler = async (error) => {
let message;
const response = error.response;
const responseData = response?.data;
@@ -40,12 +43,12 @@ export default boot(({ app }) => {
}
console.error(error);
- if (error instanceof CanceledError) {
+ if (error instanceof axios.CanceledError) {
const env = process.env.NODE_ENV;
if (env && env !== 'development') return;
message = 'Duplicate request';
}
- notify(message ?? 'globals.error', 'negative', 'error');
+ await useCau(response, message);
};
});
diff --git a/src/components/CreateNewPostcodeForm.vue b/src/components/CreateNewPostcodeForm.vue
index c656fcb2f..26b79b1bc 100644
--- a/src/components/CreateNewPostcodeForm.vue
+++ b/src/components/CreateNewPostcodeForm.vue
@@ -55,13 +55,6 @@ async function setCountry(countryFk, data) {
}
// Province
-
-async function handleProvinces(data) {
- provincesOptions.value = data;
- if (postcodeFormData.countryFk) {
- await fetchTowns();
- }
-}
async function setProvince(id, data) {
if (data.provinceFk === id) return;
const newProvince = provincesOptions.value.find((province) => province.id == id);
diff --git a/src/components/LeftMenu.vue b/src/components/LeftMenu.vue
index ab2931dfd..7a882e56c 100644
--- a/src/components/LeftMenu.vue
+++ b/src/components/LeftMenu.vue
@@ -92,13 +92,13 @@ function findMatches(search, item) {
}
function addChildren(module, route, parent) {
- if (route.menus) {
- const mainMenus = route.menus[props.source];
- const matches = findMatches(mainMenus, route);
+ const menus = route?.meta?.menu ?? route?.menus?.[props.source]; //backwards compatible
+ if (!menus) return;
- for (const child of matches) {
- navigation.addMenuItem(module, child, parent);
- }
+ const matches = findMatches(menus, route);
+
+ for (const child of matches) {
+ navigation.addMenuItem(module, child, parent);
}
}
@@ -122,16 +122,26 @@ function getRoutes() {
if (props.source === 'card') {
const currentRoute = route.matched[1];
const currentModule = toLowerCamel(currentRoute.name);
- const moduleDef = routes.find(
+ let moduleDef = routes.find(
(route) => toLowerCamel(route.name) === currentModule
);
if (!moduleDef) return;
-
+ if (!moduleDef?.menus) moduleDef = betaGetRoutes();
addChildren(currentModule, moduleDef, items.value);
}
}
+function betaGetRoutes() {
+ let menuRoute;
+ let index = route.matched.length - 1;
+ while (!menuRoute && index > 0) {
+ if (route.matched[index]?.meta?.menu) menuRoute = route.matched[index];
+ index--;
+ }
+ return menuRoute;
+}
+
async function togglePinned(item, event) {
if (event.defaultPrevented) return;
event.preventDefault();
@@ -177,6 +187,7 @@ function normalize(text) {
class="full-width"
filled
dense
+ autofocus
/>
diff --git a/src/components/NavBar.vue b/src/components/NavBar.vue
index 9b0393489..08c2410f1 100644
--- a/src/components/NavBar.vue
+++ b/src/components/NavBar.vue
@@ -59,6 +59,7 @@ const pinnedModulesRef = ref();
'no-visible': !stateQuery.isLoading().value,
}"
size="xs"
+ data-cy="loading-spinner"
/>
diff --git a/src/components/VnTable/VnFilter.vue b/src/components/VnTable/VnFilter.vue
index 999133130..426f5c716 100644
--- a/src/components/VnTable/VnFilter.vue
+++ b/src/components/VnTable/VnFilter.vue
@@ -32,7 +32,10 @@ const $props = defineProps({
defineExpose({ addFilter, props: $props });
const model = defineModel(undefined, { required: true });
-const arrayData = useArrayData($props.dataKey, { searchUrl: $props.searchUrl });
+const arrayData = useArrayData(
+ $props.dataKey,
+ $props.searchUrl ? { searchUrl: $props.searchUrl } : null
+);
const columnFilter = computed(() => $props.column?.columnFilter);
const updateEvent = { 'update:modelValue': addFilter };
diff --git a/src/components/VnTable/VnTable.vue b/src/components/VnTable/VnTable.vue
index d6117a117..3839ff0c2 100644
--- a/src/components/VnTable/VnTable.vue
+++ b/src/components/VnTable/VnTable.vue
@@ -1,20 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ t(`${chipLocale}.${tag.label}`) }}:
+ {{ formatFn(tag.value) }}
+
+
+
+
diff --git a/src/components/common/VnBreadcrumbs.vue b/src/components/common/VnBreadcrumbs.vue
index 02226e497..334ab4d21 100644
--- a/src/components/common/VnBreadcrumbs.vue
+++ b/src/components/common/VnBreadcrumbs.vue
@@ -15,7 +15,7 @@ let root = ref(null);
watchEffect(() => {
matched.value = currentRoute.value.matched.filter(
- (matched) => Object.keys(matched.meta).length
+ (matched) => !!matched?.meta?.title || !!matched?.meta?.icon
);
breadcrumbs.value.length = 0;
if (!matched.value[0]) return;
diff --git a/src/components/common/VnBtnSelect.vue b/src/components/common/VnBtnSelect.vue
index b0616a6b2..3d96a55a6 100644
--- a/src/components/common/VnBtnSelect.vue
+++ b/src/components/common/VnBtnSelect.vue
@@ -14,6 +14,7 @@ defineProps({
hide-dropdown-icon
focus-on-mount
@update:model-value="promise"
+ data-cy="vnBtnSelect_select"
/>
diff --git a/src/components/common/VnCardBeta.vue b/src/components/common/VnCardBeta.vue
new file mode 100644
index 000000000..349956be9
--- /dev/null
+++ b/src/components/common/VnCardBeta.vue
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/common/VnDateBadge.vue b/src/components/common/VnDateBadge.vue
new file mode 100644
index 000000000..83d39937a
--- /dev/null
+++ b/src/components/common/VnDateBadge.vue
@@ -0,0 +1,39 @@
+
+
+
+ {{ formatShippedDate(date) }}
+
+
+
diff --git a/src/components/common/VnDmsList.vue b/src/components/common/VnDmsList.vue
index 52dd6ef79..ed3cadc6b 100644
--- a/src/components/common/VnDmsList.vue
+++ b/src/components/common/VnDmsList.vue
@@ -297,7 +297,7 @@ defineExpose({
ref="dmsRef"
:data-key="$props.model"
:url="$props.model"
- :filter="dmsFilter"
+ :user-filter="dmsFilter"
:order="['dmsFk DESC']"
:auto-load="true"
@on-fetch="setData"
diff --git a/src/components/common/VnInputNumber.vue b/src/components/common/VnInputNumber.vue
index 1cad6c245..165cfae3d 100644
--- a/src/components/common/VnInputNumber.vue
+++ b/src/components/common/VnInputNumber.vue
@@ -1,13 +1,28 @@
-
-
+ {
+ const val = evt.target.value;
+ if (positive && val < 0) return (model = 0);
+ const [, decimal] = val.split('.');
+ if (val && decimal?.length > decimalPlaces)
+ model = parseFloat(val).toFixed(decimalPlaces);
+ }
+ "
+ />
diff --git a/src/components/common/VnLog.vue b/src/components/common/VnLog.vue
index 8c71c0997..9eca3c711 100644
--- a/src/components/common/VnLog.vue
+++ b/src/components/common/VnLog.vue
@@ -238,6 +238,7 @@ async function openPointRecord(id, modelLog) {
pointRecord.value = parseProps(propNames, locale, data);
}
async function setLogTree(data) {
+ if (!data) return;
logTree.value = getLogTree(data);
}
diff --git a/src/components/common/VnSectionMain.vue b/src/components/common/VnModule.vue
similarity index 52%
rename from src/components/common/VnSectionMain.vue
rename to src/components/common/VnModule.vue
index 15be6ad9a..038ee1d60 100644
--- a/src/components/common/VnSectionMain.vue
+++ b/src/components/common/VnModule.vue
@@ -1,8 +1,8 @@
-
+
+
diff --git a/src/components/common/VnSection.vue b/src/components/common/VnSection.vue
new file mode 100644
index 000000000..edd8d3dfa
--- /dev/null
+++ b/src/components/common/VnSection.vue
@@ -0,0 +1,94 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/common/VnSelect.vue b/src/components/common/VnSelect.vue
index 1cfe0a184..58b7667d2 100644
--- a/src/components/common/VnSelect.vue
+++ b/src/components/common/VnSelect.vue
@@ -4,6 +4,7 @@ import { useI18n } from 'vue-i18n';
import { useArrayData } from 'src/composables/useArrayData';
import { useRequired } from 'src/composables/useRequired';
import dataByOrder from 'src/utils/dataByOrder';
+import { QItemLabel } from 'quasar';
const emit = defineEmits(['update:modelValue', 'update:options', 'remove']);
const $attrs = useAttrs();
@@ -33,6 +34,10 @@ const $props = defineProps({
type: String,
default: 'id',
},
+ optionCaption: {
+ type: String,
+ default: null,
+ },
optionFilter: {
type: String,
default: null,
@@ -101,6 +106,10 @@ const $props = defineProps({
type: String,
default: null,
},
+ isOutlined: {
+ type: Boolean,
+ default: false,
+ },
});
const mixinRules = [requiredFieldRule, ...($attrs.rules ?? [])];
@@ -115,6 +124,15 @@ const noOneOpt = ref({
[optionValue.value]: false,
[optionLabel.value]: noOneText,
});
+const styleAttrs = computed(() => {
+ return $props.isOutlined
+ ? {
+ dense: true,
+ outlined: true,
+ rounded: true,
+ }
+ : {};
+});
const isLoading = ref(false);
const useURL = computed(() => $props.url);
const value = computed({
@@ -210,7 +228,7 @@ async function fetchFilter(val) {
const fetchOptions = { where, include, limit };
if (fields) fetchOptions.fields = fields;
if (sortBy) fetchOptions.order = sortBy;
- arrayData.reset(['skip', 'filter.skip', 'page']);
+ arrayData.resetPagination();
const { data } = await arrayData.applyFilter({ filter: fetchOptions });
setOptions(data);
@@ -292,7 +310,7 @@ function handleKeyDown(event) {
}
const focusableElements = document.querySelectorAll(
- 'a, button, input, textarea, select, details, [tabindex]:not([tabindex="-1"])'
+ 'a:not([disabled]), button:not([disabled]), input:not([disabled]), textarea:not([disabled]), select:not([disabled]), details:not([disabled]), [tabindex]:not([tabindex="-1"]):not([disabled])'
);
const currentIndex = Array.prototype.indexOf.call(
focusableElements,
@@ -311,9 +329,8 @@ function handleKeyDown(event) {
:options="myOptions"
:option-label="optionLabel"
:option-value="optionValue"
- v-bind="$attrs"
+ v-bind="{ ...$attrs, ...styleAttrs }"
@filter="filterHandler"
- @keydown="handleKeyDown"
:emit-value="nullishToTrue($attrs['emit-value'])"
:map-options="nullishToTrue($attrs['map-options'])"
:use-input="nullishToTrue($attrs['use-input'])"
@@ -328,13 +345,15 @@ function handleKeyDown(event) {
:input-debounce="useURL ? '300' : '0'"
:loading="isLoading"
@virtual-scroll="onScroll"
+ @keydown="handleKeyDown"
:data-cy="$attrs.dataCy ?? $attrs.label + '_select'"
+ :data-url="url"
>
{
value = null;
emit('remove');
@@ -362,6 +381,22 @@ function handleKeyDown(event) {
+
+
+ {{ opt }}
+
+ {{ opt[optionLabel] }}
+
+
+
+ {{ opt[optionLabel] }}
+
+
+ {{ `#${opt[optionCaption] || opt[optionValue]}` }}
+
+
+
+
diff --git a/src/components/common/VnSelectWorker.vue b/src/components/common/VnSelectWorker.vue
new file mode 100644
index 000000000..b0fef4443
--- /dev/null
+++ b/src/components/common/VnSelectWorker.vue
@@ -0,0 +1,85 @@
+
+
+
+
+
+
+
+
+
+ {{ $t($props.hasInfo) }}
+
+
+
+
+
+
+ {{ scope.opt.name }}
+
+
+ {{ scope.opt.nickname }}
+
+
+ {{ scope.opt.nickname }}, {{ scope.opt.code }}
+
+
+
+
+
+
+
+
+es:
+ Responsible for approving invoices: Responsable de aprobar las facturas
+
diff --git a/src/components/ui/CardDescriptor.vue b/src/components/ui/CardDescriptor.vue
index 83af77442..f4c0091d2 100644
--- a/src/components/ui/CardDescriptor.vue
+++ b/src/components/ui/CardDescriptor.vue
@@ -222,8 +222,8 @@ const toModule = computed(() =>
/>
-
-
es:
Original invoice: Factura origen
diff --git a/src/pages/InvoiceIn/Card/InvoiceInDescriptor.vue b/src/pages/InvoiceIn/Card/InvoiceInDescriptor.vue
index 92f3fffca..cb8a45833 100644
--- a/src/pages/InvoiceIn/Card/InvoiceInDescriptor.vue
+++ b/src/pages/InvoiceIn/Card/InvoiceInDescriptor.vue
@@ -1,5 +1,5 @@
{
@@ -138,8 +130,8 @@ const formatOpt = (row, { model, options }, prop) => {
@@ -154,7 +146,7 @@ const formatOpt = (row, { model, options }, prop) => {
{{ getTotal(rows, 'net') }}
- {{ getTotal(rows, 'stems') }}
+ {{ getTotal(rows, 'stems', { decimalPlaces: 0 }) }}
@@ -169,12 +161,14 @@ const formatOpt = (row, { model, options }, prop) => {
@@ -248,11 +242,6 @@ const formatOpt = (row, { model, options }, prop) => {
}
}
-
en:
amount: Amount
@@ -261,7 +250,7 @@ const formatOpt = (row, { model, options }, prop) => {
country: Country
es:
Code: Código
- amount: Cantidad
+ amount: Valor mercancía
net: Neto
stems: Tallos
country: País
diff --git a/src/pages/InvoiceIn/Card/InvoiceInSummary.vue b/src/pages/InvoiceIn/Card/InvoiceInSummary.vue
index 08fc11f69..115a33208 100644
--- a/src/pages/InvoiceIn/Card/InvoiceInSummary.vue
+++ b/src/pages/InvoiceIn/Card/InvoiceInSummary.vue
@@ -26,14 +26,14 @@ const intrastatTotals = ref({ amount: 0, net: 0, stems: 0 });
const vatColumns = ref([
{
name: 'expense',
- label: 'invoiceIn.summary.expense',
+ label: 'InvoiceIn.summary.expense',
field: (row) => row.expenseFk,
sortable: true,
align: 'left',
},
{
name: 'landed',
- label: 'invoiceIn.summary.taxableBase',
+ label: 'InvoiceIn.summary.taxableBase',
field: (row) => row.taxableBase,
format: (value) => toCurrency(value),
sortable: true,
@@ -41,7 +41,7 @@ const vatColumns = ref([
},
{
name: 'vat',
- label: 'invoiceIn.summary.sageVat',
+ label: 'InvoiceIn.summary.sageVat',
field: (row) => {
if (row.taxTypeSage) return `#${row.taxTypeSage.id} : ${row.taxTypeSage.vat}`;
},
@@ -51,7 +51,7 @@ const vatColumns = ref([
},
{
name: 'transaction',
- label: 'invoiceIn.summary.sageTransaction',
+ label: 'InvoiceIn.summary.sageTransaction',
field: (row) => {
if (row.transactionTypeSage)
return `#${row.transactionTypeSage.id} : ${row.transactionTypeSage?.transaction}`;
@@ -62,7 +62,7 @@ const vatColumns = ref([
},
{
name: 'rate',
- label: 'invoiceIn.summary.rate',
+ label: 'InvoiceIn.summary.rate',
field: (row) => taxRate(row.taxableBase, row.taxTypeSage?.rate),
format: (value) => toCurrency(value),
sortable: true,
@@ -70,7 +70,7 @@ const vatColumns = ref([
},
{
name: 'currency',
- label: 'invoiceIn.summary.currency',
+ label: 'InvoiceIn.summary.currency',
field: (row) => row.foreignValue,
format: (val) => val && toCurrency(val, currency.value),
sortable: true,
@@ -81,21 +81,21 @@ const vatColumns = ref([
const dueDayColumns = ref([
{
name: 'date',
- label: 'invoiceIn.summary.dueDay',
+ label: 'InvoiceIn.summary.dueDay',
field: (row) => toDate(row.dueDated),
sortable: true,
align: 'left',
},
{
name: 'bank',
- label: 'invoiceIn.summary.bank',
+ label: 'InvoiceIn.summary.bank',
field: (row) => row.bank.bank,
sortable: true,
align: 'left',
},
{
name: 'amount',
- label: 'invoiceIn.list.amount',
+ label: 'InvoiceIn.list.amount',
field: (row) => row.amount,
format: (value) => toCurrency(value),
sortable: true,
@@ -103,7 +103,7 @@ const dueDayColumns = ref([
},
{
name: 'landed',
- label: 'invoiceIn.summary.foreignValue',
+ label: 'InvoiceIn.summary.foreignValue',
field: (row) => row.foreignValue,
format: (val) => val && toCurrency(val, currency.value),
sortable: true,
@@ -114,7 +114,7 @@ const dueDayColumns = ref([
const intrastatColumns = ref([
{
name: 'code',
- label: 'invoiceIn.summary.code',
+ label: 'InvoiceIn.summary.code',
field: (row) => {
return `${row.intrastat.id}: ${row.intrastat?.description}`;
},
@@ -123,21 +123,21 @@ const intrastatColumns = ref([
},
{
name: 'amount',
- label: 'invoiceIn.list.amount',
+ label: 'InvoiceIn.list.amount',
field: (row) => toCurrency(row.amount),
sortable: true,
align: 'left',
},
{
name: 'net',
- label: 'invoiceIn.summary.net',
+ label: 'InvoiceIn.summary.net',
field: (row) => row.net,
sortable: true,
align: 'left',
},
{
name: 'stems',
- label: 'invoiceIn.summary.stems',
+ label: 'InvoiceIn.summary.stems',
field: (row) => row.stems,
format: (value) => value,
sortable: true,
@@ -145,7 +145,7 @@ const intrastatColumns = ref([
},
{
name: 'landed',
- label: 'invoiceIn.summary.country',
+ label: 'InvoiceIn.summary.country',
field: (row) => row.country?.code,
format: (value) => value,
sortable: true,
@@ -210,7 +210,7 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
/>
@@ -221,14 +221,18 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
-
+
+
@@ -239,21 +243,22 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
+
@@ -263,18 +268,18 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
/>
-
+
@@ -285,11 +290,11 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
-
+
`#/invoice-in/${entityId.value}/${param}`;
:color="amountsNotMatch ? 'negative' : 'transparent'"
:title="
amountsNotMatch
- ? t('invoiceIn.summary.noMatch')
- : t('invoiceIn.summary.dueTotal')
+ ? t('InvoiceIn.summary.noMatch')
+ : t('InvoiceIn.summary.dueTotal')
"
>
{{ toCurrency(entity.totals.totalDueDay) }}
@@ -309,7 +314,7 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
-
+
`#/invoice-in/${entityId.value}/${param}`;
-
+
@@ -395,7 +400,7 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
arrayData.store.data);
-const invoiceId = +useRoute().params.id;
const currency = computed(() => invoiceIn.value?.currency?.code);
const expenses = ref([]);
const sageTaxTypes = ref([]);
@@ -39,9 +41,8 @@ const columns = computed(() => [
options: expenses.value,
model: 'expenseFk',
optionValue: 'id',
- optionLabel: 'id',
+ optionLabel: (row) => `${row.id}: ${row.name}`,
sortable: true,
- tabIndex: 1,
align: 'left',
},
{
@@ -50,7 +51,6 @@ const columns = computed(() => [
field: (row) => row.taxableBase,
model: 'taxableBase',
sortable: true,
- tabIndex: 2,
align: 'left',
},
{
@@ -60,9 +60,8 @@ const columns = computed(() => [
options: sageTaxTypes.value,
model: 'taxTypeSageFk',
optionValue: 'id',
- optionLabel: 'id',
+ optionLabel: (row) => `${row.id}: ${row.vat}`,
sortable: true,
- tabindex: 3,
align: 'left',
},
{
@@ -72,16 +71,14 @@ const columns = computed(() => [
options: sageTransactionTypes.value,
model: 'transactionTypeSageFk',
optionValue: 'id',
- optionLabel: 'id',
+ optionLabel: (row) => `${row.id}: ${row.transaction}`,
sortable: true,
- tabIndex: 4,
align: 'left',
},
{
name: 'rate',
label: t('Rate'),
sortable: true,
- tabIndex: 5,
field: (row) => taxRate(row, row.taxTypeSageFk),
align: 'left',
},
@@ -89,7 +86,6 @@ const columns = computed(() => [
name: 'foreignvalue',
label: t('Foreign value'),
sortable: true,
- tabIndex: 6,
field: (row) => row.foreignValue,
align: 'left',
},
@@ -106,7 +102,7 @@ const filter = {
'transactionTypeSageFk',
],
where: {
- invoiceInFk: invoiceId,
+ invoiceInFk: route.params.id,
},
};
@@ -120,14 +116,20 @@ function taxRate(invoiceInTax) {
const taxTypeSage = taxRateSelection?.rate ?? 0;
const taxableBase = invoiceInTax?.taxableBase ?? 0;
- return (taxTypeSage / 100) * taxableBase;
+ return ((taxTypeSage / 100) * taxableBase).toFixed(2);
}
-const formatOpt = (row, { model, options }, prop) => {
- const obj = row[model];
- const option = options.find(({ id }) => id == obj);
- return option ? `${obj}:${option[prop]}` : '';
-};
+function autocompleteExpense(evt, row, col) {
+ const val = evt.target.value;
+ if (!val) return;
+
+ const param = isNaN(val) ? row[col.model] : val;
+ const lookup = expenses.value.find(
+ ({ id }) => id == useAccountShortToStandard(param)
+ );
+
+ if (lookup) row[col.model] = lookup;
+}
{
data-key="InvoiceInTaxes"
url="InvoiceInTaxes"
:filter="filter"
- :data-required="{ invoiceInFk: invoiceId }"
+ :data-required="{ invoiceInFk: $route.params.id }"
auto-load
v-model:selected="rowsSelected"
- :go-to="`/invoice-in/${invoiceId}/due-day`"
+ :go-to="`/invoice-in/${$route.params.id}/due-day`"
>
{
:option-label="col.optionLabel"
:filter-options="['id', 'name']"
:tooltip="t('Create a new expense')"
+ @keydown.tab="autocompleteExpense($event, row, col)"
>
@@ -187,13 +190,7 @@ const formatOpt = (row, { model, options }, prop) => {
- {{ currency }}
{
:option-value="col.optionValue"
:option-label="col.optionLabel"
:filter-options="['id', 'vat']"
- :hide-selected="false"
- :fill-input="false"
- :display-value="formatOpt(row, col, 'vat')"
+ data-cy="vat-sageiva"
>
@@ -233,11 +228,6 @@ const formatOpt = (row, { model, options }, prop) => {
:option-value="col.optionValue"
:option-label="col.optionLabel"
:filter-options="['id', 'transaction']"
- :autofocus="col.tabIndex == 1"
- input-debounce="0"
- :hide-selected="false"
- :fill-input="false"
- :display-value="formatOpt(row, col, 'transaction')"
>
@@ -262,6 +252,16 @@ const formatOpt = (row, { model, options }, prop) => {
}"
:disable="!isNotEuro(currency)"
v-model="row.foreignValue"
+ @update:model-value="
+ async (val) => {
+ if (!isNotEuro(currency)) return;
+ row.taxableBase = await getExchange(
+ val,
+ row.currencyFk,
+ invoiceIn.issued
+ );
+ }
+ "
/>
@@ -305,7 +305,7 @@ const formatOpt = (row, { model, options }, prop) => {
v-model="props.row['expenseFk']"
:options="expenses"
option-value="id"
- option-label="name"
+ :option-label="(row) => `${row.id}:${row.name}`"
:filter-options="['id', 'name']"
:tooltip="t('Create a new expense')"
>
@@ -339,7 +339,7 @@ const formatOpt = (row, { model, options }, prop) => {
v-model="props.row['taxTypeSageFk']"
:options="sageTaxTypes"
option-value="id"
- option-label="vat"
+ :option-label="(row) => `${row.id}:${row.vat}`"
:filter-options="['id', 'vat']"
>
@@ -362,7 +362,9 @@ const formatOpt = (row, { model, options }, prop) => {
v-model="props.row['transactionTypeSageFk']"
:options="sageTransactionTypes"
option-value="id"
- option-label="transaction"
+ :option-label="
+ (row) => `${row.id}:${row.transaction}`
+ "
:filter-options="['id', 'transaction']"
>
@@ -418,11 +420,6 @@ const formatOpt = (row, { model, options }, prop) => {
.bg {
background-color: var(--vn-light-gray);
}
-
-:deep(.q-table tr td:nth-child(n + 4):nth-child(-n + 5) input) {
- display: none;
-}
-
@media (max-width: $breakpoint-xs) {
.q-dialog {
.q-card {
diff --git a/src/pages/InvoiceIn/InvoiceInCreate.vue b/src/pages/InvoiceIn/InvoiceInCreate.vue
index c809e032b..200997f65 100644
--- a/src/pages/InvoiceIn/InvoiceInCreate.vue
+++ b/src/pages/InvoiceIn/InvoiceInCreate.vue
@@ -83,7 +83,7 @@ const redirectToInvoiceInBasicData = (__, { id }) => {
@@ -97,10 +97,10 @@ const redirectToInvoiceInBasicData = (__, { id }) => {
map-options
hide-selected
:required="true"
- :rules="validate('invoiceIn.companyFk')"
+ :rules="validate('InvoiceIn.companyFk')"
/>
diff --git a/src/pages/InvoiceIn/InvoiceInFilter.vue b/src/pages/InvoiceIn/InvoiceInFilter.vue
index 130a77960..653692026 100644
--- a/src/pages/InvoiceIn/InvoiceInFilter.vue
+++ b/src/pages/InvoiceIn/InvoiceInFilter.vue
@@ -1,41 +1,66 @@
- (activities = data)"
- />
-
-
+
+
- {{ t(`params.${tag.label}`) }}:
+ {{ getLocale(tag.label) }}:
{{ formatFn(tag.value) }}
-
+
-
+
-
+
+
+
+
+
+ handleDaysAgo(params, val)"
+ @remove="(val) => handleDaysAgo(params, val)"
+ />
@@ -44,20 +69,18 @@ const activities = ref([]);
v-model="params.supplierFk"
url="Suppliers"
:fields="['id', 'nickname']"
- :label="t('params.supplierFk')"
- option-value="id"
+ :label="getLocale('supplierFk')"
option-label="nickname"
dense
outlined
rounded
- :filter-options="['id', 'name']"
/>
+
+
+
+
+
-
-
-
-
-en:
- params:
- search: Id or supplier name
- supplierRef: Supplier ref.
- supplierFk: Supplier
- fi: Supplier fiscal id
- clientFk: Customer
- amount: Amount
- created: Created
- awb: AWB
- dued: Dued
- serialNumber: Serial Number
- serial: Serial
- account: Ledger account
- isBooked: is booked
- correctedFk: Rectified
- issued: Issued
- to: To
- from: From
- awbCode: AWB
- correctingFk: Rectificative
- supplierActivityFk: Supplier activity
-es:
- params:
- search: Id o nombre proveedor
- supplierRef: Ref. proveedor
- supplierFk: Proveedor
- clientFk: Cliente
- fi: CIF proveedor
- serialNumber: Num. serie
- serial: Serie
- awb: AWB
- amount: Importe
- issued: Emitida
- isBooked: Contabilizada
- account: Cuenta contable
- created: Creada
- dued: Vencida
- correctedFk: Rectificada
- correctingFk: Rectificativa
- supplierActivityFk: Actividad proveedor
- from: Desde
- to: Hasta
- From: Desde
- To: Hasta
- Amount: Importe
- Issued: Fecha factura
- Id or supplier: Id o proveedor
-
diff --git a/src/pages/InvoiceIn/InvoiceInList.vue b/src/pages/InvoiceIn/InvoiceInList.vue
index 8d658bee3..0af2e68b2 100644
--- a/src/pages/InvoiceIn/InvoiceInList.vue
+++ b/src/pages/InvoiceIn/InvoiceInList.vue
@@ -2,6 +2,7 @@
import { ref, computed, onMounted, onUnmounted } from 'vue';
import { useI18n } from 'vue-i18n';
import { useStateStore } from 'stores/useStateStore';
+import { useState } from 'src/composables/useState';
import { downloadFile } from 'src/composables/downloadFile';
import { toDate, toCurrency } from 'src/filters/index';
import InvoiceInFilter from './InvoiceInFilter.vue';
@@ -14,8 +15,10 @@ import VnTable from 'src/components/VnTable/VnTable.vue';
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 FetchData from 'src/components/FetchData.vue';
const stateStore = useStateStore();
+const user = useState().getUser();
const { viewSummary } = useSummaryDialog();
const { t } = useI18n();
@@ -23,7 +26,14 @@ onMounted(async () => (stateStore.rightDrawer = true));
onUnmounted(() => (stateStore.rightDrawer = false));
const tableRef = ref();
+const companies = ref([]);
const cols = computed(() => [
+ {
+ align: 'left',
+ name: 'isBooked',
+ label: t('InvoiceIn.isBooked'),
+ columnFilter: false,
+ },
{
align: 'left',
name: 'id',
@@ -32,7 +42,7 @@ const cols = computed(() => [
{
align: 'left',
name: 'supplierFk',
- label: t('invoiceIn.list.supplier'),
+ label: t('InvoiceIn.list.supplier'),
columnFilter: {
component: 'select',
attrs: {
@@ -45,16 +55,16 @@ const cols = computed(() => [
{
align: 'left',
name: 'supplierRef',
- label: t('invoiceIn.list.supplierRef'),
+ label: t('InvoiceIn.list.supplierRef'),
},
{
align: 'left',
name: 'serial',
- label: t('invoiceIn.serial'),
+ label: t('InvoiceIn.serial'),
},
{
align: 'left',
- label: t('invoiceIn.list.issued'),
+ label: t('InvoiceIn.list.issued'),
name: 'issued',
component: null,
columnFilter: {
@@ -64,21 +74,38 @@ const cols = computed(() => [
},
{
align: 'left',
- name: 'isBooked',
- label: t('invoiceIn.isBooked'),
- columnFilter: false,
+ label: t('InvoiceIn.list.dueDated'),
+ name: 'dueDated',
+ component: null,
+ columnFilter: {
+ component: 'date',
+ },
+ format: (row, dashIfEmpty) => dashIfEmpty(toDate(row.dueDated)),
},
{
align: 'left',
name: 'awbCode',
- label: t('invoiceIn.list.awb'),
+ label: t('InvoiceIn.list.awb'),
},
{
align: 'left',
name: 'amount',
- label: t('invoiceIn.list.amount'),
+ label: t('InvoiceIn.list.amount'),
format: ({ amount }) => toCurrency(amount),
},
+ {
+ name: 'companyFk',
+ label: t('globals.company'),
+ columnFilter: {
+ component: 'select',
+ attrs: {
+ url: 'Companies',
+ fields: ['id', 'code'],
+ optionLabel: 'code',
+ },
+ },
+ format: (row) => row.code,
+ },
{
align: 'right',
name: 'tableActions',
@@ -87,6 +114,7 @@ const cols = computed(() => [
title: t('components.smartCard.openSummary'),
icon: 'preview',
type: 'submit',
+ isPrimary: true,
action: (row) => viewSummary(row.id, InvoiceInSummary),
},
{
@@ -101,6 +129,7 @@ const cols = computed(() => [
]);
+ (companies = data)" auto-load />
@@ -116,7 +145,7 @@ const cols = computed(() => [
urlCreate: 'InvoiceIns',
title: t('globals.createInvoiceIn'),
onDataSaved: ({ id }) => tableRef.redirect(id),
- formInitialData: {},
+ formInitialData: { companyFk: user.companyFk, issued: Date.vnNew() },
}"
redirect="invoice-in"
:columns="cols"
@@ -151,7 +180,7 @@ const cols = computed(() => [
[
option-label="code"
:required="true"
/>
-
+
diff --git a/src/pages/InvoiceIn/Serial/InvoiceInSerial.vue b/src/pages/InvoiceIn/Serial/InvoiceInSerial.vue
index 4eb9fa69d..a8fb3b0c8 100644
--- a/src/pages/InvoiceIn/Serial/InvoiceInSerial.vue
+++ b/src/pages/InvoiceIn/Serial/InvoiceInSerial.vue
@@ -58,6 +58,14 @@ onBeforeMount(async () => {
:right-search="false"
:user-params="{ daysAgo }"
:disable-option="{ card: true }"
+ :row-click="
+ (row) => {
+ $router.push({
+ name: 'InvoiceInList',
+ query: { table: JSON.stringify({ serial: row.serial }) },
+ });
+ }
+ "
auto-load
/>
diff --git a/src/pages/InvoiceIn/Serial/InvoiceInSerialFilter.vue b/src/pages/InvoiceIn/Serial/InvoiceInSerialFilter.vue
index 4f8c9d70b..19ed73e50 100644
--- a/src/pages/InvoiceIn/Serial/InvoiceInSerialFilter.vue
+++ b/src/pages/InvoiceIn/Serial/InvoiceInSerialFilter.vue
@@ -8,7 +8,11 @@ defineProps({ dataKey: { type: String, required: true } });
const { t } = useI18n();
-
+
{{ t(`params.${tag.label}`) }}:
diff --git a/src/pages/InvoiceIn/locale/en.yml b/src/pages/InvoiceIn/locale/en.yml
index b39511f29..ef7e31ac3 100644
--- a/src/pages/InvoiceIn/locale/en.yml
+++ b/src/pages/InvoiceIn/locale/en.yml
@@ -1,4 +1,4 @@
-invoiceIn:
+InvoiceIn:
serial: Serial
isBooked: Is booked
list:
@@ -7,8 +7,11 @@ invoiceIn:
supplierRef: Supplier ref.
file: File
issued: Issued
+ dueDated: Due dated
awb: AWB
amount: Amount
+ descriptor:
+ ticketList: Ticket list
card:
client: Client
company: Company
@@ -39,3 +42,9 @@ invoiceIn:
net: Net
stems: Stems
country: Country
+ params:
+ search: Id or supplier name
+ account: Ledger account
+ correctingFk: Rectificative
+ correctedFk: Corrected
+ isBooked: Is booked
diff --git a/src/pages/InvoiceIn/locale/es.yml b/src/pages/InvoiceIn/locale/es.yml
index 5f483dd08..ed5943489 100644
--- a/src/pages/InvoiceIn/locale/es.yml
+++ b/src/pages/InvoiceIn/locale/es.yml
@@ -1,15 +1,17 @@
-invoiceIn:
+InvoiceIn:
serial: Serie
isBooked: Contabilizada
list:
ref: Referencia
supplier: Proveedor
supplierRef: Ref. proveedor
- shortIssued: F. emisión
+ issued: F. emisión
+ dueDated: F. vencimiento
file: Fichero
- issued: Fecha emisión
awb: AWB
amount: Importe
+ descriptor:
+ ticketList: Listado de tickets
card:
client: Cliente
company: Empresa
@@ -38,3 +40,8 @@ invoiceIn:
net: Neto
stems: Tallos
country: País
+ params:
+ search: Id o nombre proveedor
+ account: Cuenta contable
+ correctingFk: Rectificativa
+ correctedFk: Rectificada
diff --git a/src/pages/InvoiceOut/InvoiceOutGlobalForm.vue b/src/pages/InvoiceOut/InvoiceOutGlobalForm.vue
index 3fd3104bf..e6c689523 100644
--- a/src/pages/InvoiceOut/InvoiceOutGlobalForm.vue
+++ b/src/pages/InvoiceOut/InvoiceOutGlobalForm.vue
@@ -115,6 +115,9 @@ onMounted(async () => {
{
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 1b0342668..a1788617f 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/ItemDescriptor.vue b/src/pages/Item/Card/ItemDescriptor.vue
index c51b320b5..4705525fb 100644
--- a/src/pages/Item/Card/ItemDescriptor.vue
+++ b/src/pages/Item/Card/ItemDescriptor.vue
@@ -16,7 +16,7 @@ import { cloneItem } from 'src/pages/Item/composables/cloneItem';
const $props = defineProps({
id: {
- type: Number,
+ type: [Number, String],
required: false,
default: null,
},
@@ -29,7 +29,7 @@ const $props = defineProps({
default: null,
},
saleFk: {
- type: Number,
+ type: [Number, String],
default: null,
},
warehouseFk: {
@@ -61,7 +61,7 @@ onMounted(async () => {
const data = ref(useCardDescription());
const setData = async (entity) => {
if (!entity) return;
- data.value = useCardDescription(entity.name, entity.id);
+ data.value = useCardDescription(entity?.name, entity?.id);
await updateStock();
};
diff --git a/src/pages/Item/Card/ItemDescriptorImage.vue b/src/pages/Item/Card/ItemDescriptorImage.vue
index 735e5eb4f..05185c589 100644
--- a/src/pages/Item/Card/ItemDescriptorImage.vue
+++ b/src/pages/Item/Card/ItemDescriptorImage.vue
@@ -16,7 +16,7 @@ const $props = defineProps({
default: null,
},
entityId: {
- type: String,
+ type: [String, Number],
default: null,
},
showEditButton: {
@@ -67,7 +67,7 @@ const handlePhotoUpdated = (evt = false) => {
-
+
diff --git a/src/pages/Item/Card/ItemLastEntries.vue b/src/pages/Item/Card/ItemLastEntries.vue
index 22fb9adc7..c2df553c3 100644
--- a/src/pages/Item/Card/ItemLastEntries.vue
+++ b/src/pages/Item/Card/ItemLastEntries.vue
@@ -1,21 +1,21 @@
-
@@ -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 27e265e6b..7ad60c9e0 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 db90ba06f..e1b97d7c9 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);
+};
@@ -77,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,
@@ -126,7 +128,7 @@ const insertTag = (rows) => {
{
v-model="row.value"
:label="t('itemTags.value')"
:is-clearable="false"
+ @keyup.enter.stop="submitTags(row)"
/>
{
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 84b5f63f4..8060481f0 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/ItemList.vue b/src/pages/Item/ItemList.vue
index 30b4893bd..e02afa3ba 100644
--- a/src/pages/Item/ItemList.vue
+++ b/src/pages/Item/ItemList.vue
@@ -55,17 +55,6 @@ const columns = computed(() => [
label: '',
name: 'image',
align: 'left',
- columnField: {
- component: VnImg,
- attrs: ({ row }) => {
- return {
- id: row?.id,
- zoomResolution: '1600x900',
- zoom: true,
- class: 'rounded',
- };
- },
- },
columnFilter: false,
cardVisible: true,
},
@@ -184,7 +173,7 @@ const columns = computed(() => [
cardVisible: true,
},
{
- label: t('globals.origin'),
+ label: t('item.list.origin'),
name: 'origin',
align: 'left',
component: 'select',
@@ -228,7 +217,8 @@ const columns = computed(() => [
},
},
{
- label: t('item.list.weightByPiece'),
+ label: t('item.list.weight'),
+ toolTip: t('item.list.weightByPiece'),
name: 'weightByPiece',
align: 'left',
component: 'input',
@@ -322,7 +312,6 @@ const columns = computed(() => [
ref="tableRef"
data-key="ItemList"
url="Items/filter"
- url-create="Items"
:create="{
urlCreate: 'Items',
title: t('Create Item'),
@@ -333,12 +322,19 @@ const columns = computed(() => [
}"
:order="['isActive DESC', 'name', 'id']"
:columns="columns"
- auto-load
redirect="Item"
:is-editable="false"
:right-search="false"
- :filer="itemFilter"
+ :filter="itemFilter"
>
+
+
+
{{ row.id }}
@@ -348,7 +344,7 @@ const columns = computed(() => [
{{ row.userName }}
-
+
@@ -372,6 +368,8 @@ const columns = computed(() => [
es:
New item: Nuevo artículo
+ Create Item: Crear artículo
+ You can search by id: Puedes buscar por id
Preview: Vista previa
Regularize stock: Regularizar stock
diff --git a/src/pages/Item/ItemListFilter.vue b/src/pages/Item/ItemListFilter.vue
index c8357ba33..484265b49 100644
--- a/src/pages/Item/ItemListFilter.vue
+++ b/src/pages/Item/ItemListFilter.vue
@@ -199,7 +199,17 @@ onMounted(async () => {
dense
outlined
rounded
- />
+ >
+
+
+
+ {{
+ t(`params.${scope.opt?.name}`)
+ }}
+
+
+
+
@@ -434,6 +444,13 @@ en:
description: Description
name: Name
id: Id
+ Accessories: Accessories
+ Artificial: Artificial
+ Flower: Flower
+ Fruit: Fruit
+ Green: Green
+ Handmade: Handmade
+ Plant: Plant
es:
More fields: Más campos
params:
@@ -450,4 +467,11 @@ es:
description: Descripción
name: Nombre
id: Id
+ Accessories: Accesorios
+ Artificial: Artificial
+ Flower: Flor
+ Fruit: Fruta
+ Green: Verde
+ Handmade: Hecho a mano
+ Plant: Planta
diff --git a/src/pages/Item/ItemRequest.vue b/src/pages/Item/ItemRequest.vue
index ad6e5663e..4447d1bcf 100644
--- a/src/pages/Item/ItemRequest.vue
+++ b/src/pages/Item/ItemRequest.vue
@@ -11,8 +11,10 @@ import ItemRequestDenyForm from './ItemRequestDenyForm.vue';
import { toDate } from 'src/filters';
import VnTable from 'components/VnTable/VnTable.vue';
import VnInput from 'src/components/common/VnInput.vue';
-import RightMenu from 'src/components/common/RightMenu.vue';
+import VnInputNumber from 'src/components/common/VnInputNumber.vue';
import ItemRequestFilter from './ItemRequestFilter.vue';
+import RightMenu from 'src/components/common/RightMenu.vue';
+
const { t } = useI18n();
const { notify } = useNotify();
const stateStore = useStateStore();
@@ -216,7 +218,7 @@ const onDenyAccept = (_, responseData) => {
-
+
{
-
-
-
- {{ row.response }}
-
-
-
-
- {{ t('Discard') }}
-
-
-
+
+
+ {{ row.response }}
+
+
+
+
+ {{ t('Discard') }}
+
+
diff --git a/src/pages/Item/ItemRequestFilter.vue b/src/pages/Item/ItemRequestFilter.vue
index 8d8a1aa40..f23cadcad 100644
--- a/src/pages/Item/ItemRequestFilter.vue
+++ b/src/pages/Item/ItemRequestFilter.vue
@@ -1,11 +1,13 @@
@@ -129,33 +145,17 @@ const exprBuilder = (param, value) => {
-
-
-
-
- {{ scope.opt?.name }}
- {{ scope.opt?.nickname }},
- {{ scope.opt?.code }}
-
-
-
-
+ />
@@ -201,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
@@ -218,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/ItemTypeSearchbar.vue b/src/pages/Item/ItemType/ItemTypeSearchbar.vue
index 87903a517..749033d43 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/ItemTypeList.vue b/src/pages/Item/ItemTypeList.vue
index 149de482d..4cea931e2 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 78a1c3ff0..bd91ef745 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 5498f4458..b821d276a 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 2205666ec..82578a61f 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();
@@ -112,33 +113,16 @@ const getLocale = (label) => {
-
-
-
-
- {{ opt.name }}
-
- {{ `${opt.nickname}, ${opt.code}` }}
-
-
-
-
-
+
@@ -150,6 +134,7 @@ const getLocale = (label) => {
/>
+
{
/>
+
+
+
+
+
+
+
+
+
+
[
align: 'left',
format: (row) => row.practicalHour,
columnFilter: false,
+ dense: true,
},
{
label: t('salesTicketsTable.preparation'),
@@ -197,6 +203,7 @@ const columns = computed(() => [
'false-value': 0,
'true-value': 1,
},
+ component: false,
},
{
label: t('salesTicketsTable.zone'),
@@ -213,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',
@@ -226,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',
@@ -257,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 timeDiff = today - timeTicket;
-
- if (timeDiff == 0) return { color: 'warning', 'text-color': 'black' };
- if (timeDiff < 0) return { color: 'success', 'text-color': 'black' };
- return { color: 'transparent', 'text-color': 'white' };
-};
-
let refreshTimer = null;
const autoRefreshHandler = (value) => {
@@ -286,14 +322,6 @@ const totalPriceColor = (ticket) => {
if (total > 0 && total < 50) return 'warning';
};
-const formatShippedDate = (date) => {
- if (!date) return '-';
- const dateSplit = date.split('T');
- const [year, month, day] = dateSplit[0].split('-');
- const newDate = new Date(year, month - 1, day);
- return toDateFormat(newDate);
-};
-
const openTab = (id) =>
window.open(`#/ticket/${id}/sale`, '_blank', 'noopener, noreferrer');
@@ -325,6 +353,33 @@ const openTab = (id) =>
auto-load
@on-fetch="(data) => (zoneOpts = data)"
/>
+ (ItemPackingTypeOpts = data)"
+ />
+ (DepartmentOpts = data)"
+ />
+ (PayMethodOpts = data)"
+ />
@@ -389,13 +444,7 @@ const openTab = (id) =>
-
- {{ formatShippedDate(row.shippedDate) }}
-
+
diff --git a/src/pages/Monitor/locale/en.yml b/src/pages/Monitor/locale/en.yml
index ff4031654..e61a24979 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 a2ed3bb1a..30afb1904 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/OrderCatalog.vue b/src/pages/Order/Card/OrderCatalog.vue
index 2ede429a0..da2e88aa9 100644
--- a/src/pages/Order/Card/OrderCatalog.vue
+++ b/src/pages/Order/Card/OrderCatalog.vue
@@ -1,7 +1,7 @@
@@ -103,16 +88,14 @@ provide('onItemSaved', onItemSaved);
:info="t('You can search items by name or id')"
:search-remove-params="false"
/>
-
-
-
-
-
+
+
+
{
params.typeFk = null;
params.categoryFk = category.id;
await loadTypes(category?.id);
- await search();
};
const loadTypes = async (id) => {
diff --git a/src/pages/Order/Card/OrderCatalogItemDialog.vue b/src/pages/Order/Card/OrderCatalogItemDialog.vue
index b1cd8ed6b..163b036eb 100644
--- a/src/pages/Order/Card/OrderCatalogItemDialog.vue
+++ b/src/pages/Order/Card/OrderCatalogItemDialog.vue
@@ -1,12 +1,12 @@
@@ -90,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"
>
@@ -110,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 138fcc40f..e0c613aed 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 917369919..fcd1ef2e4 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 c47a9b2ec..dfeb0f6e2 100644
--- a/src/pages/Order/OrderList.vue
+++ b/src/pages/Order/OrderList.vue
@@ -1,7 +1,7 @@
diff --git a/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue b/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue
index df84add93..cf4481537 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 b88dd89e8..64815752a 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) }}
-
+
(formData.userFk = user.value.id);
option-label="name"
option-value="id"
/>
-
-
-
-
-
- {{ opt.name }}
-
-
- {{ opt.nickname }}, {{ opt.code }}
-
-
-
-
+
diff --git a/src/pages/Ticket/Card/TicketDescriptorMenu.vue b/src/pages/Ticket/Card/TicketDescriptorMenu.vue
index 60a703f84..38e2af612 100644
--- a/src/pages/Ticket/Card/TicketDescriptorMenu.vue
+++ b/src/pages/Ticket/Card/TicketDescriptorMenu.vue
@@ -1,6 +1,6 @@
{{ t('Show Proforma') }}
+
+
+
+
+ {{ t('Restore ticket') }}
+
diff --git a/src/pages/Ticket/Card/TicketExpedition.vue b/src/pages/Ticket/Card/TicketExpedition.vue
index b7f1f4dd0..7da049124 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/TicketPurchaseRequest.vue b/src/pages/Ticket/Card/TicketPurchaseRequest.vue
index 3b9d6a25b..4e77c7277 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 8e3c99aa4..8aa785c74 100644
--- a/src/pages/Ticket/Card/TicketSale.vue
+++ b/src/pages/Ticket/Card/TicketSale.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 }}
-
-
+
[
@@ -465,6 +466,7 @@ watch(
color="primary"
name="vn:agency-term"
size="xs"
+ class="q-mr-xs"
>
@@ -483,6 +485,14 @@ watch(
+
+ {{ t('advanceTickets.clonedSales') }}
+
diff --git a/src/pages/Ticket/TicketAdvanceFilter.vue b/src/pages/Ticket/TicketAdvanceFilter.vue
index a1d301f35..6d5c7726e 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 bde27f30e..9c8b9f1a3 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 ffe967272..d28b0af71 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 eb03a4927..823f74fc5 100644
--- a/src/pages/Ticket/TicketList.vue
+++ b/src/pages/Ticket/TicketList.vue
@@ -8,13 +8,11 @@ import { useQuasar } from 'quasar';
import { toDate, toCurrency, dashIfEmpty } from 'src/filters/index';
import useNotify from 'src/composables/useNotify';
import TicketSummary from './Card/TicketSummary.vue';
-import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
import VnTable from 'src/components/VnTable/VnTable.vue';
import VnSelect from 'src/components/common/VnSelect.vue';
import VnInputDate from 'src/components/common/VnInputDate.vue';
import VnRow from 'src/components/ui/VnRow.vue';
-import RightMenu from 'src/components/common/RightMenu.vue';
import TicketFilter from './TicketFilter.vue';
import VnInput from 'src/components/common/VnInput.vue';
import FetchData from 'src/components/FetchData.vue';
@@ -23,6 +21,7 @@ import ZoneDescriptorProxy from 'src/pages/Zone/Card/ZoneDescriptorProxy.vue';
import { toTimeFormat } from 'src/filters/date';
import InvoiceOutDescriptorProxy from 'src/pages/InvoiceOut/Card/InvoiceOutDescriptorProxy.vue';
import TicketProblems from 'src/components/TicketProblems.vue';
+import VnSection from 'src/components/common/VnSection.vue';
const route = useRoute();
const router = useRouter();
@@ -66,6 +65,7 @@ const dialogData = ref();
const companiesOptions = ref([]);
const accountingOptions = ref([]);
const amountToReturn = ref();
+const dataKey = 'TicketList';
const columns = computed(() => [
{
@@ -452,223 +452,228 @@ function setReference(data) {
@on-fetch="(data) => (accountingOptions = data)"
auto-load
/>
-
-
-
+
+
-
-
-
-
-
-
-
- {{ dashIfEmpty(row.userName) }}
-
-
-
-
-
-
- {{ toDate(row.shippedDate) }}
-
-
-
-
-
- {{ row.nickname }}
-
-
-
-
-
- {{ row.addressNickname }}
-
-
-
-
-
-
- {{ row.refFk }}
-
-
-
-
-
- {{ row.state }}
-
-
-
- {{ row.state }}
-
-
-
-
- {{ dashIfEmpty(row.zoneName) }}
-
-
-
-
-
+
- {{ row.totalWithVat }}
-
-
-
-
- onClientSelected(data)"
- :sort-by="'id ASC'"
- >
-
-
-
-
- {{ scope.opt.name }}
-
-
- {{ `#${scope.opt.id}` }}
-
-
-
-
-
-
-
- fetchAvailableAgencies(data)"
- >
-
-
+
+
+
+
+ {{ dashIfEmpty(row.userName) }}
+
+
+
+
+
+
+ {{ toDate(row.shippedDate) }}
+
+
+
+
+
+ {{ row.nickname }}
+
+
+
+
+
+ {{ row.addressNickname }}
+
+
+
+
+
+
+ {{ row.refFk }}
+
+
+
+
+
+ {{ row.state }}
+
+
+
+ {{ row.state }}
+
+
+
+
+ {{ dashIfEmpty(row.zoneName) }}
+
+
+
+
+
+ {{ row.totalWithVat }}
+
+
+
+
+ onClientSelected(data)"
+ :sort-by="'id ASC'"
>
-
-
-
-
-
+
+
+
+ {{ scope.opt.name }}
+
+
+ {{ `#${scope.opt.id}` }}
+
+
+
+
+
+
+
+ fetchAvailableAgencies(data)"
+ >
+
+
- {{
- `${
- !scope.opt?.isActive
- ? t('basicData.inactive')
- : ''
- } `
- }}
-
- {{ scope.opt?.nickname }}:
- {{ scope.opt?.street }}, {{ scope.opt?.city }}
-
-
-
-
-
-
-
-
-
- fetchAvailableAgencies(data)"
- />
-
-
-
-
- fetchAvailableAgencies(data)"
- />
-
-
-
-
-
-
-
+
+
+
+
+
+ {{
+ `${
+ !scope.opt?.isActive
+ ? t('basicData.inactive')
+ : ''
+ } `
+ }}
+
+ {{ scope.opt?.nickname }}:
+ {{ scope.opt?.street }},
+ {{ scope.opt?.city }}
+
+
+
+
+
+
+
+
+
+ fetchAvailableAgencies(data)"
+ />
+
+
+
+
+ fetchAvailableAgencies(data)"
+ />
+
+
+
+
+
+
+
+
+
-
+
-import { onMounted, ref, computed, onUnmounted } from 'vue';
+import { onMounted, ref, computed } from 'vue';
import { useI18n } from 'vue-i18n';
import VnSelect from 'src/components/common/VnSelect.vue';
import VnSelectCache from 'src/components/common/VnSelectCache.vue';
@@ -170,8 +170,6 @@ onMounted(async () => {
const filteredColumns = columns.value.filter((col) => col.name !== 'actions');
allColumnNames.value = filteredColumns.map((col) => col.name);
});
-
-onUnmounted(() => (stateStore.rightDrawer = false));
diff --git a/src/pages/Ticket/locale/en.yml b/src/pages/Ticket/locale/en.yml
index 56cc798ba..f11b32c3a 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 bb068ac5b..945da8367 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/ExtraCommunity.vue b/src/pages/Travel/ExtraCommunity.vue
index 675a44979..c23b6b0a1 100644
--- a/src/pages/Travel/ExtraCommunity.vue
+++ b/src/pages/Travel/ExtraCommunity.vue
@@ -704,6 +704,7 @@ en:
physicKg: Phy. KG
shipped: W. shipped
landed: W. landed
+ notes: Notes
es:
searchExtraCommunity: Buscar por envío extra comunitario
@@ -711,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/TravelList.vue b/src/pages/Travel/TravelList.vue
index 70e81aae2..f77beff21 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;
});
@@ -295,6 +294,7 @@ es:
Search travel: Buscar envio
Clone: Clonar
Add entry: Añadir Entrada
+ Create Travels: Crear envíos