Merge branch 'dev' into 6629-addressObservation
This commit is contained in:
commit
6bc6797eba
79
CHANGELOG.md
79
CHANGELOG.md
|
@ -1,3 +1,82 @@
|
||||||
|
# Version 25.00 - 2025-01-14
|
||||||
|
|
||||||
|
### Added 🆕
|
||||||
|
|
||||||
|
- chore: refs #7056 move test by:jorgep
|
||||||
|
- feat: refs #7050 7050 add object check by:Jtubau
|
||||||
|
- feat: refs #7050 7050 add test to isEmpty() by:Jtubau
|
||||||
|
- feat: refs #7056 add tests in FormModel by:jorgep
|
||||||
|
- feat: refs #7056 update route meta information and add FormModel tests by:jorgep
|
||||||
|
- feat: refs #7074 tests for fns setData(), parseDms() and showFormDialog() (7074-makeFrontTestToVnDmsList) by:Jtubau
|
||||||
|
- feat: refs #7079 created VnLocation front test by:provira
|
||||||
|
- feat: refs #7189 add Accept-Language header to axios requests by:jorgep
|
||||||
|
- feat: refs #7924 add custom inspection checkbox and localization support by:jgallego
|
||||||
|
- feat: refs #7924 update custom inspection label for clarity in English and Spanish locales by:jgallego
|
||||||
|
- feat: refs #8004 enhance FetchedTags component with column support and styling updates by:pablone
|
||||||
|
- feat: refs #8004 hide rightFilter by:pablone
|
||||||
|
- feat: refs #8246 added new field in list by:Jon
|
||||||
|
- feat: refs #8266 added descriptor to item name by:jtubau
|
||||||
|
- feat: refs #8293 add zone filter by:Jtubau
|
||||||
|
- feat: refs #8293 include zone data in each record by:Jtubau
|
||||||
|
- fix: refs #8004 more list style issues by:pablone
|
||||||
|
- fix: refs #8004 some style issues on all list by:pablone
|
||||||
|
- style: refs #8004 update layout and styling in FetchedTags and ItemList components by:pablone
|
||||||
|
- style: update CustomerBalance.vue to set label color by:jgallego
|
||||||
|
|
||||||
|
### Changed 📦
|
||||||
|
|
||||||
|
- perf: order by:alexm
|
||||||
|
- perf: redirect transition list to card by:alexm
|
||||||
|
- perf: refs #8201 onDataSaved fetch by:Jon
|
||||||
|
- perf: revert processData by:alexm
|
||||||
|
- perf: simplify if by:alexm
|
||||||
|
- perf: simplify if (perf_redirectTransition) by:alexm
|
||||||
|
- refactor: item fixedPrice by:Jon
|
||||||
|
- refactor: refs #7050 refactorize by:jtubau
|
||||||
|
- refactor: refs #7050 removed blank spaces by:jtubau
|
||||||
|
- refactor: refs #7052 move EditTableCellValueForm tests to a new location and enhance test coverage by:jgallego
|
||||||
|
- refactor: refs #7052 remove unnecessary console logs from EditTableCellValueForm tests by:jgallego
|
||||||
|
- refactor: refs #7074 move dms constant to global scope by:Jtubau
|
||||||
|
- refactor: refs #7079 removed useless code by:provira
|
||||||
|
- refactor: refs #7924 simplify custom inspection icon rendering in ExtraCommunity.vue by:jgallego
|
||||||
|
- refactor: refs #8004 remove console log from CardSummary component on mount by:pablone
|
||||||
|
- refactor: refs #8004 remove consoleLogs by:pablone
|
||||||
|
- refactor: refs #8004 remove unused stateStore import in InvoiceInList.vue by:pablone
|
||||||
|
- refactor: refs #8004 remove unused travelFilterRef and chip definition in TravelList.vue by:pablone
|
||||||
|
- refactor: refs #8004 replace VnSelect with VnSelectWorker in CustomerList component by:pablone
|
||||||
|
- refactor: refs #8201 added onMounted to stablish the value to show icons by:Jon
|
||||||
|
- refactor: refs #8201 deleted condition by:Jon
|
||||||
|
- refactor: refs #8201 deleted log by:Jon
|
||||||
|
- refactor: refs #8201 deleted logs by:Jon
|
||||||
|
- refactor: refs #8266 8266 change expedition item name by:Jtubau
|
||||||
|
- refactor: refs #8266 change expedition label by:Jtubau
|
||||||
|
- refactor: refs #8293 remove redundant attributes by:Jtubau
|
||||||
|
- refactor: refs #8320 changed folder names from "specs" to "**tests**" by:provira
|
||||||
|
- refactor: refs #8320 moved front tests to their respective sections by:provira
|
||||||
|
- refactor: refs #8813 removed unused class property by:provira
|
||||||
|
|
||||||
|
### Fixed 🛠️
|
||||||
|
|
||||||
|
- fix: discount class by:PAU ROVIRA ROSALENY
|
||||||
|
- fix: duplicate transalation after test to dev by:alexm
|
||||||
|
- fix: fix translations by:carlossa
|
||||||
|
- fix: redirect to sales when confirming lines by:Jon
|
||||||
|
- fix: refs #7050 delete import added by mistake by:Jtubau
|
||||||
|
- fix: refs #7133 handleSalesModelValue function to handle empty input by:jorgep
|
||||||
|
- fix: refs #7189 update user language on sessionStorage by:jorgep
|
||||||
|
- fix: refs #7935 remove unused 'companyFk' column from InvoiceInList component by:jorgep
|
||||||
|
- fix: refs #8004 more list style issues by:pablone
|
||||||
|
- fix: refs #8004 some style issues on all list by:pablone
|
||||||
|
- fix: refs #8004 update label for daysOnward in TravelFilter component and add translations by:pablone
|
||||||
|
- fix: refs #8004 vnTable card with and add permanent labels by:pablone
|
||||||
|
- fix: refs #8201 added onDataSaved emi to refetch when cahnges are made by:Jon
|
||||||
|
- fix: refs #8201 use arrayData to fix the error by:Jon
|
||||||
|
- fix: refs #8314 space between label and value by:jtubau
|
||||||
|
- fix: refs #8813 fixed ClaimLines format by:provira
|
||||||
|
- fix: update button sizes in ExtraCommunity.vue for better visibility by:jgallego
|
||||||
|
- perf: revert processData by:alexm
|
||||||
|
- refactor: item fixedPrice by:Jon
|
||||||
|
|
||||||
# Version 24.52 - 2024-01-07
|
# Version 24.52 - 2024-01-07
|
||||||
|
|
||||||
### Added 🆕
|
### Added 🆕
|
||||||
|
|
|
@ -31,7 +31,7 @@ export default {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
form.addEventListener('keyup', function (evt) {
|
form.addEventListener('keyup', function (evt) {
|
||||||
if (evt.key === 'Enter') {
|
if (evt.key === 'Enter' && !that.$attrs['prevent-submit']) {
|
||||||
const input = evt.target;
|
const input = evt.target;
|
||||||
if (input.type == 'textarea' && evt.shiftKey) {
|
if (input.type == 'textarea' && evt.shiftKey) {
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
|
|
|
@ -198,6 +198,7 @@ async function fetch() {
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
state.set(modelValue, {});
|
state.set(modelValue, {});
|
||||||
originalData.value = {};
|
originalData.value = {};
|
||||||
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ const onDataSaved = (data) => {
|
||||||
<FormModelPopup
|
<FormModelPopup
|
||||||
url-create="Items/regularize"
|
url-create="Items/regularize"
|
||||||
model="Items"
|
model="Items"
|
||||||
:title="t('Regularize stock')"
|
:title="t('item.regularizeStock')"
|
||||||
:form-initial-data="regularizeFormData"
|
:form-initial-data="regularizeFormData"
|
||||||
@on-data-saved="onDataSaved($event)"
|
@on-data-saved="onDataSaved($event)"
|
||||||
>
|
>
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
import { createWrapper, axios } from 'app/test/vitest/helper';
|
||||||
|
import FilterItemForm from 'src/components/FilterItemForm.vue';
|
||||||
|
import { vi, beforeAll, describe, expect, it } from 'vitest';
|
||||||
|
|
||||||
|
describe('FilterItemForm', () => {
|
||||||
|
let vm;
|
||||||
|
let wrapper;
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
wrapper = createWrapper(FilterItemForm, {
|
||||||
|
props: {
|
||||||
|
url: 'Items/withName',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
vm = wrapper.vm;
|
||||||
|
wrapper = wrapper.wrapper;
|
||||||
|
|
||||||
|
vi.spyOn(axios, 'get').mockResolvedValue({
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
id: 999996,
|
||||||
|
name: 'bolas de madera',
|
||||||
|
size: 2,
|
||||||
|
inkFk: null,
|
||||||
|
producerFk: null,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should filter data and populate tableRows for table display', async () => {
|
||||||
|
vm.itemFilterParams.name = 'bolas de madera';
|
||||||
|
|
||||||
|
await vm.onSubmit();
|
||||||
|
|
||||||
|
const expectedFilter = {
|
||||||
|
include: [
|
||||||
|
{ relation: 'producer', scope: { fields: ['name'] } },
|
||||||
|
{ relation: 'ink', scope: { fields: ['name'] } },
|
||||||
|
],
|
||||||
|
where: {"name":{"like":"%bolas de madera%"}},
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(axios.get).toHaveBeenCalledWith('Items/withName', {
|
||||||
|
params: { filter: JSON.stringify(expectedFilter) },
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(vm.tableRows).toEqual([
|
||||||
|
{
|
||||||
|
id: 999996,
|
||||||
|
name: 'bolas de madera',
|
||||||
|
size: 2,
|
||||||
|
inkFk: null,
|
||||||
|
producerFk: null,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle an empty itemFilterParams correctly', async () => {
|
||||||
|
vm.itemFilterParams.name = null;
|
||||||
|
vm.itemFilterParams = {};
|
||||||
|
|
||||||
|
await vm.onSubmit();
|
||||||
|
|
||||||
|
const expectedFilter = {
|
||||||
|
include: [
|
||||||
|
{ relation: 'producer', scope: { fields: ['name'] } },
|
||||||
|
{ relation: 'ink', scope: { fields: ['name'] } },
|
||||||
|
],
|
||||||
|
where: {},
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(axios.get).toHaveBeenCalledWith('Items/withName', {
|
||||||
|
params: { filter: JSON.stringify(expectedFilter) },
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should emit "itemSelected" with the correct id and close the form', () => {
|
||||||
|
vm.selectItem({ id: 12345 });
|
||||||
|
expect(wrapper.emitted('itemSelected')[0]).toEqual([12345]);
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,29 +1,17 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted, useSlots } from 'vue';
|
import { onMounted, useSlots } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useStateStore } from 'stores/useStateStore';
|
import { useStateStore } from 'stores/useStateStore';
|
||||||
import { useQuasar } from 'quasar';
|
import { useQuasar } from 'quasar';
|
||||||
|
import { useHasContent } from 'src/composables/useHasContent';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const quasar = useQuasar();
|
const quasar = useQuasar();
|
||||||
const stateStore = useStateStore();
|
const stateStore = useStateStore();
|
||||||
const slots = useSlots();
|
const slots = useSlots();
|
||||||
const hasContent = ref(false);
|
const hasContent = useHasContent('#right-panel');
|
||||||
const rightPanel = ref(null);
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
rightPanel.value = document.querySelector('#right-panel');
|
|
||||||
if (!rightPanel.value) return;
|
|
||||||
|
|
||||||
const observer = new MutationObserver(() => {
|
|
||||||
hasContent.value = rightPanel.value.childNodes.length;
|
|
||||||
});
|
|
||||||
|
|
||||||
observer.observe(rightPanel.value, {
|
|
||||||
subtree: true,
|
|
||||||
childList: true,
|
|
||||||
attributes: true,
|
|
||||||
});
|
|
||||||
if ((!slots['right-panel'] && !hasContent.value) || quasar.platform.is.mobile)
|
if ((!slots['right-panel'] && !hasContent.value) || quasar.platform.is.mobile)
|
||||||
stateStore.rightDrawer = false;
|
stateStore.rightDrawer = false;
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import CreateNewPostcode from 'src/components/CreateNewPostcodeForm.vue';
|
import CreateNewPostcode from 'src/components/CreateNewPostcodeForm.vue';
|
||||||
import VnSelectDialog from 'components/common/VnSelectDialog.vue';
|
import VnSelectDialog from 'components/common/VnSelectDialog.vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { computed } from 'vue';
|
import { ref, watch } from 'vue';
|
||||||
import { useAttrs } from 'vue';
|
import { useAttrs } from 'vue';
|
||||||
import { useRequired } from 'src/composables/useRequired';
|
import { useRequired } from 'src/composables/useRequired';
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
@ -16,6 +16,14 @@ const props = defineProps({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.location,
|
||||||
|
(newValue) => {
|
||||||
|
if (!modelValue.value) return;
|
||||||
|
modelValue.value = formatLocation(newValue) ?? null;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const mixinRules = [requiredFieldRule];
|
const mixinRules = [requiredFieldRule];
|
||||||
const locationProperties = [
|
const locationProperties = [
|
||||||
'postcode',
|
'postcode',
|
||||||
|
@ -43,9 +51,7 @@ const formatLocation = (obj, properties = locationProperties) => {
|
||||||
return filteredParts.join(', ');
|
return filteredParts.join(', ');
|
||||||
};
|
};
|
||||||
|
|
||||||
const modelValue = computed(() =>
|
const modelValue = ref(props.location ? formatLocation(props.location) : null);
|
||||||
props.location ? formatLocation(props.location, locationProperties) : null
|
|
||||||
);
|
|
||||||
|
|
||||||
function showLabel(data) {
|
function showLabel(data) {
|
||||||
const dataProperties = [
|
const dataProperties = [
|
||||||
|
|
|
@ -2,9 +2,10 @@
|
||||||
import RightMenu from './RightMenu.vue';
|
import RightMenu from './RightMenu.vue';
|
||||||
import VnSearchbar from 'components/ui/VnSearchbar.vue';
|
import VnSearchbar from 'components/ui/VnSearchbar.vue';
|
||||||
import VnTableFilter from '../VnTable/VnTableFilter.vue';
|
import VnTableFilter from '../VnTable/VnTableFilter.vue';
|
||||||
import { onBeforeMount, computed } from 'vue';
|
import { onBeforeMount, computed, ref } from 'vue';
|
||||||
import { useArrayData } from 'src/composables/useArrayData';
|
import { useArrayData } from 'src/composables/useArrayData';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
|
import { useHasContent } from 'src/composables/useHasContent';
|
||||||
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
section: {
|
section: {
|
||||||
|
@ -55,6 +56,8 @@ const isMainSection = computed(() => {
|
||||||
}
|
}
|
||||||
return isSame;
|
return isSame;
|
||||||
});
|
});
|
||||||
|
const searchbarId = 'section-searchbar';
|
||||||
|
const hasContent = useHasContent(`#${searchbarId}`);
|
||||||
|
|
||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
if ($props.dataKey)
|
if ($props.dataKey)
|
||||||
|
@ -69,14 +72,14 @@ onBeforeMount(() => {
|
||||||
<template>
|
<template>
|
||||||
<slot name="searchbar">
|
<slot name="searchbar">
|
||||||
<VnSearchbar
|
<VnSearchbar
|
||||||
v-if="searchBar"
|
v-if="searchBar && !hasContent"
|
||||||
v-bind="arrayDataProps"
|
v-bind="arrayDataProps"
|
||||||
:data-key="dataKey"
|
:data-key="dataKey"
|
||||||
:label="$t(`${prefix}.search`)"
|
:label="$t(`${prefix}.search`)"
|
||||||
:info="$t(`${prefix}.searchInfo`)"
|
:info="$t(`${prefix}.searchInfo`)"
|
||||||
/>
|
/>
|
||||||
|
<div :id="searchbarId"></div>
|
||||||
</slot>
|
</slot>
|
||||||
|
|
||||||
<RightMenu>
|
<RightMenu>
|
||||||
<template #right-panel v-if="$slots['rightMenu'] || rightFilter">
|
<template #right-panel v-if="$slots['rightMenu'] || rightFilter">
|
||||||
<slot name="rightMenu">
|
<slot name="rightMenu">
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
import { createWrapper } from 'app/test/vitest/helper.js';
|
||||||
|
import { describe, it, expect } from 'vitest';
|
||||||
|
import VnInputDate from 'components/common/VnInputDate.vue';
|
||||||
|
|
||||||
|
let vm;
|
||||||
|
let wrapper;
|
||||||
|
|
||||||
|
function generateWrapper(date, outlined, required) {
|
||||||
|
wrapper = createWrapper(VnInputDate, {
|
||||||
|
props: {
|
||||||
|
modelValue: date,
|
||||||
|
},
|
||||||
|
attrs: {
|
||||||
|
isOutlined: outlined,
|
||||||
|
required: required
|
||||||
|
},
|
||||||
|
});
|
||||||
|
wrapper = wrapper.wrapper;
|
||||||
|
vm = wrapper.vm;
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('VnInputDate', () => {
|
||||||
|
|
||||||
|
describe('formattedDate', () => {
|
||||||
|
it('formats a valid date correctly', async () => {
|
||||||
|
generateWrapper('2023-12-25', false, false);
|
||||||
|
await vm.$nextTick();
|
||||||
|
expect(vm.formattedDate).toBe('25/12/2023');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('updates the model value when a new date is set', async () => {
|
||||||
|
const input = wrapper.find('input');
|
||||||
|
await input.setValue('31/12/2023');
|
||||||
|
expect(wrapper.emitted()['update:modelValue']).toBeTruthy();
|
||||||
|
expect(wrapper.emitted()['update:modelValue'][0][0]).toBe('2023-12-31T00:00:00.000Z');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not update the model value when an invalid date is set', async () => {
|
||||||
|
const input = wrapper.find('input');
|
||||||
|
await input.setValue('invalid-date');
|
||||||
|
expect(wrapper.emitted()['update:modelValue'][0][0]).toBe('2023-12-31T00:00:00.000Z');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('styleAttrs', () => {
|
||||||
|
it('should return empty styleAttrs when isOutlined is false', async () => {
|
||||||
|
generateWrapper('2023-12-25', false, false);
|
||||||
|
await vm.$nextTick();
|
||||||
|
expect(vm.styleAttrs).toEqual({});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set styleAttrs when isOutlined is true', async () => {
|
||||||
|
generateWrapper('2023-12-25', true, false);
|
||||||
|
await vm.$nextTick();
|
||||||
|
expect(vm.styleAttrs.outlined).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('required', () => {
|
||||||
|
it('should not applies required class when isRequired is false', async () => {
|
||||||
|
generateWrapper('2023-12-25', false, false);
|
||||||
|
await vm.$nextTick();
|
||||||
|
expect(wrapper.find('.vn-input-date').classes()).not.toContain('required');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should applies required class when isRequired is true', async () => {
|
||||||
|
generateWrapper('2023-12-25', false, true);
|
||||||
|
await vm.$nextTick();
|
||||||
|
expect(wrapper.find('.vn-input-date').classes()).toContain('required');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,63 @@
|
||||||
|
import { vi, describe, expect, it, beforeAll, afterEach } from 'vitest';
|
||||||
|
import { createWrapper } from 'app/test/vitest/helper';
|
||||||
|
import VnInputTime from 'components/common/VnInputTime.vue';
|
||||||
|
|
||||||
|
describe('VnInputTime', () => {
|
||||||
|
let wrapper;
|
||||||
|
let vm;
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
wrapper = createWrapper(VnInputTime, {
|
||||||
|
props: {
|
||||||
|
isOutlined: true,
|
||||||
|
timeOnly: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
vm = wrapper.vm;
|
||||||
|
wrapper = wrapper.wrapper;
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
vi.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return the correct data if isOutlined is true', () => {
|
||||||
|
expect(vm.isOutlined).toBe(true);
|
||||||
|
expect(vm.styleAttrs).toEqual({ dense: true, outlined: true, rounded: true });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return the formatted data', () => {
|
||||||
|
expect(vm.dateToTime('2022-01-01T03:23:43')).toBe('03:23');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('formattedTime', () => {
|
||||||
|
it('should return the formatted time for a valid ISO date', () => {
|
||||||
|
vm.model = '2025-01-02T15:45:00';
|
||||||
|
expect(vm.formattedTime).toBe('15:45');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle null model value gracefully', () => {
|
||||||
|
vm.model = null;
|
||||||
|
expect(vm.formattedTime).toBe(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle time-only input correctly', async () => {
|
||||||
|
await wrapper.setProps({ timeOnly: true });
|
||||||
|
vm.formattedTime = '14:30';
|
||||||
|
expect(vm.model).toBe('14:30');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should pad short time values correctly', async () => {
|
||||||
|
await wrapper.setProps({ timeOnly: true });
|
||||||
|
vm.formattedTime = '9';
|
||||||
|
expect(vm.model).toBe('09:00');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not update the model if the value is unchanged', () => {
|
||||||
|
vm.model = '14:30';
|
||||||
|
const previousModel = vm.model;
|
||||||
|
vm.formattedTime = '14:30';
|
||||||
|
expect(vm.model).toBe(previousModel);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -6,6 +6,7 @@ import { useArrayData } from 'composables/useArrayData';
|
||||||
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
|
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
|
||||||
import { useState } from 'src/composables/useState';
|
import { useState } from 'src/composables/useState';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
|
import VnMoreOptions from './VnMoreOptions.vue';
|
||||||
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
url: {
|
url: {
|
||||||
|
@ -47,7 +48,6 @@ let store;
|
||||||
let entity;
|
let entity;
|
||||||
const isLoading = ref(false);
|
const isLoading = ref(false);
|
||||||
const isSameDataKey = computed(() => $props.dataKey === route.meta.moduleName);
|
const isSameDataKey = computed(() => $props.dataKey === route.meta.moduleName);
|
||||||
const menuRef = ref();
|
|
||||||
defineExpose({ getData });
|
defineExpose({ getData });
|
||||||
|
|
||||||
onBeforeMount(async () => {
|
onBeforeMount(async () => {
|
||||||
|
@ -159,25 +159,11 @@ const toModule = computed(() =>
|
||||||
</QTooltip>
|
</QTooltip>
|
||||||
</QBtn>
|
</QBtn>
|
||||||
</RouterLink>
|
</RouterLink>
|
||||||
<QBtn
|
<VnMoreOptions v-if="$slots.menu">
|
||||||
v-if="$slots.menu"
|
<template #menu="{ menuRef }">
|
||||||
color="white"
|
<slot name="menu" :entity="entity" :menu-ref="menuRef" />
|
||||||
dense
|
</template>
|
||||||
flat
|
</VnMoreOptions>
|
||||||
icon="more_vert"
|
|
||||||
round
|
|
||||||
size="md"
|
|
||||||
data-cy="descriptor-more-opts"
|
|
||||||
>
|
|
||||||
<QTooltip>
|
|
||||||
{{ t('components.cardDescriptor.moreOptions') }}
|
|
||||||
</QTooltip>
|
|
||||||
<QMenu :ref="menuRef">
|
|
||||||
<QList>
|
|
||||||
<slot name="menu" :entity="entity" :menu-ref="menuRef" />
|
|
||||||
</QList>
|
|
||||||
</QMenu>
|
|
||||||
</QBtn>
|
|
||||||
</div>
|
</div>
|
||||||
<slot name="before" />
|
<slot name="before" />
|
||||||
<div class="body q-py-sm">
|
<div class="body q-py-sm">
|
||||||
|
@ -222,8 +208,8 @@ const toModule = computed(() =>
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss">
|
||||||
:deep(.body) {
|
.body {
|
||||||
background-color: var(--vn-section-color);
|
background-color: var(--vn-section-color);
|
||||||
.text-h5 {
|
.text-h5 {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
|
@ -262,7 +248,9 @@ const toModule = computed(() =>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
.title {
|
.title {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, watch, onBeforeMount, onMounted } from 'vue';
|
import { ref, computed, watch, onBeforeMount } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import SkeletonSummary from 'components/ui/SkeletonSummary.vue';
|
import SkeletonSummary from 'components/ui/SkeletonSummary.vue';
|
||||||
import { useArrayData } from 'src/composables/useArrayData';
|
import { useArrayData } from 'src/composables/useArrayData';
|
||||||
import { isDialogOpened } from 'src/filters';
|
import { isDialogOpened } from 'src/filters';
|
||||||
import { useStateStore } from 'src/stores/useStateStore';
|
import VnMoreOptions from './VnMoreOptions.vue';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
url: {
|
url: {
|
||||||
|
@ -40,7 +40,6 @@ const { store } = arrayData;
|
||||||
const entity = computed(() => (Array.isArray(store.data) ? store.data[0] : store.data));
|
const entity = computed(() => (Array.isArray(store.data) ? store.data[0] : store.data));
|
||||||
const isLoading = ref(false);
|
const isLoading = ref(false);
|
||||||
|
|
||||||
const stateStore = useStateStore();
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
entity,
|
entity,
|
||||||
fetch,
|
fetch,
|
||||||
|
@ -52,9 +51,6 @@ onBeforeMount(async () => {
|
||||||
watch(props, async () => await fetch());
|
watch(props, async () => await fetch());
|
||||||
});
|
});
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
stateStore.rightDrawerChangeValue(false);
|
|
||||||
});
|
|
||||||
async function fetch() {
|
async function fetch() {
|
||||||
store.url = props.url;
|
store.url = props.url;
|
||||||
store.filter = props.filter ?? {};
|
store.filter = props.filter ?? {};
|
||||||
|
@ -64,6 +60,7 @@ async function fetch() {
|
||||||
isLoading.value = false;
|
isLoading.value = false;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="summary container">
|
<div class="summary container">
|
||||||
<QCard class="cardSummary">
|
<QCard class="cardSummary">
|
||||||
|
@ -86,9 +83,14 @@ async function fetch() {
|
||||||
<slot name="header" :entity="entity" dense>
|
<slot name="header" :entity="entity" dense>
|
||||||
{{ entity.id + ' - ' + entity.name }}
|
{{ entity.id + ' - ' + entity.name }}
|
||||||
</slot>
|
</slot>
|
||||||
<slot name="header-right" :entity="entity">
|
<span class="row no-wrap">
|
||||||
<span></span>
|
<slot name="header-right" :entity="entity" />
|
||||||
</slot>
|
<VnMoreOptions v-if="$slots.menu && isDialogOpened()">
|
||||||
|
<template #menu="{ menuRef }">
|
||||||
|
<slot name="menu" :entity="entity" :menu-ref="menuRef" />
|
||||||
|
</template>
|
||||||
|
</VnMoreOptions>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="summaryBody row q-mb-md">
|
<div class="summaryBody row q-mb-md">
|
||||||
<slot name="body" :entity="entity" />
|
<slot name="body" :entity="entity" />
|
||||||
|
@ -97,6 +99,7 @@ async function fetch() {
|
||||||
</QCard>
|
</QCard>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.summary.container {
|
.summary.container {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
@ -18,8 +18,7 @@ const $props = defineProps({
|
||||||
},
|
},
|
||||||
columns: {
|
columns: {
|
||||||
type: Number,
|
type: Number,
|
||||||
required: false,
|
default: 3,
|
||||||
default: null,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,38 +1,49 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="header bg-primary q-pa-sm q-mb-md">
|
<div class="header bg-primary q-pa-sm q-mb-md">
|
||||||
<QSkeleton type="rect" square />
|
<QSkeleton type="rect" square />
|
||||||
|
<QSkeleton type="rect" square />
|
||||||
</div>
|
</div>
|
||||||
<div class="row q-pa-md q-col-gutter-md q-mb-md">
|
<div class="row q-pa-md q-col-gutter-md q-mb-md">
|
||||||
<QSkeleton type="rect" class="q-mb-md" square />
|
<div class="col">
|
||||||
<QSkeleton type="text" square />
|
<QSkeleton type="rect" class="q-mb-md" square />
|
||||||
<QSkeleton type="text" square />
|
<QSkeleton type="text" square />
|
||||||
<QSkeleton type="text" square />
|
<QSkeleton type="text" square />
|
||||||
<QSkeleton type="text" square />
|
<QSkeleton type="text" square />
|
||||||
<QSkeleton type="text" square />
|
<QSkeleton type="text" square />
|
||||||
<QSkeleton type="rect" class="q-mb-md" square />
|
<QSkeleton type="text" square />
|
||||||
<QSkeleton type="text" square />
|
</div>
|
||||||
<QSkeleton type="text" square />
|
<div class="col">
|
||||||
<QSkeleton type="text" square />
|
<QSkeleton type="rect" class="q-mb-md" square />
|
||||||
<QSkeleton type="text" square />
|
<QSkeleton type="text" square />
|
||||||
<QSkeleton type="text" square />
|
<QSkeleton type="text" square />
|
||||||
<QSkeleton type="rect" class="q-mb-md" square />
|
<QSkeleton type="text" square />
|
||||||
<QSkeleton type="text" square />
|
<QSkeleton type="text" square />
|
||||||
<QSkeleton type="text" square />
|
<QSkeleton type="text" square />
|
||||||
<QSkeleton type="text" square />
|
</div>
|
||||||
<QSkeleton type="text" square />
|
<div class="col">
|
||||||
<QSkeleton type="text" square />
|
<QSkeleton type="rect" class="q-mb-md" square />
|
||||||
<QSkeleton type="rect" class="q-mb-md" square />
|
<QSkeleton type="text" square />
|
||||||
<QSkeleton type="text" square />
|
<QSkeleton type="text" square />
|
||||||
<QSkeleton type="text" square />
|
<QSkeleton type="text" square />
|
||||||
<QSkeleton type="text" square />
|
<QSkeleton type="text" square />
|
||||||
<QSkeleton type="text" square />
|
<QSkeleton type="text" square />
|
||||||
<QSkeleton type="text" square />
|
</div>
|
||||||
<QSkeleton type="rect" class="q-mb-md" square />
|
<div class="col">
|
||||||
<QSkeleton type="text" square />
|
<QSkeleton type="rect" class="q-mb-md" square />
|
||||||
<QSkeleton type="text" square />
|
<QSkeleton type="text" square />
|
||||||
<QSkeleton type="text" square />
|
<QSkeleton type="text" square />
|
||||||
<QSkeleton type="text" square />
|
<QSkeleton type="text" square />
|
||||||
<QSkeleton type="text" square />
|
<QSkeleton type="text" square />
|
||||||
|
<QSkeleton type="text" square />
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<QSkeleton type="rect" class="q-mb-md" square />
|
||||||
|
<QSkeleton type="text" square />
|
||||||
|
<QSkeleton type="text" square />
|
||||||
|
<QSkeleton type="text" square />
|
||||||
|
<QSkeleton type="text" square />
|
||||||
|
<QSkeleton type="text" square />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ onBeforeMount(async () => {
|
||||||
.data;
|
.data;
|
||||||
if (!channel) channel = defaultChannel;
|
if (!channel) channel = defaultChannel;
|
||||||
|
|
||||||
phone.value = await parsePhone(props.phoneNumber, props.country.toLowerCase());
|
phone.value = await parsePhone(props.phoneNumber, props.country?.toLowerCase());
|
||||||
config[
|
config[
|
||||||
type
|
type
|
||||||
].url = `${url}?customerIdentity=%2B${phone.value}&channelId=${channel}`;
|
].url = `${url}?customerIdentity=%2B${phone.value}&channelId=${channel}`;
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
<template>
|
||||||
|
<QBtn
|
||||||
|
color="white"
|
||||||
|
dense
|
||||||
|
flat
|
||||||
|
icon="more_vert"
|
||||||
|
round
|
||||||
|
size="md"
|
||||||
|
data-cy="descriptor-more-opts"
|
||||||
|
>
|
||||||
|
<QTooltip>
|
||||||
|
{{ $t('components.cardDescriptor.moreOptions') }}
|
||||||
|
</QTooltip>
|
||||||
|
<QMenu ref="menuRef">
|
||||||
|
<QList>
|
||||||
|
<slot name="menu" :menu-ref="$refs.menuRef" />
|
||||||
|
</QList>
|
||||||
|
</QMenu>
|
||||||
|
</QBtn>
|
||||||
|
</template>
|
|
@ -0,0 +1,78 @@
|
||||||
|
import { vi, describe, expect, it, beforeAll, afterEach, beforeEach } from 'vitest';
|
||||||
|
import { createWrapper, axios } from 'app/test/vitest/helper';
|
||||||
|
import CardSummary from 'src/components/ui/CardSummary.vue';
|
||||||
|
import * as vueRouter from 'vue-router';
|
||||||
|
|
||||||
|
describe('CardSummary', () => {
|
||||||
|
let vm;
|
||||||
|
let wrapper;
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
vi.spyOn(axios, 'get').mockResolvedValue({ data: [] });
|
||||||
|
});
|
||||||
|
|
||||||
|
vi.spyOn(vueRouter, 'useRoute').mockReturnValue({
|
||||||
|
query: {},
|
||||||
|
params: {},
|
||||||
|
meta: { moduleName: 'mockName' },
|
||||||
|
path: 'mockName/1/summary',
|
||||||
|
name: 'CardSummary',
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = createWrapper(CardSummary, {
|
||||||
|
propsData: {
|
||||||
|
dataKey: 'cardSummaryKey',
|
||||||
|
url: 'cardSummaryUrl',
|
||||||
|
filter: 'cardFilter',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
vm = wrapper.vm;
|
||||||
|
wrapper = wrapper.wrapper;
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
vi.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fetch data correctly', async () => {
|
||||||
|
const fetchSpy = vi
|
||||||
|
.spyOn(vm.arrayData, 'fetch')
|
||||||
|
.mockResolvedValue({ data: [{ id: 1, name: 'Test Entity' }] });
|
||||||
|
await vm.fetch();
|
||||||
|
|
||||||
|
expect(fetchSpy).toHaveBeenCalledWith({ append: false, updateRouter: false });
|
||||||
|
expect(wrapper.emitted('onFetch')).toBeTruthy();
|
||||||
|
expect(vm.isLoading).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set correct props to the store', () => {
|
||||||
|
expect(vm.store.url).toEqual('cardSummaryUrl');
|
||||||
|
expect(vm.store.filter).toEqual('cardFilter');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should compute entity correctly from store data', () => {
|
||||||
|
vm.store.data = [{ id: 1, name: 'Entity 1' }];
|
||||||
|
expect(vm.entity).toEqual({ id: 1, name: 'Entity 1' });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle empty data gracefully', () => {
|
||||||
|
vm.store.data = [];
|
||||||
|
expect(vm.entity).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should respond to prop changes and refetch data', async () => {
|
||||||
|
const newUrl = 'CardSummary/35';
|
||||||
|
const newKey = 'cardSummaryKey/35';
|
||||||
|
const fetchSpy = vi.spyOn(vm.arrayData, 'fetch');
|
||||||
|
await wrapper.setProps({ url: newUrl, filter: { key: newKey } });
|
||||||
|
|
||||||
|
expect(fetchSpy).toHaveBeenCalled();
|
||||||
|
expect(vm.store.url).toBe(newUrl);
|
||||||
|
expect(vm.store.filter).toEqual({ key: newKey });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return true if route path ends with /summary' , () => {
|
||||||
|
expect(vm.isSummary).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,6 @@
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
export default async (id) => {
|
||||||
|
const { data } = await axios.get(`Accounts/${id}/exists`);
|
||||||
|
return data.exists;
|
||||||
|
};
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { onMounted, ref } from 'vue';
|
||||||
|
|
||||||
|
export function useHasContent(selector) {
|
||||||
|
const container = ref({});
|
||||||
|
const hasContent = ref();
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
container.value = document.querySelector(selector);
|
||||||
|
if (!container.value) return;
|
||||||
|
|
||||||
|
const observer = new MutationObserver(() => {
|
||||||
|
if (document.querySelector(selector))
|
||||||
|
hasContent.value = !!container.value.childNodes.length;
|
||||||
|
});
|
||||||
|
|
||||||
|
observer.observe(container.value, {
|
||||||
|
subtree: true,
|
||||||
|
childList: true,
|
||||||
|
attributes: true,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return hasContent;
|
||||||
|
}
|
|
@ -346,6 +346,7 @@ globals:
|
||||||
countryFk: Country
|
countryFk: Country
|
||||||
companyFk: Company
|
companyFk: Company
|
||||||
changePass: Change password
|
changePass: Change password
|
||||||
|
setPass: Set password
|
||||||
deleteConfirmTitle: Delete selected elements
|
deleteConfirmTitle: Delete selected elements
|
||||||
changeState: Change state
|
changeState: Change state
|
||||||
raid: 'Raid {daysInForward} days'
|
raid: 'Raid {daysInForward} days'
|
||||||
|
@ -388,80 +389,6 @@ cau:
|
||||||
subtitle: By sending this ticket, all the data related to the error, the section, the user, etc., are already sent.
|
subtitle: By sending this ticket, all the data related to the error, the section, the user, etc., are already sent.
|
||||||
inputLabel: Explain why this error should not appear
|
inputLabel: Explain why this error should not appear
|
||||||
askPrivileges: Ask for privileges
|
askPrivileges: Ask for privileges
|
||||||
entry:
|
|
||||||
list:
|
|
||||||
newEntry: New entry
|
|
||||||
tableVisibleColumns:
|
|
||||||
created: Creation
|
|
||||||
supplierFk: Supplier
|
|
||||||
isBooked: Booked
|
|
||||||
isConfirmed: Confirmed
|
|
||||||
isOrdered: Ordered
|
|
||||||
companyFk: Company
|
|
||||||
travelFk: Travel
|
|
||||||
isExcludedFromAvailable: Inventory
|
|
||||||
invoiceAmount: Import
|
|
||||||
summary:
|
|
||||||
commission: Commission
|
|
||||||
currency: Currency
|
|
||||||
invoiceNumber: Invoice number
|
|
||||||
ordered: Ordered
|
|
||||||
booked: Booked
|
|
||||||
excludedFromAvailable: Inventory
|
|
||||||
travelReference: Reference
|
|
||||||
travelAgency: Agency
|
|
||||||
travelShipped: Shipped
|
|
||||||
travelDelivered: Delivered
|
|
||||||
travelLanded: Landed
|
|
||||||
travelReceived: Received
|
|
||||||
buys: Buys
|
|
||||||
stickers: Stickers
|
|
||||||
package: Package
|
|
||||||
packing: Pack.
|
|
||||||
grouping: Group.
|
|
||||||
buyingValue: Buying value
|
|
||||||
import: Import
|
|
||||||
pvp: PVP
|
|
||||||
basicData:
|
|
||||||
travel: Travel
|
|
||||||
currency: Currency
|
|
||||||
commission: Commission
|
|
||||||
observation: Observation
|
|
||||||
booked: Booked
|
|
||||||
excludedFromAvailable: Inventory
|
|
||||||
buys:
|
|
||||||
observations: Observations
|
|
||||||
packagingFk: Box
|
|
||||||
color: Color
|
|
||||||
printedStickers: Printed stickers
|
|
||||||
notes:
|
|
||||||
observationType: Observation type
|
|
||||||
latestBuys:
|
|
||||||
tableVisibleColumns:
|
|
||||||
image: Picture
|
|
||||||
itemFk: Item ID
|
|
||||||
weightByPiece: Weight/Piece
|
|
||||||
isActive: Active
|
|
||||||
family: Family
|
|
||||||
entryFk: Entry
|
|
||||||
freightValue: Freight value
|
|
||||||
comissionValue: Commission value
|
|
||||||
packageValue: Package value
|
|
||||||
isIgnored: Is ignored
|
|
||||||
price2: Grouping
|
|
||||||
price3: Packing
|
|
||||||
minPrice: Min
|
|
||||||
ektFk: Ekt
|
|
||||||
packingOut: Package out
|
|
||||||
landing: Landing
|
|
||||||
isExcludedFromAvailable: Es inventory
|
|
||||||
params:
|
|
||||||
toShipped: To
|
|
||||||
fromShipped: From
|
|
||||||
warehouseiNFk: Warehouse
|
|
||||||
daysOnward: Days onward
|
|
||||||
daysAgo: Days ago
|
|
||||||
warehouseInFk: Warehouse in
|
|
||||||
ticket:
|
ticket:
|
||||||
params:
|
params:
|
||||||
ticketFk: Ticket ID
|
ticketFk: Ticket ID
|
||||||
|
@ -578,27 +505,6 @@ parking:
|
||||||
searchBar:
|
searchBar:
|
||||||
info: You can search by parking code
|
info: You can search by parking code
|
||||||
label: Search parking...
|
label: Search parking...
|
||||||
order:
|
|
||||||
field:
|
|
||||||
salesPersonFk: Sales Person
|
|
||||||
form:
|
|
||||||
clientFk: Client
|
|
||||||
addressFk: Address
|
|
||||||
agencyModeFk: Agency
|
|
||||||
list:
|
|
||||||
newOrder: New Order
|
|
||||||
summary:
|
|
||||||
basket: Basket
|
|
||||||
notConfirmed: Not confirmed
|
|
||||||
created: Created
|
|
||||||
createdFrom: Created From
|
|
||||||
address: Address
|
|
||||||
total: Total
|
|
||||||
items: Items
|
|
||||||
orderTicketList: Order Ticket List
|
|
||||||
amount: Amount
|
|
||||||
confirm: Confirm
|
|
||||||
confirmLines: Confirm lines
|
|
||||||
department:
|
department:
|
||||||
chat: Chat
|
chat: Chat
|
||||||
bossDepartment: Boss Department
|
bossDepartment: Boss Department
|
||||||
|
@ -889,7 +795,10 @@ components:
|
||||||
hasMinPrice: Minimum price
|
hasMinPrice: Minimum price
|
||||||
# LatestBuysFilter
|
# LatestBuysFilter
|
||||||
salesPersonFk: Buyer
|
salesPersonFk: Buyer
|
||||||
|
supplierFk: Supplier
|
||||||
from: From
|
from: From
|
||||||
|
to: To
|
||||||
|
visible: Is visible
|
||||||
active: Is active
|
active: Is active
|
||||||
floramondo: Is floramondo
|
floramondo: Is floramondo
|
||||||
showBadDates: Show future items
|
showBadDates: Show future items
|
||||||
|
|
|
@ -348,6 +348,7 @@ globals:
|
||||||
countryFk: País
|
countryFk: País
|
||||||
companyFk: Empresa
|
companyFk: Empresa
|
||||||
changePass: Cambiar contraseña
|
changePass: Cambiar contraseña
|
||||||
|
setPass: Establecer contraseña
|
||||||
deleteConfirmTitle: Eliminar los elementos seleccionados
|
deleteConfirmTitle: Eliminar los elementos seleccionados
|
||||||
changeState: Cambiar estado
|
changeState: Cambiar estado
|
||||||
raid: 'Redada {daysInForward} días'
|
raid: 'Redada {daysInForward} días'
|
||||||
|
@ -388,80 +389,6 @@ cau:
|
||||||
subtitle: Al enviar este cau ya se envían todos los datos relacionados con el error, la sección, el usuario, etc
|
subtitle: Al enviar este cau ya se envían todos los datos relacionados con el error, la sección, el usuario, etc
|
||||||
inputLabel: Explique el motivo por el que no deberia aparecer este fallo
|
inputLabel: Explique el motivo por el que no deberia aparecer este fallo
|
||||||
askPrivileges: Solicitar permisos
|
askPrivileges: Solicitar permisos
|
||||||
entry:
|
|
||||||
list:
|
|
||||||
newEntry: Nueva entrada
|
|
||||||
tableVisibleColumns:
|
|
||||||
created: Creación
|
|
||||||
supplierFk: Proveedor
|
|
||||||
isBooked: Asentado
|
|
||||||
isConfirmed: Confirmado
|
|
||||||
isOrdered: Pedida
|
|
||||||
companyFk: Empresa
|
|
||||||
travelFk: Envio
|
|
||||||
isExcludedFromAvailable: Inventario
|
|
||||||
invoiceAmount: Importe
|
|
||||||
summary:
|
|
||||||
commission: Comisión
|
|
||||||
currency: Moneda
|
|
||||||
invoiceNumber: Núm. factura
|
|
||||||
ordered: Pedida
|
|
||||||
booked: Contabilizada
|
|
||||||
excludedFromAvailable: Inventario
|
|
||||||
travelReference: Referencia
|
|
||||||
travelAgency: Agencia
|
|
||||||
travelShipped: F. envio
|
|
||||||
travelWarehouseOut: Alm. salida
|
|
||||||
travelDelivered: Enviada
|
|
||||||
travelLanded: F. entrega
|
|
||||||
travelReceived: Recibida
|
|
||||||
buys: Compras
|
|
||||||
stickers: Etiquetas
|
|
||||||
package: Embalaje
|
|
||||||
packing: Pack.
|
|
||||||
grouping: Group.
|
|
||||||
buyingValue: Coste
|
|
||||||
import: Importe
|
|
||||||
pvp: PVP
|
|
||||||
basicData:
|
|
||||||
travel: Envío
|
|
||||||
currency: Moneda
|
|
||||||
observation: Observación
|
|
||||||
commission: Comisión
|
|
||||||
booked: Asentado
|
|
||||||
excludedFromAvailable: Inventario
|
|
||||||
buys:
|
|
||||||
observations: Observaciónes
|
|
||||||
packagingFk: Embalaje
|
|
||||||
color: Color
|
|
||||||
printedStickers: Etiquetas impresas
|
|
||||||
notes:
|
|
||||||
observationType: Tipo de observación
|
|
||||||
latestBuys:
|
|
||||||
tableVisibleColumns:
|
|
||||||
image: Foto
|
|
||||||
itemFk: Id Artículo
|
|
||||||
weightByPiece: Peso (gramos)/tallo
|
|
||||||
isActive: Activo
|
|
||||||
family: Familia
|
|
||||||
entryFk: Entrada
|
|
||||||
freightValue: Porte
|
|
||||||
comissionValue: Comisión
|
|
||||||
packageValue: Embalaje
|
|
||||||
isIgnored: Ignorado
|
|
||||||
price2: Grouping
|
|
||||||
price3: Packing
|
|
||||||
minPrice: Min
|
|
||||||
ektFk: Ekt
|
|
||||||
packingOut: Embalaje envíos
|
|
||||||
landing: Llegada
|
|
||||||
isExcludedFromAvailable: Es inventario
|
|
||||||
params:
|
|
||||||
toShipped: Hasta
|
|
||||||
fromShipped: Desde
|
|
||||||
warehouseInFk: Alm. entrada
|
|
||||||
daysOnward: Días adelante
|
|
||||||
daysAgo: Días atras
|
|
||||||
ticket:
|
ticket:
|
||||||
params:
|
params:
|
||||||
ticketFk: ID de ticket
|
ticketFk: ID de ticket
|
||||||
|
@ -562,30 +489,6 @@ invoiceOut:
|
||||||
comercial: Comercial
|
comercial: Comercial
|
||||||
errors:
|
errors:
|
||||||
downloadCsvFailed: Error al descargar CSV
|
downloadCsvFailed: Error al descargar CSV
|
||||||
order:
|
|
||||||
field:
|
|
||||||
salesPersonFk: Comercial
|
|
||||||
form:
|
|
||||||
clientFk: Cliente
|
|
||||||
addressFk: Dirección
|
|
||||||
agencyModeFk: Agencia
|
|
||||||
list:
|
|
||||||
newOrder: Nuevo Pedido
|
|
||||||
summary:
|
|
||||||
basket: Cesta
|
|
||||||
notConfirmed: No confirmada
|
|
||||||
created: Creado
|
|
||||||
createdFrom: Creado desde
|
|
||||||
address: Dirección
|
|
||||||
total: Total
|
|
||||||
vat: IVA
|
|
||||||
state: Estado
|
|
||||||
alias: Alias
|
|
||||||
items: Artículos
|
|
||||||
orderTicketList: Tickets del pedido
|
|
||||||
amount: Monto
|
|
||||||
confirm: Confirmar
|
|
||||||
confirmLines: Confirmar lineas
|
|
||||||
shelving:
|
shelving:
|
||||||
list:
|
list:
|
||||||
parking: Parking
|
parking: Parking
|
||||||
|
@ -889,7 +792,11 @@ components:
|
||||||
wareHouseFk: Almacén
|
wareHouseFk: Almacén
|
||||||
# LatestBuysFilter
|
# LatestBuysFilter
|
||||||
salesPersonFk: Comprador
|
salesPersonFk: Comprador
|
||||||
|
supplierFk: Proveedor
|
||||||
|
visible: Visible
|
||||||
active: Activo
|
active: Activo
|
||||||
|
from: Desde
|
||||||
|
to: Hasta
|
||||||
floramondo: Floramondo
|
floramondo: Floramondo
|
||||||
showBadDates: Ver items a futuro
|
showBadDates: Ver items a futuro
|
||||||
userPanel:
|
userPanel:
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed } from 'vue';
|
import { ref, computed, onMounted } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import CardDescriptor from 'components/ui/CardDescriptor.vue';
|
import CardDescriptor from 'components/ui/CardDescriptor.vue';
|
||||||
import VnLv from 'src/components/ui/VnLv.vue';
|
import VnLv from 'src/components/ui/VnLv.vue';
|
||||||
import useCardDescription from 'src/composables/useCardDescription';
|
import useCardDescription from 'src/composables/useCardDescription';
|
||||||
import AccountDescriptorMenu from './AccountDescriptorMenu.vue';
|
import AccountDescriptorMenu from './AccountDescriptorMenu.vue';
|
||||||
import FetchData from 'src/components/FetchData.vue';
|
|
||||||
import VnImg from 'src/components/ui/VnImg.vue';
|
import VnImg from 'src/components/ui/VnImg.vue';
|
||||||
|
import useHasAccount from 'src/composables/useHasAccount.js';
|
||||||
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
id: {
|
id: {
|
||||||
|
@ -23,6 +23,7 @@ const entityId = computed(() => {
|
||||||
return $props.id || route.params.id;
|
return $props.id || route.params.id;
|
||||||
});
|
});
|
||||||
const data = ref(useCardDescription());
|
const data = ref(useCardDescription());
|
||||||
|
const hasAccount = ref();
|
||||||
const setData = (entity) => (data.value = useCardDescription(entity.nickname, entity.id));
|
const setData = (entity) => (data.value = useCardDescription(entity.nickname, entity.id));
|
||||||
|
|
||||||
const filter = {
|
const filter = {
|
||||||
|
@ -30,18 +31,16 @@ const filter = {
|
||||||
fields: ['id', 'nickname', 'name', 'role'],
|
fields: ['id', 'nickname', 'name', 'role'],
|
||||||
include: { relation: 'role', scope: { fields: ['id', 'name'] } },
|
include: { relation: 'role', scope: { fields: ['id', 'name'] } },
|
||||||
};
|
};
|
||||||
const hasAccount = ref(false);
|
|
||||||
|
onMounted(async () => {
|
||||||
|
hasAccount.value = await useHasAccount(entityId.value);
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<FetchData
|
|
||||||
:url="`Accounts/${entityId}/exists`"
|
|
||||||
auto-load
|
|
||||||
@on-fetch="(data) => (hasAccount = data.exists)"
|
|
||||||
/>
|
|
||||||
<CardDescriptor
|
<CardDescriptor
|
||||||
ref="descriptor"
|
ref="descriptor"
|
||||||
url="VnUsers/preview"
|
:url="`VnUsers/preview`"
|
||||||
:filter="filter"
|
:filter="filter"
|
||||||
module="Account"
|
module="Account"
|
||||||
@on-fetch="setData"
|
@on-fetch="setData"
|
||||||
|
@ -50,7 +49,7 @@ const hasAccount = ref(false);
|
||||||
:subtitle="data.subtitle"
|
:subtitle="data.subtitle"
|
||||||
>
|
>
|
||||||
<template #menu>
|
<template #menu>
|
||||||
<AccountDescriptorMenu :has-account="hasAccount" />
|
<AccountDescriptorMenu :entity-id="entityId" />
|
||||||
</template>
|
</template>
|
||||||
<template #before>
|
<template #before>
|
||||||
<VnImg :id="entityId" collection="user" resolution="520x520" class="photo">
|
<VnImg :id="entityId" collection="user" resolution="520x520" class="photo">
|
||||||
|
@ -74,7 +73,7 @@ const hasAccount = ref(false);
|
||||||
<VnLv :label="t('account.card.nickname')" :value="entity.name" />
|
<VnLv :label="t('account.card.nickname')" :value="entity.name" />
|
||||||
<VnLv :label="t('account.card.role')" :value="entity.role.name" />
|
<VnLv :label="t('account.card.role')" :value="entity.role.name" />
|
||||||
</template>
|
</template>
|
||||||
<template #icons="{ entity }">
|
<template #actions="{ entity }">
|
||||||
<QCardActions class="q-gutter-x-md">
|
<QCardActions class="q-gutter-x-md">
|
||||||
<QIcon
|
<QIcon
|
||||||
v-if="!entity.active"
|
v-if="!entity.active"
|
||||||
|
@ -82,7 +81,7 @@ const hasAccount = ref(false);
|
||||||
name="vn:disabled"
|
name="vn:disabled"
|
||||||
flat
|
flat
|
||||||
round
|
round
|
||||||
size="xs"
|
size="sm"
|
||||||
class="fill-icon"
|
class="fill-icon"
|
||||||
>
|
>
|
||||||
<QTooltip>{{ t('account.card.deactivated') }}</QTooltip>
|
<QTooltip>{{ t('account.card.deactivated') }}</QTooltip>
|
||||||
|
@ -93,7 +92,7 @@ const hasAccount = ref(false);
|
||||||
v-if="hasAccount"
|
v-if="hasAccount"
|
||||||
flat
|
flat
|
||||||
round
|
round
|
||||||
size="xs"
|
size="sm"
|
||||||
class="fill-icon"
|
class="fill-icon"
|
||||||
>
|
>
|
||||||
<QTooltip>{{ t('account.card.enabled') }}</QTooltip>
|
<QTooltip>{{ t('account.card.enabled') }}</QTooltip>
|
||||||
|
|
|
@ -1,15 +1,17 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { computed, ref, toRefs } from 'vue';
|
import { computed, onMounted, ref, toRefs } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useVnConfirm } from 'composables/useVnConfirm';
|
import { useVnConfirm } from 'composables/useVnConfirm';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { useAcl } from 'src/composables/useAcl';
|
import { useAcl } from 'src/composables/useAcl';
|
||||||
import { useArrayData } from 'src/composables/useArrayData';
|
import { useArrayData } from 'src/composables/useArrayData';
|
||||||
|
import { useState } from 'src/composables/useState';
|
||||||
import VnConfirm from 'src/components/ui/VnConfirm.vue';
|
import VnConfirm from 'src/components/ui/VnConfirm.vue';
|
||||||
|
import VnInputPassword from 'src/components/common/VnInputPassword.vue';
|
||||||
import VnChangePassword from 'src/components/common/VnChangePassword.vue';
|
import VnChangePassword from 'src/components/common/VnChangePassword.vue';
|
||||||
import { useQuasar } from 'quasar';
|
import { useQuasar } from 'quasar';
|
||||||
import VnInputPassword from 'src/components/common/VnInputPassword.vue';
|
import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
hasAccount: {
|
hasAccount: {
|
||||||
|
@ -18,14 +20,20 @@ const $props = defineProps({
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { hasAccount } = toRefs($props);
|
const { hasAccount } = toRefs($props);
|
||||||
const { openConfirmationModal } = useVnConfirm();
|
const { openConfirmationModal } = useVnConfirm();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
const router = useRouter();
|
||||||
|
const state = useState();
|
||||||
|
const user = state.getUser();
|
||||||
const { notify } = useQuasar();
|
const { notify } = useQuasar();
|
||||||
const account = computed(() => useArrayData('AccountId').store.data[0]);
|
const account = computed(() => useArrayData('AccountId').store.data[0]);
|
||||||
account.value.hasAccount = hasAccount.value;
|
account.value.hasAccount = hasAccount.value;
|
||||||
const entityId = computed(() => +route.params.id);
|
const entityId = computed(() => +route.params.id);
|
||||||
|
const hasitManagementAccess = ref();
|
||||||
|
const hasSysadminAccess = ref();
|
||||||
|
|
||||||
async function updateStatusAccount(active) {
|
async function updateStatusAccount(active) {
|
||||||
if (active) {
|
if (active) {
|
||||||
|
@ -37,7 +45,7 @@ async function updateStatusAccount(active) {
|
||||||
account.value.hasAccount = active;
|
account.value.hasAccount = active;
|
||||||
const status = active ? 'enable' : 'disable';
|
const status = active ? 'enable' : 'disable';
|
||||||
notify({
|
notify({
|
||||||
message: t(`account.card.${status}Account.success`),
|
message: t(`account.card.actions.${status}Account.success`),
|
||||||
type: 'positive',
|
type: 'positive',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -50,6 +58,17 @@ async function updateStatusUser(active) {
|
||||||
type: 'positive',
|
type: 'positive',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function deleteAccount() {
|
||||||
|
const { data } = await axios.delete(`VnUsers/${entityId.value}`);
|
||||||
|
if (data) {
|
||||||
|
notify({
|
||||||
|
message: t('account.card.actions.delete.success'),
|
||||||
|
type: 'positive',
|
||||||
|
});
|
||||||
|
router.push({ name: 'AccountList' });
|
||||||
|
}
|
||||||
|
}
|
||||||
const showSyncDialog = ref(false);
|
const showSyncDialog = ref(false);
|
||||||
const syncPassword = ref(null);
|
const syncPassword = ref(null);
|
||||||
const shouldSyncPassword = ref(false);
|
const shouldSyncPassword = ref(false);
|
||||||
|
@ -64,11 +83,27 @@ async function sync() {
|
||||||
type: 'positive',
|
type: 'positive',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
const askOldPass = ref(false);
|
||||||
|
const changePassRef = ref();
|
||||||
|
|
||||||
|
const onChangePass = (oldPass) => {
|
||||||
|
askOldPass.value = oldPass;
|
||||||
|
changePassRef.value.show();
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
hasitManagementAccess.value = useAcl().hasAny([
|
||||||
|
{ model: 'VnUser', props: 'higherPrivileges', accessType: 'WRITE' },
|
||||||
|
]);
|
||||||
|
hasSysadminAccess.value = useAcl().hasAny([
|
||||||
|
{ model: 'VnUser', props: 'adminUser', accessType: 'WRITE' },
|
||||||
|
]);
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<VnChangePassword
|
<VnChangePassword
|
||||||
ref="changePassRef"
|
ref="changePassRef"
|
||||||
:ask-old-pass="true"
|
:ask-old-pass="askOldPass"
|
||||||
:submit-fn="
|
:submit-fn="
|
||||||
async (newPassword, oldPassword) => {
|
async (newPassword, oldPassword) => {
|
||||||
await axios.patch(`Accounts/change-password`, {
|
await axios.patch(`Accounts/change-password`, {
|
||||||
|
@ -105,22 +140,51 @@ async function sync() {
|
||||||
class="full-width"
|
class="full-width"
|
||||||
clearable
|
clearable
|
||||||
clear-icon="close"
|
clear-icon="close"
|
||||||
|
type="password"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</VnConfirm>
|
</VnConfirm>
|
||||||
<QItem
|
<QItem
|
||||||
v-if="
|
v-if="hasitManagementAccess"
|
||||||
entityId == account.id &&
|
|
||||||
useAcl().hasAny([{ model: 'Account', props: '*', accessType: 'WRITE' }])
|
|
||||||
"
|
|
||||||
v-ripple
|
v-ripple
|
||||||
clickable
|
clickable
|
||||||
@click="$refs.changePassRef.show()"
|
@click="
|
||||||
|
openConfirmationModal(
|
||||||
|
t('account.card.actions.disableAccount.title'),
|
||||||
|
t('account.card.actions.disableAccount.subtitle'),
|
||||||
|
() => deleteAccount()
|
||||||
|
)
|
||||||
|
"
|
||||||
>
|
>
|
||||||
<QItemSection>{{ t('globals.changePass') }}</QItemSection>
|
<QItemSection>{{ t('globals.delete') }}</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
<QItem
|
<QItem
|
||||||
v-if="account.hasAccount"
|
v-if="hasSysadminAccess"
|
||||||
|
v-ripple
|
||||||
|
clickable
|
||||||
|
@click="user.id === account.id ? onChangePass(true) : onChangePass(false)"
|
||||||
|
>
|
||||||
|
<QItemSection v-if="user.id === account.id">
|
||||||
|
{{ t('globals.changePass') }}
|
||||||
|
</QItemSection>
|
||||||
|
<QItemSection v-else>{{ t('globals.setPass') }}</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
<QItem
|
||||||
|
v-if="!account.hasAccount && hasSysadminAccess"
|
||||||
|
v-ripple
|
||||||
|
clickable
|
||||||
|
@click="
|
||||||
|
openConfirmationModal(
|
||||||
|
t('account.card.actions.enableAccount.title'),
|
||||||
|
t('account.card.actions.enableAccount.subtitle'),
|
||||||
|
() => updateStatusAccount(true)
|
||||||
|
)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<QItemSection>{{ t('account.card.actions.enableAccount.name') }}</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
<QItem
|
||||||
|
v-if="account.hasAccount && hasSysadminAccess"
|
||||||
v-ripple
|
v-ripple
|
||||||
clickable
|
clickable
|
||||||
@click="
|
@click="
|
||||||
|
@ -135,7 +199,7 @@ async function sync() {
|
||||||
</QItem>
|
</QItem>
|
||||||
|
|
||||||
<QItem
|
<QItem
|
||||||
v-if="!account.active"
|
v-if="!account.active && hasitManagementAccess"
|
||||||
v-ripple
|
v-ripple
|
||||||
clickable
|
clickable
|
||||||
@click="
|
@click="
|
||||||
|
@ -149,7 +213,7 @@ async function sync() {
|
||||||
<QItemSection>{{ t('account.card.actions.activateUser.name') }}</QItemSection>
|
<QItemSection>{{ t('account.card.actions.activateUser.name') }}</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
<QItem
|
<QItem
|
||||||
v-if="account.active"
|
v-if="account.active && hasitManagementAccess"
|
||||||
v-ripple
|
v-ripple
|
||||||
clickable
|
clickable
|
||||||
@click="
|
@click="
|
||||||
|
@ -162,7 +226,12 @@ async function sync() {
|
||||||
>
|
>
|
||||||
<QItemSection>{{ t('account.card.actions.deactivateUser.name') }}</QItemSection>
|
<QItemSection>{{ t('account.card.actions.deactivateUser.name') }}</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
<QItem v-ripple clickable @click="showSyncDialog = true">
|
<QItem
|
||||||
|
v-if="useAcl().hasAny([{ model: 'VnRole', props: '*', accessType: 'WRITE' }])"
|
||||||
|
v-ripple
|
||||||
|
clickable
|
||||||
|
@click="showSyncDialog = true"
|
||||||
|
>
|
||||||
<QItemSection>{{ t('account.card.actions.sync.name') }}</QItemSection>
|
<QItemSection>{{ t('account.card.actions.sync.name') }}</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
<QSeparator />
|
<QSeparator />
|
||||||
|
|
|
@ -9,6 +9,7 @@ import AccountMailAliasCreateForm from './AccountMailAliasCreateForm.vue';
|
||||||
import { useVnConfirm } from 'composables/useVnConfirm';
|
import { useVnConfirm } from 'composables/useVnConfirm';
|
||||||
import { useArrayData } from 'composables/useArrayData';
|
import { useArrayData } from 'composables/useArrayData';
|
||||||
import useNotify from 'src/composables/useNotify.js';
|
import useNotify from 'src/composables/useNotify.js';
|
||||||
|
import useHasAccount from 'src/composables/useHasAccount.js';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
@ -50,16 +51,6 @@ const columns = computed(() => [
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const fetchAccountExistence = async () => {
|
|
||||||
try {
|
|
||||||
const { data } = await axios.get(`Accounts/${route.params.id}/exists`);
|
|
||||||
return data.exists;
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error fetching account existence', error);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const deleteMailAlias = async (row) => {
|
const deleteMailAlias = async (row) => {
|
||||||
await axios.delete(`${urlPath}/${row.id}`);
|
await axios.delete(`${urlPath}/${row.id}`);
|
||||||
fetchMailAliases();
|
fetchMailAliases();
|
||||||
|
@ -79,7 +70,7 @@ const fetchMailAliases = async () => {
|
||||||
|
|
||||||
const getAccountData = async (reload = true) => {
|
const getAccountData = async (reload = true) => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
hasAccount.value = await fetchAccountExistence();
|
hasAccount.value = await useHasAccount(route.params.id);
|
||||||
if (!hasAccount.value) {
|
if (!hasAccount.value) {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
store.data = [];
|
store.data = [];
|
||||||
|
|
|
@ -9,6 +9,7 @@ import VnRow from 'components/ui/VnRow.vue';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { useStateStore } from 'stores/useStateStore';
|
import { useStateStore } from 'stores/useStateStore';
|
||||||
import useNotify from 'src/composables/useNotify.js';
|
import useNotify from 'src/composables/useNotify.js';
|
||||||
|
import useHasAccount from 'src/composables/useHasAccount';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
@ -30,23 +31,9 @@ const hasDataChanged = computed(
|
||||||
initialData.value.hasData !== hasData.value
|
initialData.value.hasData !== hasData.value
|
||||||
);
|
);
|
||||||
|
|
||||||
const fetchAccountExistence = async () => {
|
|
||||||
try {
|
|
||||||
const { data } = await axios.get(`Accounts/${route.params.id}/exists`);
|
|
||||||
return data.exists;
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error fetching account existence', error);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchMailForwards = async () => {
|
const fetchMailForwards = async () => {
|
||||||
try {
|
const response = await axios.get(`MailForwards/${route.params.id}`);
|
||||||
const response = await axios.get(`MailForwards/${route.params.id}`);
|
return response.data;
|
||||||
return response.data;
|
|
||||||
} catch {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const deleteMailForward = async () => {
|
const deleteMailForward = async () => {
|
||||||
|
@ -72,7 +59,7 @@ const setInitialData = async () => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
initialData.value.account = route.params.id;
|
initialData.value.account = route.params.id;
|
||||||
formData.value.account = route.params.id;
|
formData.value.account = route.params.id;
|
||||||
hasAccount.value = await fetchAccountExistence(route.params.id);
|
hasAccount.value = await useHasAccount(route.params.id);
|
||||||
if (!hasAccount.value) {
|
if (!hasAccount.value) {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -7,6 +7,7 @@ import CardSummary from 'components/ui/CardSummary.vue';
|
||||||
import VnLv from 'src/components/ui/VnLv.vue';
|
import VnLv from 'src/components/ui/VnLv.vue';
|
||||||
|
|
||||||
import { useArrayData } from 'src/composables/useArrayData';
|
import { useArrayData } from 'src/composables/useArrayData';
|
||||||
|
import AccountDescriptorMenu from './AccountDescriptorMenu.vue';
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
@ -31,12 +32,14 @@ const filter = {
|
||||||
<template>
|
<template>
|
||||||
<CardSummary
|
<CardSummary
|
||||||
data-key="AccountId"
|
data-key="AccountId"
|
||||||
ref="AccountSummary"
|
|
||||||
url="VnUsers/preview"
|
url="VnUsers/preview"
|
||||||
:filter="filter"
|
:filter="filter"
|
||||||
@on-fetch="(data) => (account = data)"
|
@on-fetch="(data) => (account = data)"
|
||||||
>
|
>
|
||||||
<template #header>{{ account.id }} - {{ account.nickname }}</template>
|
<template #header>{{ account.id }} - {{ account.nickname }}</template>
|
||||||
|
<template #menu="">
|
||||||
|
<AccountDescriptorMenu :entity-id="entityId" />
|
||||||
|
</template>
|
||||||
<template #body>
|
<template #body>
|
||||||
<QCard class="vn-one">
|
<QCard class="vn-one">
|
||||||
<QCardSection class="q-pa-none">
|
<QCardSection class="q-pa-none">
|
||||||
|
|
|
@ -1,21 +1,13 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import VnCard from 'components/common/VnCard.vue';
|
import VnCardBeta from 'components/common/VnCardBeta.vue';
|
||||||
import ClaimDescriptor from './ClaimDescriptor.vue';
|
import ClaimDescriptor from './ClaimDescriptor.vue';
|
||||||
import ClaimFilter from '../ClaimFilter.vue';
|
|
||||||
import filter from './ClaimFilter.js';
|
import filter from './ClaimFilter.js';
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<VnCard
|
<VnCardBeta
|
||||||
data-key="Claim"
|
data-key="Claim"
|
||||||
base-url="Claims"
|
base-url="Claims"
|
||||||
:descriptor="ClaimDescriptor"
|
:descriptor="ClaimDescriptor"
|
||||||
:filter-panel="ClaimFilter"
|
|
||||||
search-data-key="ClaimList"
|
|
||||||
:filter="filter"
|
:filter="filter"
|
||||||
:searchbar-props="{
|
|
||||||
url: 'Claims/filter',
|
|
||||||
label: 'Search claim',
|
|
||||||
info: 'You can search by claim id or customer name',
|
|
||||||
}"
|
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -19,6 +19,7 @@ import ClaimNotes from 'src/pages/Claim/Card/ClaimNotes.vue';
|
||||||
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
|
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
|
||||||
import CustomerDescriptorProxy from 'src/pages/Customer/Card/CustomerDescriptorProxy.vue';
|
import CustomerDescriptorProxy from 'src/pages/Customer/Card/CustomerDescriptorProxy.vue';
|
||||||
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
|
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
|
||||||
|
import ClaimDescriptorMenu from './ClaimDescriptorMenu.vue';
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
@ -228,6 +229,9 @@ function claimUrl(section) {
|
||||||
</QList>
|
</QList>
|
||||||
</QBtnDropdown>
|
</QBtnDropdown>
|
||||||
</template>
|
</template>
|
||||||
|
<template #menu="{ entity }">
|
||||||
|
<ClaimDescriptorMenu :claim="entity.claim" />
|
||||||
|
</template>
|
||||||
<template #body="{ entity: { claim, salesClaimed, developments } }">
|
<template #body="{ entity: { claim, salesClaimed, developments } }">
|
||||||
<QCard class="vn-one" v-if="$route.name != 'ClaimSummary'">
|
<QCard class="vn-one" v-if="$route.name != 'ClaimSummary'">
|
||||||
<VnTitle
|
<VnTitle
|
||||||
|
|
|
@ -2,18 +2,18 @@
|
||||||
import { ref, computed } from 'vue';
|
import { ref, computed } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { toDate } from 'filters/index';
|
import { toDate } from 'filters/index';
|
||||||
import VnSearchbar from 'components/ui/VnSearchbar.vue';
|
|
||||||
import ClaimFilter from './ClaimFilter.vue';
|
import ClaimFilter from './ClaimFilter.vue';
|
||||||
import CustomerDescriptorProxy from 'src/pages/Customer/Card/CustomerDescriptorProxy.vue';
|
import CustomerDescriptorProxy from 'src/pages/Customer/Card/CustomerDescriptorProxy.vue';
|
||||||
import VnUserLink from 'src/components/ui/VnUserLink.vue';
|
import VnUserLink from 'src/components/ui/VnUserLink.vue';
|
||||||
import ClaimSummary from './Card/ClaimSummary.vue';
|
import ClaimSummary from './Card/ClaimSummary.vue';
|
||||||
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
|
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
|
||||||
import RightMenu from 'src/components/common/RightMenu.vue';
|
|
||||||
import VnTable from 'src/components/VnTable/VnTable.vue';
|
import VnTable from 'src/components/VnTable/VnTable.vue';
|
||||||
import ZoneDescriptorProxy from '../Zone/Card/ZoneDescriptorProxy.vue';
|
import ZoneDescriptorProxy from '../Zone/Card/ZoneDescriptorProxy.vue';
|
||||||
|
import VnSection from 'src/components/common/VnSection.vue';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { viewSummary } = useSummaryDialog();
|
const { viewSummary } = useSummaryDialog();
|
||||||
|
const dataKey = 'ClaimList';
|
||||||
|
|
||||||
const claimFilterRef = ref();
|
const claimFilterRef = ref();
|
||||||
const columns = computed(() => [
|
const columns = computed(() => [
|
||||||
|
@ -125,48 +125,50 @@ const STATE_COLOR = {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<VnSearchbar
|
<VnSection
|
||||||
data-key="ClaimList"
|
:data-key="dataKey"
|
||||||
:label="t('Search claim')"
|
:columns="columns"
|
||||||
:info="t('You can search by claim id or customer name')"
|
prefix="claim"
|
||||||
/>
|
:array-data-props="{
|
||||||
<RightMenu>
|
url: 'Claims/filter',
|
||||||
<template #right-panel>
|
order: ['cs.priority ASC', 'created ASC'],
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<template #rightMenu>
|
||||||
<ClaimFilter data-key="ClaimList" ref="claimFilterRef" />
|
<ClaimFilter data-key="ClaimList" ref="claimFilterRef" />
|
||||||
</template>
|
</template>
|
||||||
</RightMenu>
|
<template #body>
|
||||||
<VnTable
|
<VnTable
|
||||||
data-key="ClaimList"
|
:data-key="dataKey"
|
||||||
url="Claims/filter"
|
:columns="columns"
|
||||||
:order="['cs.priority ASC', 'created ASC']"
|
redirect="claim"
|
||||||
:columns="columns"
|
:right-search="false"
|
||||||
redirect="claim"
|
auto-load
|
||||||
:right-search="false"
|
>
|
||||||
>
|
<template #column-clientFk="{ row }">
|
||||||
<template #column-clientFk="{ row }">
|
<span class="link" @click.stop>
|
||||||
<span class="link" @click.stop>
|
{{ row.clientName }}
|
||||||
{{ row.clientName }}
|
<CustomerDescriptorProxy :id="row.clientFk" />
|
||||||
<CustomerDescriptorProxy :id="row.clientFk" />
|
</span>
|
||||||
</span>
|
</template>
|
||||||
|
<template #column-attendedBy="{ row }">
|
||||||
|
<span @click.stop>
|
||||||
|
<VnUserLink :name="row.workerName" :worker-id="row.workerFk" />
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<template #column-zoneFk="{ row }">
|
||||||
|
<span class="link" @click.stop>
|
||||||
|
{{ row.zoneName }}
|
||||||
|
<ZoneDescriptorProxy :id="row.zoneId" />
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</VnTable>
|
||||||
</template>
|
</template>
|
||||||
<template #column-attendedBy="{ row }">
|
</VnSection>
|
||||||
<span @click.stop>
|
|
||||||
<VnUserLink :name="row.workerName" :worker-id="row.workerFk" />
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<template #column-zoneFk="{ row }">
|
|
||||||
<span class="link" @click.stop>
|
|
||||||
{{ row.zoneName }}
|
|
||||||
<ZoneDescriptorProxy :id="row.zoneId" />
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
</VnTable>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<i18n>
|
<i18n>
|
||||||
es:
|
es:
|
||||||
Search claim: Buscar reclamación
|
|
||||||
You can search by claim id or customer name: Puedes buscar por id de la reclamación o nombre del cliente
|
|
||||||
params:
|
params:
|
||||||
stateCode: Estado
|
stateCode: Estado
|
||||||
en:
|
en:
|
||||||
|
|
|
@ -44,3 +44,5 @@ claim:
|
||||||
fileDescription: 'Claim id {claimId} from client {clientName} id {clientId}'
|
fileDescription: 'Claim id {claimId} from client {clientName} id {clientId}'
|
||||||
noData: 'There are no images/videos, click here or drag and drop the file'
|
noData: 'There are no images/videos, click here or drag and drop the file'
|
||||||
dragDrop: Drag and drop it here
|
dragDrop: Drag and drop it here
|
||||||
|
search: Search claims
|
||||||
|
searchInfo: You can search by claim id or customer name
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
Search claim: Buscar reclamación
|
|
||||||
You can search by claim id or customer name: Puedes buscar por id de la reclamación o nombre del cliente
|
|
||||||
claim:
|
claim:
|
||||||
customer: Cliente
|
customer: Cliente
|
||||||
code: Código
|
code: Código
|
||||||
|
@ -46,3 +44,5 @@ claim:
|
||||||
fileDescription: 'ID de reclamación {claimId} del cliente {clientName} con ID {clientId}'
|
fileDescription: 'ID de reclamación {claimId} del cliente {clientName} con ID {clientId}'
|
||||||
noData: 'No hay imágenes/videos, haz clic aquí o arrastra y suelta el archivo'
|
noData: 'No hay imágenes/videos, haz clic aquí o arrastra y suelta el archivo'
|
||||||
dragDrop: Arrastra y suelta aquí
|
dragDrop: Arrastra y suelta aquí
|
||||||
|
search: Buscar reclamación
|
||||||
|
searchInfo: Puedes buscar por ID de la reclamación o nombre del cliente
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, onMounted } from 'vue';
|
import { ref, computed } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
|
@ -11,16 +11,9 @@ import CardDescriptor from 'components/ui/CardDescriptor.vue';
|
||||||
import VnLv from 'src/components/ui/VnLv.vue';
|
import VnLv from 'src/components/ui/VnLv.vue';
|
||||||
import VnUserLink from 'src/components/ui/VnUserLink.vue';
|
import VnUserLink from 'src/components/ui/VnUserLink.vue';
|
||||||
import CustomerDescriptorMenu from './CustomerDescriptorMenu.vue';
|
import CustomerDescriptorMenu from './CustomerDescriptorMenu.vue';
|
||||||
import { useState } from 'src/composables/useState';
|
|
||||||
const state = useState();
|
|
||||||
|
|
||||||
const customer = ref();
|
|
||||||
|
|
||||||
onMounted(async () => {
|
|
||||||
customer.value = state.get('customer');
|
|
||||||
if (customer.value) customer.value.webAccess = data.value?.account?.isActive;
|
|
||||||
});
|
|
||||||
|
|
||||||
|
const customerDebt = ref();
|
||||||
|
const customerCredit = ref();
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
id: {
|
id: {
|
||||||
type: Number,
|
type: Number,
|
||||||
|
@ -42,10 +35,12 @@ const entityId = computed(() => {
|
||||||
|
|
||||||
const data = ref(useCardDescription());
|
const data = ref(useCardDescription());
|
||||||
const setData = (entity) => {
|
const setData = (entity) => {
|
||||||
|
customerDebt.value = entity?.debt;
|
||||||
|
customerCredit.value = entity?.credit;
|
||||||
data.value = useCardDescription(entity?.name, entity?.id);
|
data.value = useCardDescription(entity?.name, entity?.id);
|
||||||
};
|
};
|
||||||
const debtWarning = computed(() => {
|
const debtWarning = computed(() => {
|
||||||
return customer.value?.debt > customer.value?.credit ? 'negative' : 'primary';
|
return customerDebt.value > customerCredit.value ? 'negative' : 'primary';
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -97,26 +92,21 @@ const debtWarning = computed(() => {
|
||||||
:value="entity.businessType.description"
|
:value="entity.businessType.description"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #icons>
|
<template #icons="{ entity }">
|
||||||
<QCardActions v-if="customer" class="q-gutter-x-md">
|
<QCardActions class="q-gutter-x-md">
|
||||||
<QIcon
|
<QIcon
|
||||||
v-if="!customer.isActive"
|
v-if="!entity.isActive"
|
||||||
name="vn:disabled"
|
name="vn:disabled"
|
||||||
size="xs"
|
size="xs"
|
||||||
color="primary"
|
color="primary"
|
||||||
>
|
>
|
||||||
<QTooltip>{{ t('customer.card.isDisabled') }}</QTooltip>
|
<QTooltip>{{ t('customer.card.isDisabled') }}</QTooltip>
|
||||||
</QIcon>
|
</QIcon>
|
||||||
<QIcon
|
<QIcon v-if="entity.isFreezed" name="vn:frozen" size="xs" color="primary">
|
||||||
v-if="customer.isFreezed"
|
|
||||||
name="vn:frozen"
|
|
||||||
size="xs"
|
|
||||||
color="primary"
|
|
||||||
>
|
|
||||||
<QTooltip>{{ t('customer.card.isFrozen') }}</QTooltip>
|
<QTooltip>{{ t('customer.card.isFrozen') }}</QTooltip>
|
||||||
</QIcon>
|
</QIcon>
|
||||||
<QIcon
|
<QIcon
|
||||||
v-if="!customer.account?.active"
|
v-if="!entity.account?.active"
|
||||||
color="primary"
|
color="primary"
|
||||||
name="vn:noweb"
|
name="vn:noweb"
|
||||||
size="xs"
|
size="xs"
|
||||||
|
@ -124,7 +114,7 @@ const debtWarning = computed(() => {
|
||||||
<QTooltip>{{ t('customer.card.webAccountInactive') }}</QTooltip>
|
<QTooltip>{{ t('customer.card.webAccountInactive') }}</QTooltip>
|
||||||
</QIcon>
|
</QIcon>
|
||||||
<QIcon
|
<QIcon
|
||||||
v-if="customer.debt > customer.credit"
|
v-if="entity.debt > entity.credit"
|
||||||
name="vn:risk"
|
name="vn:risk"
|
||||||
size="xs"
|
size="xs"
|
||||||
:color="debtWarning"
|
:color="debtWarning"
|
||||||
|
@ -132,7 +122,7 @@ const debtWarning = computed(() => {
|
||||||
<QTooltip>{{ t('customer.card.hasDebt') }}</QTooltip>
|
<QTooltip>{{ t('customer.card.hasDebt') }}</QTooltip>
|
||||||
</QIcon>
|
</QIcon>
|
||||||
<QIcon
|
<QIcon
|
||||||
v-if="!customer.isTaxDataChecked"
|
v-if="!entity.isTaxDataChecked"
|
||||||
name="vn:no036"
|
name="vn:no036"
|
||||||
size="xs"
|
size="xs"
|
||||||
color="primary"
|
color="primary"
|
||||||
|
@ -140,7 +130,7 @@ const debtWarning = computed(() => {
|
||||||
<QTooltip>{{ t('customer.card.notChecked') }}</QTooltip>
|
<QTooltip>{{ t('customer.card.notChecked') }}</QTooltip>
|
||||||
</QIcon>
|
</QIcon>
|
||||||
<QBtn
|
<QBtn
|
||||||
v-if="customer.unpaid"
|
v-if="entity.unpaid"
|
||||||
flat
|
flat
|
||||||
size="sm"
|
size="sm"
|
||||||
icon="vn:Client_unpaid"
|
icon="vn:Client_unpaid"
|
||||||
|
|
|
@ -12,6 +12,7 @@ import VnLinkMail from 'src/components/ui/VnLinkMail.vue';
|
||||||
import CustomerSummaryTable from 'src/pages/Customer/components/CustomerSummaryTable.vue';
|
import CustomerSummaryTable from 'src/pages/Customer/components/CustomerSummaryTable.vue';
|
||||||
import VnTitle from 'src/components/common/VnTitle.vue';
|
import VnTitle from 'src/components/common/VnTitle.vue';
|
||||||
import VnRow from 'src/components/ui/VnRow.vue';
|
import VnRow from 'src/components/ui/VnRow.vue';
|
||||||
|
import CustomerDescriptorMenu from './CustomerDescriptorMenu.vue';
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const grafanaUrl = 'https://grafana.verdnatura.es';
|
const grafanaUrl = 'https://grafana.verdnatura.es';
|
||||||
|
@ -70,6 +71,9 @@ const sumRisk = ({ clientRisks }) => {
|
||||||
data-key="CustomerSummary"
|
data-key="CustomerSummary"
|
||||||
module-name="Customer"
|
module-name="Customer"
|
||||||
>
|
>
|
||||||
|
<template #menu="{ entity }">
|
||||||
|
<CustomerDescriptorMenu :customer="entity" />
|
||||||
|
</template>
|
||||||
<template #body="{ entity }">
|
<template #body="{ entity }">
|
||||||
<QCard class="vn-one">
|
<QCard class="vn-one">
|
||||||
<VnTitle
|
<VnTitle
|
||||||
|
@ -94,14 +98,13 @@ const sumRisk = ({ clientRisks }) => {
|
||||||
:phone-number="entity.mobile"
|
:phone-number="entity.mobile"
|
||||||
:channel="entity.country?.saySimpleCountry?.channel"
|
:channel="entity.country?.saySimpleCountry?.channel"
|
||||||
class="q-ml-xs"
|
class="q-ml-xs"
|
||||||
:country="entity.country?.code"
|
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</VnLv>
|
</VnLv>
|
||||||
<VnLv :value="entity.email" copy
|
<VnLv :value="entity.email" copy
|
||||||
><template #label>
|
><template #label>
|
||||||
{{ t('globals.params.email') }}
|
{{ t('globals.params.email') }}
|
||||||
<VnLinkMail :email="entity.email"></VnLinkMail> </template
|
<VnLinkMail email="entity.email"></VnLinkMail> </template
|
||||||
></VnLv>
|
></VnLv>
|
||||||
<VnLv
|
<VnLv
|
||||||
:label="t('customer.summary.salesPerson')"
|
:label="t('customer.summary.salesPerson')"
|
||||||
|
@ -173,7 +176,7 @@ const sumRisk = ({ clientRisks }) => {
|
||||||
:label="t('customer.summary.notifyByEmail')"
|
:label="t('customer.summary.notifyByEmail')"
|
||||||
:value="entity.isToBeMailed"
|
:value="entity.isToBeMailed"
|
||||||
/>
|
/>
|
||||||
<VnLv :label="t('globals.isVies')" :value="entity.isVies" />
|
<VnLv :label="t('customer.summary.vies')" :value="entity.isVies" />
|
||||||
</VnRow>
|
</VnRow>
|
||||||
</QCard>
|
</QCard>
|
||||||
<QCard class="vn-one">
|
<QCard class="vn-one">
|
||||||
|
|
|
@ -11,6 +11,7 @@ import VnInput from 'src/components/common/VnInput.vue';
|
||||||
import VnSelect from 'src/components/common/VnSelect.vue';
|
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||||
import VnSelectDialog from 'src/components/common/VnSelectDialog.vue';
|
import VnSelectDialog from 'src/components/common/VnSelectDialog.vue';
|
||||||
import CustomerNewCustomsAgent from 'src/pages/Customer/components/CustomerNewCustomsAgent.vue';
|
import CustomerNewCustomsAgent from 'src/pages/Customer/components/CustomerNewCustomsAgent.vue';
|
||||||
|
import VnInputNumber from 'src/components/common/VnInputNumber.vue';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
@ -150,6 +151,22 @@ function onAgentCreated({ id, fiscalName }, data) {
|
||||||
</template>
|
</template>
|
||||||
</VnSelectDialog>
|
</VnSelectDialog>
|
||||||
</VnRow>
|
</VnRow>
|
||||||
|
<VnRow>
|
||||||
|
<VnInputNumber
|
||||||
|
:label="t('Longitude')"
|
||||||
|
clearable
|
||||||
|
v-model="data.longitude"
|
||||||
|
:decimal-places="7"
|
||||||
|
:positive="false"
|
||||||
|
/>
|
||||||
|
<VnInputNumber
|
||||||
|
:label="t('Latitude')"
|
||||||
|
clearable
|
||||||
|
v-model="data.latitude"
|
||||||
|
:decimal-places="7"
|
||||||
|
:positive="false"
|
||||||
|
/>
|
||||||
|
</VnRow>
|
||||||
</template>
|
</template>
|
||||||
</FormModel>
|
</FormModel>
|
||||||
</template>
|
</template>
|
||||||
|
@ -175,4 +192,6 @@ es:
|
||||||
Mobile: Movíl
|
Mobile: Movíl
|
||||||
Incoterms: Incoterms
|
Incoterms: Incoterms
|
||||||
Customs agent: Agente de aduanas
|
Customs agent: Agente de aduanas
|
||||||
|
Longitude: Longitud
|
||||||
|
Latitude: Latitud
|
||||||
</i18n>
|
</i18n>
|
||||||
|
|
|
@ -293,8 +293,16 @@ function handleLocation(data, location) {
|
||||||
:label="t('Longitude')"
|
:label="t('Longitude')"
|
||||||
clearable
|
clearable
|
||||||
v-model="data.longitude"
|
v-model="data.longitude"
|
||||||
|
:decimal-places="7"
|
||||||
|
:positive="false"
|
||||||
|
/>
|
||||||
|
<VnInputNumber
|
||||||
|
:label="t('Latitude')"
|
||||||
|
clearable
|
||||||
|
v-model="data.latitude"
|
||||||
|
:decimal-places="7"
|
||||||
|
:positive="false"
|
||||||
/>
|
/>
|
||||||
<VnInputNumber :label="t('Latitude')" clearable v-model="data.latitude" />
|
|
||||||
</VnRow>
|
</VnRow>
|
||||||
<h4 class="q-mb-xs">{{ t('Notes') }}</h4>
|
<h4 class="q-mb-xs">{{ t('Notes') }}</h4>
|
||||||
<VnRow
|
<VnRow
|
||||||
|
|
|
@ -1,21 +1,13 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import VnCard from 'components/common/VnCard.vue';
|
import VnCardBeta from 'components/common/VnCardBeta.vue';
|
||||||
import EntryDescriptor from './EntryDescriptor.vue';
|
import EntryDescriptor from './EntryDescriptor.vue';
|
||||||
import EntryFilter from '../EntryFilter.vue';
|
import filter from './EntryFilter.js'
|
||||||
import filter from './EntryFilter.js';
|
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<VnCard
|
<VnCardBeta
|
||||||
data-key="Entry"
|
data-key="Entry"
|
||||||
base-url="Entries"
|
base-url="Entries"
|
||||||
:filter="filter"
|
|
||||||
:descriptor="EntryDescriptor"
|
:descriptor="EntryDescriptor"
|
||||||
:filter-panel="EntryFilter"
|
:user-filter="filter"
|
||||||
search-data-key="EntryList"
|
|
||||||
:searchbar-props="{
|
|
||||||
url: 'Entries/filter',
|
|
||||||
label: 'Search entries',
|
|
||||||
info: 'You can search by entry reference',
|
|
||||||
}"
|
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -7,9 +7,9 @@ import CardDescriptor from 'components/ui/CardDescriptor.vue';
|
||||||
import VnLv from 'src/components/ui/VnLv.vue';
|
import VnLv from 'src/components/ui/VnLv.vue';
|
||||||
|
|
||||||
import { toDate } from 'src/filters';
|
import { toDate } from 'src/filters';
|
||||||
import { usePrintService } from 'composables/usePrintService';
|
|
||||||
import { getUrl } from 'src/composables/getUrl';
|
import { getUrl } from 'src/composables/getUrl';
|
||||||
import filter from './EntryFilter.js';
|
import filter from './EntryFilter.js';
|
||||||
|
import EntryDescriptorMenu from './EntryDescriptorMenu.vue';
|
||||||
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
id: {
|
id: {
|
||||||
|
@ -21,7 +21,6 @@ const $props = defineProps({
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { openReport } = usePrintService();
|
|
||||||
const entryDescriptorRef = ref(null);
|
const entryDescriptorRef = ref(null);
|
||||||
const url = ref();
|
const url = ref();
|
||||||
|
|
||||||
|
@ -52,10 +51,6 @@ const getEntryRedirectionFilter = (entry) => {
|
||||||
to,
|
to,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const showEntryReport = () => {
|
|
||||||
openReport(`Entries/${route.params.id}/entry-order-pdf`);
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -68,14 +63,12 @@ const showEntryReport = () => {
|
||||||
data-key="Entry"
|
data-key="Entry"
|
||||||
>
|
>
|
||||||
<template #menu="{ entity }">
|
<template #menu="{ entity }">
|
||||||
<QItem v-ripple clickable @click="showEntryReport(entity)">
|
<EntryDescriptorMenu :id="entity.id" />
|
||||||
<QItemSection>{{ t('Show entry report') }}</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
</template>
|
</template>
|
||||||
<template #body="{ entity }">
|
<template #body="{ entity }">
|
||||||
<VnLv :label="t('globals.agency')" :value="entity.travel?.agency?.name" />
|
<VnLv :label="t('globals.agency')" :value="entity.travel?.agency?.name" />
|
||||||
<VnLv :label="t('globals.shipped')" :value="toDate(entity.travel?.shipped)" />
|
<VnLv :label="t('shipped')" :value="toDate(entity.travel?.shipped)" />
|
||||||
<VnLv :label="t('globals.landed')" :value="toDate(entity.travel?.landed)" />
|
<VnLv :label="t('landed')" :value="toDate(entity.travel?.landed)" />
|
||||||
<VnLv
|
<VnLv
|
||||||
:label="t('globals.warehouseOut')"
|
:label="t('globals.warehouseOut')"
|
||||||
:value="entity.travel?.warehouseOut?.name"
|
:value="entity.travel?.warehouseOut?.name"
|
||||||
|
@ -154,7 +147,6 @@ es:
|
||||||
Supplier card: Ficha del proveedor
|
Supplier card: Ficha del proveedor
|
||||||
All travels with current agency: Todos los envíos con la agencia actual
|
All travels with current agency: Todos los envíos con la agencia actual
|
||||||
All entries with current supplier: Todas las entradas con el proveedor actual
|
All entries with current supplier: Todas las entradas con el proveedor actual
|
||||||
Show entry report: Ver informe del pedido
|
|
||||||
Go to module index: Ir al índice del modulo
|
Go to module index: Ir al índice del modulo
|
||||||
Inventory entry: Es inventario
|
Inventory entry: Es inventario
|
||||||
Virtual entry: Es una redada
|
Virtual entry: Es una redada
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
<script setup>
|
||||||
|
import { usePrintService } from 'composables/usePrintService';
|
||||||
|
|
||||||
|
const { openReport } = usePrintService();
|
||||||
|
|
||||||
|
const $props = defineProps({
|
||||||
|
id: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
function showEntryReport() {
|
||||||
|
openReport(`Entries/${$props.id}/entry-order-pdf`);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<QItem v-ripple clickable @click="showEntryReport">
|
||||||
|
<QItemSection>{{ $t('entryList.list.showEntryReport') }}</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
</template>
|
|
@ -12,6 +12,7 @@ import { getUrl } from 'src/composables/getUrl';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import FetchedTags from 'src/components/ui/FetchedTags.vue';
|
import FetchedTags from 'src/components/ui/FetchedTags.vue';
|
||||||
import VnToSummary from 'src/components/ui/VnToSummary.vue';
|
import VnToSummary from 'src/components/ui/VnToSummary.vue';
|
||||||
|
import EntryDescriptorMenu from './EntryDescriptorMenu.vue';
|
||||||
import VnRow from 'src/components/ui/VnRow.vue';
|
import VnRow from 'src/components/ui/VnRow.vue';
|
||||||
import VnTitle from 'src/components/common/VnTitle.vue';
|
import VnTitle from 'src/components/common/VnTitle.vue';
|
||||||
|
|
||||||
|
@ -172,6 +173,9 @@ const fetchEntryBuys = async () => {
|
||||||
<template #header>
|
<template #header>
|
||||||
<span>{{ entry.id }} - {{ entry.supplier.nickname }}</span>
|
<span>{{ entry.id }} - {{ entry.supplier.nickname }}</span>
|
||||||
</template>
|
</template>
|
||||||
|
<template #menu="{ entity }">
|
||||||
|
<EntryDescriptorMenu :id="entity.id" />
|
||||||
|
</template>
|
||||||
<template #body>
|
<template #body>
|
||||||
<QCard class="vn-one">
|
<QCard class="vn-one">
|
||||||
<VnTitle
|
<VnTitle
|
||||||
|
@ -207,7 +211,10 @@ const fetchEntryBuys = async () => {
|
||||||
:label="t('entry.summary.travelAgency')"
|
:label="t('entry.summary.travelAgency')"
|
||||||
:value="entry.travel.agency?.name"
|
:value="entry.travel.agency?.name"
|
||||||
/>
|
/>
|
||||||
<VnLv :label="t('globals.shipped')" :value="toDate(entry.travel.shipped)" />
|
<VnLv
|
||||||
|
:label="t('globals.shipped')"
|
||||||
|
:value="toDate(entry.travel.shipped)"
|
||||||
|
/>
|
||||||
<VnLv
|
<VnLv
|
||||||
:label="t('globals.warehouseOut')"
|
:label="t('globals.warehouseOut')"
|
||||||
:value="entry.travel.warehouseOut?.name"
|
:value="entry.travel.warehouseOut?.name"
|
||||||
|
|
|
@ -40,7 +40,7 @@ const companiesOptions = ref([]);
|
||||||
<VnFilterPanel :data-key="props.dataKey" :search-button="true">
|
<VnFilterPanel :data-key="props.dataKey" :search-button="true">
|
||||||
<template #tags="{ tag, formatFn }">
|
<template #tags="{ tag, formatFn }">
|
||||||
<div class="q-gutter-x-xs">
|
<div class="q-gutter-x-xs">
|
||||||
<strong>{{ t(`params.${tag.label}`) }}: </strong>
|
<strong>{{ t(`entryFilter.params.${tag.label}`) }}: </strong>
|
||||||
<span>{{ formatFn(tag.value) }}</span>
|
<span>{{ formatFn(tag.value) }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -49,7 +49,7 @@ const companiesOptions = ref([]);
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<VnInput
|
<VnInput
|
||||||
v-model="params.search"
|
v-model="params.search"
|
||||||
:label="t('entryFilter.filter.search')"
|
:label="t('entryFilter.params.search')"
|
||||||
is-outlined
|
is-outlined
|
||||||
/>
|
/>
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
|
@ -58,7 +58,7 @@ const companiesOptions = ref([]);
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<VnInput
|
<VnInput
|
||||||
v-model="params.reference"
|
v-model="params.reference"
|
||||||
:label="t('entryFilter.filter.reference')"
|
:label="t('entryFilter.params.reference')"
|
||||||
is-outlined
|
is-outlined
|
||||||
/>
|
/>
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
|
@ -67,7 +67,7 @@ const companiesOptions = ref([]);
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<VnInput
|
<VnInput
|
||||||
v-model="params.invoiceNumber"
|
v-model="params.invoiceNumber"
|
||||||
:label="t('params.invoiceNumber')"
|
:label="t('entryFilter.params.invoiceNumber')"
|
||||||
is-outlined
|
is-outlined
|
||||||
/>
|
/>
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
|
@ -76,7 +76,7 @@ const companiesOptions = ref([]);
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<VnInput
|
<VnInput
|
||||||
v-model="params.travelFk"
|
v-model="params.travelFk"
|
||||||
:label="t('params.travelFk')"
|
:label="t('entryFilter.params.travelFk')"
|
||||||
is-outlined
|
is-outlined
|
||||||
/>
|
/>
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
|
@ -84,7 +84,7 @@ const companiesOptions = ref([]);
|
||||||
<QItem>
|
<QItem>
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<VnSelect
|
<VnSelect
|
||||||
:label="t('params.companyFk')"
|
:label="t('entryFilter.params.companyFk')"
|
||||||
v-model="params.companyFk"
|
v-model="params.companyFk"
|
||||||
@update:model-value="searchFn()"
|
@update:model-value="searchFn()"
|
||||||
:options="companiesOptions"
|
:options="companiesOptions"
|
||||||
|
@ -100,7 +100,7 @@ const companiesOptions = ref([]);
|
||||||
<QItem>
|
<QItem>
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<VnSelect
|
<VnSelect
|
||||||
:label="t('params.currencyFk')"
|
:label="t('entryFilter.params.currencyFk')"
|
||||||
v-model="params.currencyFk"
|
v-model="params.currencyFk"
|
||||||
@update:model-value="searchFn()"
|
@update:model-value="searchFn()"
|
||||||
:options="currenciesOptions"
|
:options="currenciesOptions"
|
||||||
|
@ -116,7 +116,7 @@ const companiesOptions = ref([]);
|
||||||
<QItem>
|
<QItem>
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<VnSelect
|
<VnSelect
|
||||||
:label="t('params.supplierFk')"
|
:label="t('entryFilter.params.supplierFk')"
|
||||||
v-model="params.supplierFk"
|
v-model="params.supplierFk"
|
||||||
@update:model-value="searchFn()"
|
@update:model-value="searchFn()"
|
||||||
url="Suppliers"
|
url="Suppliers"
|
||||||
|
@ -148,7 +148,7 @@ const companiesOptions = ref([]);
|
||||||
<QItem>
|
<QItem>
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<VnInputDate
|
<VnInputDate
|
||||||
:label="t('params.created')"
|
:label="t('entryFilter.params.created')"
|
||||||
v-model="params.created"
|
v-model="params.created"
|
||||||
@update:model-value="searchFn()"
|
@update:model-value="searchFn()"
|
||||||
is-outlined
|
is-outlined
|
||||||
|
@ -158,7 +158,7 @@ const companiesOptions = ref([]);
|
||||||
<QItem>
|
<QItem>
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<VnInputDate
|
<VnInputDate
|
||||||
:label="t('params.from')"
|
:label="t('entryFilter.params.from')"
|
||||||
v-model="params.from"
|
v-model="params.from"
|
||||||
@update:model-value="searchFn()"
|
@update:model-value="searchFn()"
|
||||||
is-outlined
|
is-outlined
|
||||||
|
@ -168,7 +168,7 @@ const companiesOptions = ref([]);
|
||||||
<QItem>
|
<QItem>
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<VnInputDate
|
<VnInputDate
|
||||||
:label="t('params.to')"
|
:label="t('entryFilter.params.to')"
|
||||||
v-model="params.to"
|
v-model="params.to"
|
||||||
@update:model-value="searchFn()"
|
@update:model-value="searchFn()"
|
||||||
is-outlined
|
is-outlined
|
||||||
|
@ -178,14 +178,14 @@ const companiesOptions = ref([]);
|
||||||
<QItem>
|
<QItem>
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<QCheckbox
|
<QCheckbox
|
||||||
:label="t('params.isBooked')"
|
:label="t('entryFilter.params.isBooked')"
|
||||||
v-model="params.isBooked"
|
v-model="params.isBooked"
|
||||||
toggle-indeterminate
|
toggle-indeterminate
|
||||||
/>
|
/>
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<QCheckbox
|
<QCheckbox
|
||||||
:label="t('params.isConfirmed')"
|
:label="t('entryFilter.params.isConfirmed')"
|
||||||
v-model="params.isConfirmed"
|
v-model="params.isConfirmed"
|
||||||
toggle-indeterminate
|
toggle-indeterminate
|
||||||
/>
|
/>
|
||||||
|
@ -194,7 +194,7 @@ const companiesOptions = ref([]);
|
||||||
<QItem>
|
<QItem>
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<QCheckbox
|
<QCheckbox
|
||||||
:label="t('params.isOrdered')"
|
:label="t('entryFilter.params.isOrdered')"
|
||||||
v-model="params.isOrdered"
|
v-model="params.isOrdered"
|
||||||
toggle-indeterminate
|
toggle-indeterminate
|
||||||
/>
|
/>
|
||||||
|
@ -202,35 +202,4 @@ const companiesOptions = ref([]);
|
||||||
</QItem>
|
</QItem>
|
||||||
</template>
|
</template>
|
||||||
</VnFilterPanel>
|
</VnFilterPanel>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<i18n>
|
|
||||||
en:
|
|
||||||
params:
|
|
||||||
|
|
||||||
invoiceNumber: Invoice number
|
|
||||||
travelFk: Travel
|
|
||||||
companyFk: Company
|
|
||||||
currencyFk: Currency
|
|
||||||
supplierFk: Supplier
|
|
||||||
from: From
|
|
||||||
to: To
|
|
||||||
created: Created
|
|
||||||
isBooked: Booked
|
|
||||||
isConfirmed: Confirmed
|
|
||||||
isOrdered: Ordered
|
|
||||||
es:
|
|
||||||
params:
|
|
||||||
|
|
||||||
invoiceNumber: Núm. factura
|
|
||||||
travelFk: Envío
|
|
||||||
companyFk: Empresa
|
|
||||||
currencyFk: Moneda
|
|
||||||
supplierFk: Proveedor
|
|
||||||
from: Desde
|
|
||||||
to: Hasta
|
|
||||||
created: Fecha creación
|
|
||||||
isBooked: Asentado
|
|
||||||
isConfirmed: Confirmado
|
|
||||||
isOrdered: Pedida
|
|
||||||
</i18n>
|
|
|
@ -102,7 +102,7 @@ const columns = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
label: t('globals.weightByPiece'),
|
label: t('entry.latestBuys.tableVisibleColumns.weightByPiece'),
|
||||||
name: 'weightByPiece',
|
name: 'weightByPiece',
|
||||||
columnFilter: {
|
columnFilter: {
|
||||||
component: 'number',
|
component: 'number',
|
||||||
|
@ -157,7 +157,7 @@ const columns = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
label: t('entry.buys.packageValue'),
|
label: t('entry.latestBuys.tableVisibleColumns.packageValue'),
|
||||||
name: 'packageValue',
|
name: 'packageValue',
|
||||||
columnFilter: {
|
columnFilter: {
|
||||||
component: 'number',
|
component: 'number',
|
||||||
|
@ -262,8 +262,3 @@ onUnmounted(() => (stateStore.rightDrawer = false));
|
||||||
:right-search="false"
|
:right-search="false"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<i18n>
|
|
||||||
es:
|
|
||||||
Edit buy(s): Editar compra(s)
|
|
||||||
</i18n>
|
|
||||||
|
|
|
@ -2,17 +2,17 @@
|
||||||
import { ref, computed } from 'vue';
|
import { ref, computed } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import EntryFilter from './EntryFilter.vue';
|
import EntryFilter from './EntryFilter.vue';
|
||||||
import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
|
|
||||||
import VnTable from 'components/VnTable/VnTable.vue';
|
import VnTable from 'components/VnTable/VnTable.vue';
|
||||||
import RightMenu from 'src/components/common/RightMenu.vue';
|
|
||||||
import { toDate } from 'src/filters';
|
import { toDate } from 'src/filters';
|
||||||
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
|
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
|
||||||
import EntrySummary from './Card/EntrySummary.vue';
|
import EntrySummary from './Card/EntrySummary.vue';
|
||||||
import SupplierDescriptorProxy from 'src/pages/Supplier/Card/SupplierDescriptorProxy.vue';
|
import SupplierDescriptorProxy from 'src/pages/Supplier/Card/SupplierDescriptorProxy.vue';
|
||||||
import TravelDescriptorProxy from 'src/pages/Travel/Card/TravelDescriptorProxy.vue';
|
import TravelDescriptorProxy from 'src/pages/Travel/Card/TravelDescriptorProxy.vue';
|
||||||
|
import VnSection from 'src/components/common/VnSection.vue';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const tableRef = ref();
|
const tableRef = ref();
|
||||||
|
const dataKey = 'EntryList';
|
||||||
|
|
||||||
const { viewSummary } = useSummaryDialog();
|
const { viewSummary } = useSummaryDialog();
|
||||||
const entryFilter = {
|
const entryFilter = {
|
||||||
|
@ -178,74 +178,73 @@ const columns = computed(() => [
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<VnSearchbar
|
<VnSection
|
||||||
data-key="EntryList"
|
:data-key="dataKey"
|
||||||
|
:columns="columns"
|
||||||
|
prefix="entry"
|
||||||
url="Entries/filter"
|
url="Entries/filter"
|
||||||
:label="t('Search entries')"
|
:array-data-props="{
|
||||||
:info="t('You can search by entry reference')"
|
url: 'Entries/filter',
|
||||||
/>
|
order: 'id DESC',
|
||||||
<RightMenu>
|
userFilter: 'entryFilter',
|
||||||
<template #right-panel>
|
}"
|
||||||
|
>
|
||||||
|
<template #rightMenu>
|
||||||
<EntryFilter data-key="EntryList" />
|
<EntryFilter data-key="EntryList" />
|
||||||
</template>
|
</template>
|
||||||
</RightMenu>
|
<template #body>
|
||||||
<VnTable
|
<VnTable
|
||||||
ref="tableRef"
|
ref="tableRef"
|
||||||
data-key="EntryList"
|
:data-key="dataKey"
|
||||||
url="Entries/filter"
|
:create="{
|
||||||
:filter="entryFilter"
|
urlCreate: 'Entries',
|
||||||
:create="{
|
title: t('entry.list.newEntry'),
|
||||||
urlCreate: 'Entries',
|
onDataSaved: ({ id }) => tableRef.redirect(id),
|
||||||
title: t('Create entry'),
|
formInitialData: {},
|
||||||
onDataSaved: ({ id }) => tableRef.redirect(id),
|
}"
|
||||||
formInitialData: {},
|
:columns="columns"
|
||||||
}"
|
redirect="entry"
|
||||||
order="id DESC"
|
:right-search="false"
|
||||||
:columns="columns"
|
>
|
||||||
redirect="entry"
|
<template #column-status="{ row }">
|
||||||
:right-search="false"
|
<div class="row q-gutter-xs">
|
||||||
>
|
<QIcon
|
||||||
<template #column-status="{ row }">
|
v-if="!!row.isExcludedFromAvailable"
|
||||||
<div class="row q-gutter-xs">
|
name="vn:inventory"
|
||||||
<QIcon
|
color="primary"
|
||||||
v-if="!!row.isExcludedFromAvailable"
|
>
|
||||||
name="vn:inventory"
|
<QTooltip>{{
|
||||||
color="primary"
|
t(
|
||||||
>
|
'entry.list.tableVisibleColumns.isExcludedFromAvailable'
|
||||||
<QTooltip>{{
|
)
|
||||||
t('entry.list.tableVisibleColumns.isExcludedFromAvailable')
|
}}</QTooltip>
|
||||||
}}</QTooltip>
|
</QIcon>
|
||||||
</QIcon>
|
<QIcon v-if="!!row.isRaid" name="vn:net" color="primary">
|
||||||
<QIcon v-if="!!row.isRaid" name="vn:net" color="primary">
|
<QTooltip>
|
||||||
<QTooltip>
|
{{
|
||||||
{{
|
t('globals.raid', {
|
||||||
t('globals.raid', { daysInForward: row.daysInForward })
|
daysInForward: row.daysInForward,
|
||||||
}}</QTooltip
|
})
|
||||||
>
|
}}</QTooltip
|
||||||
</QIcon>
|
>
|
||||||
</div>
|
</QIcon>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #column-supplierFk="{ row }">
|
||||||
|
<span class="link" @click.stop>
|
||||||
|
{{ row.supplierName }}
|
||||||
|
<SupplierDescriptorProxy :id="row.supplierFk" />
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<template #column-travelFk="{ row }">
|
||||||
|
<span class="link" @click.stop>
|
||||||
|
{{ row.travelRef }}
|
||||||
|
<TravelDescriptorProxy :id="row.travelFk" />
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</VnTable>
|
||||||
</template>
|
</template>
|
||||||
<template #column-supplierFk="{ row }">
|
</VnSection>
|
||||||
<span class="link" @click.stop>
|
|
||||||
{{ row.supplierName }}
|
|
||||||
<SupplierDescriptorProxy :id="row.supplierFk" />
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<template #column-travelFk="{ row }">
|
|
||||||
<span class="link" @click.stop>
|
|
||||||
{{ row.travelRef }}
|
|
||||||
<TravelDescriptorProxy :id="row.travelFk" />
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
</VnTable>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<i18n>
|
|
||||||
es:
|
|
||||||
Inventory entry: Es inventario
|
|
||||||
Virtual entry: Es una redada
|
|
||||||
Search entries: Buscar entradas
|
|
||||||
You can search by entry reference: Puedes buscar por referencia de la entrada
|
|
||||||
Create entry: Crear entrada
|
|
||||||
</i18n>
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue';
|
import { ref, computed } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useState } from 'src/composables/useState';
|
import { useState } from 'src/composables/useState';
|
||||||
import { useQuasar } from 'quasar';
|
import { useQuasar } from 'quasar';
|
||||||
|
@ -19,7 +19,7 @@ const { t } = useI18n();
|
||||||
const quasar = useQuasar();
|
const quasar = useQuasar();
|
||||||
const state = useState();
|
const state = useState();
|
||||||
const user = state.getUser();
|
const user = state.getUser();
|
||||||
const columns = [
|
const columns = computed(() => [
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
label: 'Id',
|
label: 'Id',
|
||||||
|
@ -31,7 +31,7 @@ const columns = [
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
name: 'workerFk',
|
name: 'workerFk',
|
||||||
label: t('Buyer'),
|
label: t('entryStockBought.buyer'),
|
||||||
isTitle: true,
|
isTitle: true,
|
||||||
component: 'select',
|
component: 'select',
|
||||||
cardVisible: true,
|
cardVisible: true,
|
||||||
|
@ -49,7 +49,7 @@ const columns = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
align: 'center',
|
align: 'center',
|
||||||
label: t('Reserve'),
|
label: t('entryStockBought.reserve'),
|
||||||
name: 'reserve',
|
name: 'reserve',
|
||||||
columnFilter: false,
|
columnFilter: false,
|
||||||
create: true,
|
create: true,
|
||||||
|
@ -58,7 +58,7 @@ const columns = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
align: 'center',
|
align: 'center',
|
||||||
label: t('Bought'),
|
label: t('entryStockBought.bought'),
|
||||||
name: 'bought',
|
name: 'bought',
|
||||||
summation: true,
|
summation: true,
|
||||||
cardVisible: true,
|
cardVisible: true,
|
||||||
|
@ -66,7 +66,7 @@ const columns = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
label: t('Date'),
|
label: t('entryStockBought.date'),
|
||||||
name: 'dated',
|
name: 'dated',
|
||||||
component: 'date',
|
component: 'date',
|
||||||
visible: false,
|
visible: false,
|
||||||
|
@ -77,7 +77,7 @@ const columns = [
|
||||||
name: 'tableActions',
|
name: 'tableActions',
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
title: t('View more details'),
|
title: t('entryStockBought.viewMoreDetails'),
|
||||||
icon: 'search',
|
icon: 'search',
|
||||||
isPrimary: true,
|
isPrimary: true,
|
||||||
action: (row) => {
|
action: (row) => {
|
||||||
|
@ -92,7 +92,7 @@ const columns = [
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
]);
|
||||||
|
|
||||||
const fetchDataRef = ref();
|
const fetchDataRef = ref();
|
||||||
const travelDialogRef = ref(false);
|
const travelDialogRef = ref(false);
|
||||||
|
@ -166,7 +166,7 @@ function round(value) {
|
||||||
<VnRow class="travel">
|
<VnRow class="travel">
|
||||||
<div v-if="travel">
|
<div v-if="travel">
|
||||||
<span style="color: var(--vn-label-color)">
|
<span style="color: var(--vn-label-color)">
|
||||||
{{ t('Purchase Spaces') }}:
|
{{ t('entryStockBought.purchaseSpaces') }}:
|
||||||
</span>
|
</span>
|
||||||
<span>
|
<span>
|
||||||
{{ travel?.m3 }}
|
{{ travel?.m3 }}
|
||||||
|
@ -177,7 +177,7 @@ function round(value) {
|
||||||
flat
|
flat
|
||||||
icon="edit"
|
icon="edit"
|
||||||
@click="openDialog()"
|
@click="openDialog()"
|
||||||
:title="t('Edit travel')"
|
:title="t('entryStockBought.editTravel')"
|
||||||
color="primary"
|
color="primary"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -226,7 +226,7 @@ function round(value) {
|
||||||
@on-fetch="(data) => setFooter(data)"
|
@on-fetch="(data) => setFooter(data)"
|
||||||
:create="{
|
:create="{
|
||||||
urlCreate: 'StockBoughts',
|
urlCreate: 'StockBoughts',
|
||||||
title: t('Reserve some space'),
|
title: t('entryStockBought.reserveSomeSpace'),
|
||||||
onDataSaved: () => tableRef.reload(),
|
onDataSaved: () => tableRef.reload(),
|
||||||
formInitialData: {
|
formInitialData: {
|
||||||
workerFk: user.id,
|
workerFk: user.id,
|
||||||
|
@ -288,16 +288,3 @@ function round(value) {
|
||||||
color: $negative !important;
|
color: $negative !important;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<i18n>
|
|
||||||
es:
|
|
||||||
Edit travel: Editar envío
|
|
||||||
Travel: Envíos
|
|
||||||
Purchase Spaces: Espacios de compra
|
|
||||||
Buyer: Comprador
|
|
||||||
Reserve: Reservado
|
|
||||||
Bought: Comprado
|
|
||||||
Date: Fecha
|
|
||||||
View more details: Ver más detalles
|
|
||||||
Reserve some space: Reservar espacio
|
|
||||||
This buyer has already made a reservation for this date: Este comprador ya ha hecho una reserva para esta fecha
|
|
||||||
</i18n>
|
|
||||||
|
|
|
@ -123,8 +123,8 @@ const printBuys = (rowId) => {
|
||||||
<VnSearchbar
|
<VnSearchbar
|
||||||
data-key="myEntriesList"
|
data-key="myEntriesList"
|
||||||
url="Entries/filter"
|
url="Entries/filter"
|
||||||
:label="t('Search entries')"
|
:label="t('myEntries.search')"
|
||||||
:info="t('You can search by entry reference')"
|
:info="t('myEntries.searchInfo')"
|
||||||
/>
|
/>
|
||||||
<VnTable
|
<VnTable
|
||||||
data-key="myEntriesList"
|
data-key="myEntriesList"
|
||||||
|
@ -137,7 +137,3 @@ const printBuys = (rowId) => {
|
||||||
chip-locale="myEntries"
|
chip-locale="myEntries"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<i18n>
|
|
||||||
You can search by entry reference: Puedes buscar por referencia de la entrada
|
|
||||||
</i18n>
|
|
||||||
|
|
|
@ -1,8 +1,92 @@
|
||||||
entryList:
|
entry:
|
||||||
list:
|
list:
|
||||||
|
newEntry: New entry
|
||||||
|
tableVisibleColumns:
|
||||||
|
created: Creation
|
||||||
|
supplierFk: Supplier
|
||||||
|
isBooked: Booked
|
||||||
|
isConfirmed: Confirmed
|
||||||
|
isOrdered: Ordered
|
||||||
|
companyFk: Company
|
||||||
|
travelFk: Travel
|
||||||
|
isExcludedFromAvailable: Inventory
|
||||||
|
invoiceAmount: Import
|
||||||
inventoryEntry: Inventory entry
|
inventoryEntry: Inventory entry
|
||||||
|
summary:
|
||||||
|
commission: Commission
|
||||||
|
currency: Currency
|
||||||
|
invoiceNumber: Invoice number
|
||||||
|
ordered: Ordered
|
||||||
|
booked: Booked
|
||||||
|
excludedFromAvailable: Inventory
|
||||||
|
travelReference: Reference
|
||||||
|
travelAgency: Agency
|
||||||
|
travelShipped: Shipped
|
||||||
|
travelDelivered: Delivered
|
||||||
|
travelLanded: Landed
|
||||||
|
travelReceived: Received
|
||||||
|
buys: Buys
|
||||||
|
stickers: Stickers
|
||||||
|
package: Package
|
||||||
|
packing: Pack.
|
||||||
|
grouping: Group.
|
||||||
|
buyingValue: Buying value
|
||||||
|
import: Import
|
||||||
|
pvp: PVP
|
||||||
|
basicData:
|
||||||
|
travel: Travel
|
||||||
|
currency: Currency
|
||||||
|
commission: Commission
|
||||||
|
observation: Observation
|
||||||
|
booked: Booked
|
||||||
|
excludedFromAvailable: Inventory
|
||||||
|
buys:
|
||||||
|
observations: Observations
|
||||||
|
packagingFk: Box
|
||||||
|
color: Color
|
||||||
|
printedStickers: Printed stickers
|
||||||
|
notes:
|
||||||
|
observationType: Observation type
|
||||||
|
latestBuys:
|
||||||
|
tableVisibleColumns:
|
||||||
|
image: Picture
|
||||||
|
itemFk: Item ID
|
||||||
|
weightByPiece: Weight/Piece
|
||||||
|
isActive: Active
|
||||||
|
family: Family
|
||||||
|
entryFk: Entry
|
||||||
|
freightValue: Freight value
|
||||||
|
comissionValue: Commission value
|
||||||
|
packageValue: Package value
|
||||||
|
isIgnored: Is ignored
|
||||||
|
price2: Grouping
|
||||||
|
price3: Packing
|
||||||
|
minPrice: Min
|
||||||
|
ektFk: Ekt
|
||||||
|
packingOut: Package out
|
||||||
|
landing: Landing
|
||||||
|
isExcludedFromAvailable: Es inventory
|
||||||
|
params:
|
||||||
|
toShipped: To
|
||||||
|
fromShipped: From
|
||||||
|
daysOnward: Days onward
|
||||||
|
daysAgo: Days ago
|
||||||
|
warehouseInFk: Warehouse in
|
||||||
|
search: Search entries
|
||||||
|
searchInfo: You can search by entry reference
|
||||||
entryFilter:
|
entryFilter:
|
||||||
filter:
|
params:
|
||||||
|
invoiceNumber: Invoice number
|
||||||
|
travelFk: Travel
|
||||||
|
companyFk: Company
|
||||||
|
currencyFk: Currency
|
||||||
|
supplierFk: Supplier
|
||||||
|
from: From
|
||||||
|
to: To
|
||||||
|
created: Created
|
||||||
|
isBooked: Booked
|
||||||
|
isConfirmed: Confirmed
|
||||||
|
isOrdered: Ordered
|
||||||
search: General search
|
search: General search
|
||||||
reference: Reference
|
reference: Reference
|
||||||
myEntries:
|
myEntries:
|
||||||
|
@ -18,5 +102,18 @@ myEntries:
|
||||||
daysOnward: Days onward
|
daysOnward: Days onward
|
||||||
daysAgo: Days ago
|
daysAgo: Days ago
|
||||||
downloadCsv: Download CSV
|
downloadCsv: Download CSV
|
||||||
|
search: Search entries
|
||||||
|
searchInfo: You can search by entry reference
|
||||||
|
entryStockBought:
|
||||||
|
travel: Travel
|
||||||
|
editTravel: Edit travel
|
||||||
|
purchaseSpaces: Purchase spaces
|
||||||
|
buyer: Buyer
|
||||||
|
reserve: Reserve
|
||||||
|
bought: Bought
|
||||||
|
date: Date
|
||||||
|
viewMoreDetails: View more details
|
||||||
|
reserveSomeSpace: Reserve some space
|
||||||
|
thisBuyerHasReservationThisDate: This buyer has already made a reservation for this date
|
||||||
wasteRecalc:
|
wasteRecalc:
|
||||||
recalcOk: The wastes were successfully recalculated
|
recalcOk: The wastes were successfully recalculated
|
||||||
|
|
|
@ -1,11 +1,93 @@
|
||||||
Search entries: Buscar entradas
|
entry:
|
||||||
You can search by entry reference: Puedes buscar por referencia de la entrada
|
|
||||||
|
|
||||||
entryList:
|
|
||||||
list:
|
list:
|
||||||
|
newEntry: Nueva entrada
|
||||||
|
tableVisibleColumns:
|
||||||
|
created: Creación
|
||||||
|
supplierFk: Proveedor
|
||||||
|
isBooked: Asentado
|
||||||
|
isConfirmed: Confirmado
|
||||||
|
isOrdered: Pedida
|
||||||
|
companyFk: Empresa
|
||||||
|
travelFk: Envio
|
||||||
|
isExcludedFromAvailable: Inventario
|
||||||
|
invoiceAmount: Importe
|
||||||
inventoryEntry: Es inventario
|
inventoryEntry: Es inventario
|
||||||
|
summary:
|
||||||
|
commission: Comisión
|
||||||
|
currency: Moneda
|
||||||
|
invoiceNumber: Núm. factura
|
||||||
|
ordered: Pedida
|
||||||
|
booked: Contabilizada
|
||||||
|
excludedFromAvailable: Inventario
|
||||||
|
travelReference: Referencia
|
||||||
|
travelAgency: Agencia
|
||||||
|
travelShipped: F. envio
|
||||||
|
travelWarehouseOut: Alm. salida
|
||||||
|
travelDelivered: Enviada
|
||||||
|
travelLanded: F. entrega
|
||||||
|
travelReceived: Recibida
|
||||||
|
buys: Compras
|
||||||
|
stickers: Etiquetas
|
||||||
|
package: Embalaje
|
||||||
|
packing: Pack.
|
||||||
|
grouping: Group.
|
||||||
|
buyingValue: Coste
|
||||||
|
import: Importe
|
||||||
|
pvp: PVP
|
||||||
|
basicData:
|
||||||
|
travel: Envío
|
||||||
|
currency: Moneda
|
||||||
|
observation: Observación
|
||||||
|
commission: Comisión
|
||||||
|
booked: Asentado
|
||||||
|
excludedFromAvailable: Inventario
|
||||||
|
buys:
|
||||||
|
observations: Observaciónes
|
||||||
|
packagingFk: Embalaje
|
||||||
|
color: Color
|
||||||
|
printedStickers: Etiquetas impresas
|
||||||
|
notes:
|
||||||
|
observationType: Tipo de observación
|
||||||
|
latestBuys:
|
||||||
|
tableVisibleColumns:
|
||||||
|
image: Foto
|
||||||
|
itemFk: Id Artículo
|
||||||
|
weightByPiece: Peso (gramos)/tallo
|
||||||
|
isActive: Activo
|
||||||
|
family: Familia
|
||||||
|
entryFk: Entrada
|
||||||
|
freightValue: Porte
|
||||||
|
comissionValue: Comisión
|
||||||
|
packageValue: Embalaje
|
||||||
|
isIgnored: Ignorado
|
||||||
|
price2: Grouping
|
||||||
|
price3: Packing
|
||||||
|
minPrice: Min
|
||||||
|
ektFk: Ekt
|
||||||
|
packingOut: Embalaje envíos
|
||||||
|
landing: Llegada
|
||||||
|
isExcludedFromAvailable: Es inventario
|
||||||
|
params:
|
||||||
|
toShipped: Hasta
|
||||||
|
fromShipped: Desde
|
||||||
|
warehouseInFk: Alm. entrada
|
||||||
|
daysOnward: Días adelante
|
||||||
|
daysAgo: Días atras
|
||||||
|
search: Buscar entradas
|
||||||
|
searchInfo: Puedes buscar por referencia de entrada
|
||||||
entryFilter:
|
entryFilter:
|
||||||
filter:
|
params:
|
||||||
|
invoiceNumber: Núm. factura
|
||||||
|
travelFk: Envío
|
||||||
|
companyFk: Empresa
|
||||||
|
currencyFk: Moneda
|
||||||
|
supplierFk: Proveedor
|
||||||
|
from: Desde
|
||||||
|
to: Hasta
|
||||||
|
created: Fecha creación
|
||||||
|
isBooked: Asentado
|
||||||
|
isConfirmed: Confirmado
|
||||||
|
isOrdered: Pedida
|
||||||
search: Búsqueda general
|
search: Búsqueda general
|
||||||
reference: Referencia
|
reference: Referencia
|
||||||
myEntries:
|
myEntries:
|
||||||
|
@ -21,5 +103,18 @@ myEntries:
|
||||||
daysOnward: Días adelante
|
daysOnward: Días adelante
|
||||||
daysAgo: Días atras
|
daysAgo: Días atras
|
||||||
downloadCsv: Descargar CSV
|
downloadCsv: Descargar CSV
|
||||||
|
search: Buscar entradas
|
||||||
|
searchInfo: Puedes buscar por referencia de la entrada
|
||||||
|
entryStockBought:
|
||||||
|
travel: Envío
|
||||||
|
editTravel: Editar envío
|
||||||
|
purchaseSpaces: Espacios de compra
|
||||||
|
buyer: Comprador
|
||||||
|
reserve: Reservado
|
||||||
|
bought: Comprado
|
||||||
|
date: Fecha
|
||||||
|
viewMoreDetails: Ver más detalles
|
||||||
|
reserveSomeSpace: Reservar espacio
|
||||||
|
thisBuyerHasReservationThisDate: Este comprador ya ha hecho una reserva para esta fecha
|
||||||
wasteRecalc:
|
wasteRecalc:
|
||||||
recalcOk: Se han recalculado las mermas correctamente
|
recalcOk: Se han recalculado las mermas correctamente
|
||||||
|
|
|
@ -268,7 +268,7 @@ function deleteFile(dmsFk) {
|
||||||
</VnRow>
|
</VnRow>
|
||||||
<VnRow>
|
<VnRow>
|
||||||
<VnSelect
|
<VnSelect
|
||||||
:label="t('InvoiceIn.summary.sage')"
|
:label="t('invoicein.summary.sage')"
|
||||||
v-model="data.withholdingSageFk"
|
v-model="data.withholdingSageFk"
|
||||||
:options="sageWithholdings"
|
:options="sageWithholdings"
|
||||||
option-value="id"
|
option-value="id"
|
||||||
|
|
|
@ -1,60 +1,30 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, reactive, computed, onBeforeMount, capitalize } from 'vue';
|
import { ref, reactive, computed, onBeforeMount } from 'vue';
|
||||||
import { useRouter, onBeforeRouteUpdate } from 'vue-router';
|
import { useRouter, onBeforeRouteUpdate } from 'vue-router';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useQuasar } from 'quasar';
|
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { toCurrency, toDate } from 'src/filters';
|
import { toCurrency, toDate } from 'src/filters';
|
||||||
import { useAcl } from 'src/composables/useAcl';
|
|
||||||
import { downloadFile } from 'src/composables/downloadFile';
|
|
||||||
import { useArrayData } from 'src/composables/useArrayData';
|
|
||||||
import { usePrintService } from 'composables/usePrintService';
|
|
||||||
import VnLv from 'src/components/ui/VnLv.vue';
|
import VnLv from 'src/components/ui/VnLv.vue';
|
||||||
import CardDescriptor from 'components/ui/CardDescriptor.vue';
|
import CardDescriptor from 'components/ui/CardDescriptor.vue';
|
||||||
import FetchData from 'src/components/FetchData.vue';
|
import FetchData from 'src/components/FetchData.vue';
|
||||||
import SendEmailDialog from 'components/common/SendEmailDialog.vue';
|
|
||||||
import VnConfirm from 'src/components/ui/VnConfirm.vue';
|
|
||||||
import VnSelect from 'src/components/common/VnSelect.vue';
|
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||||
|
import { useCapitalize } from 'src/composables/useCapitalize';
|
||||||
import SupplierDescriptorProxy from 'src/pages/Supplier/Card/SupplierDescriptorProxy.vue';
|
import SupplierDescriptorProxy from 'src/pages/Supplier/Card/SupplierDescriptorProxy.vue';
|
||||||
import InvoiceInToBook from '../InvoiceInToBook.vue';
|
import InvoiceInDescriptorMenu from './InvoiceInDescriptorMenu.vue';
|
||||||
|
|
||||||
const $props = defineProps({ id: { type: Number, default: null } });
|
const $props = defineProps({ id: { type: Number, default: null } });
|
||||||
|
|
||||||
const { push, currentRoute } = useRouter();
|
const { push, currentRoute } = useRouter();
|
||||||
|
|
||||||
const quasar = useQuasar();
|
|
||||||
const { hasAny } = useAcl();
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { openReport, sendEmail } = usePrintService();
|
|
||||||
const arrayData = useArrayData();
|
|
||||||
|
|
||||||
const invoiceIn = computed(() => arrayData.store.data);
|
|
||||||
const cardDescriptorRef = ref();
|
const cardDescriptorRef = ref();
|
||||||
const correctionDialogRef = ref();
|
const correctionDialogRef = ref();
|
||||||
const entityId = computed(() => $props.id || +currentRoute.value.params.id);
|
const entityId = computed(() => $props.id || +currentRoute.value.params.id);
|
||||||
const totalAmount = ref();
|
const totalAmount = ref();
|
||||||
const currentAction = ref();
|
|
||||||
const config = ref();
|
const config = ref();
|
||||||
const cplusRectificationTypes = ref([]);
|
const cplusRectificationTypes = ref([]);
|
||||||
const siiTypeInvoiceIns = ref([]);
|
const siiTypeInvoiceIns = ref([]);
|
||||||
const invoiceCorrectionTypes = ref([]);
|
const invoiceCorrectionTypes = ref([]);
|
||||||
const actions = {
|
|
||||||
unbook: {
|
|
||||||
title: t('assertAction', { action: t('unbook') }),
|
|
||||||
action: toUnbook,
|
|
||||||
},
|
|
||||||
delete: {
|
|
||||||
title: t('assertAction', { action: t('delete') }),
|
|
||||||
action: deleteInvoice,
|
|
||||||
},
|
|
||||||
clone: {
|
|
||||||
title: t('assertAction', { action: t('clone') }),
|
|
||||||
action: cloneInvoice,
|
|
||||||
},
|
|
||||||
showPdf: { cb: showPdfInvoice },
|
|
||||||
sendPdf: { cb: sendPdfInvoiceConfirmation },
|
|
||||||
correct: { cb: () => correctionDialogRef.value.show() },
|
|
||||||
};
|
|
||||||
const filter = {
|
const filter = {
|
||||||
include: [
|
include: [
|
||||||
{
|
{
|
||||||
|
@ -90,7 +60,7 @@ const routes = reactive({
|
||||||
return {
|
return {
|
||||||
name: 'InvoiceInList',
|
name: 'InvoiceInList',
|
||||||
query: {
|
query: {
|
||||||
table: JSON.stringify({ supplierFk: id }),
|
params: JSON.stringify({ supplierFk: id }),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
@ -99,7 +69,7 @@ const routes = reactive({
|
||||||
return {
|
return {
|
||||||
name: 'InvoiceInList',
|
name: 'InvoiceInList',
|
||||||
query: {
|
query: {
|
||||||
table: JSON.stringify({ correctedFk: entityId.value }),
|
params: JSON.stringify({ correctedFk: entityId.value }),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -118,21 +88,21 @@ const routes = reactive({
|
||||||
const correctionFormData = reactive({
|
const correctionFormData = reactive({
|
||||||
invoiceReason: 2,
|
invoiceReason: 2,
|
||||||
invoiceType: 2,
|
invoiceType: 2,
|
||||||
invoiceClass: 8,
|
invoiceClass: 6,
|
||||||
});
|
});
|
||||||
const isNotFilled = computed(() => Object.values(correctionFormData).includes(null));
|
const isNotFilled = computed(() => Object.values(correctionFormData).includes(null));
|
||||||
|
|
||||||
onBeforeMount(async () => {
|
onBeforeMount(async () => {
|
||||||
await setInvoiceCorrection(entityId.value);
|
await setInvoiceCorrection(entityId.value);
|
||||||
const { data } = await axios.get(`InvoiceIns/${entityId.value}/getTotals`);
|
const { data } = await axios.get(`InvoiceIns/${entityId.value}/getTotals`);
|
||||||
totalAmount.value = data.totalTaxableBase;
|
totalAmount.value = data.totalDueDay;
|
||||||
});
|
});
|
||||||
|
|
||||||
onBeforeRouteUpdate(async (to, from) => {
|
onBeforeRouteUpdate(async (to, from) => {
|
||||||
if (to.params.id !== from.params.id) {
|
if (to.params.id !== from.params.id) {
|
||||||
await setInvoiceCorrection(to.params.id);
|
await setInvoiceCorrection(to.params.id);
|
||||||
const { data } = await axios.get(`InvoiceIns/${to.params.id}/getTotals`);
|
const { data } = await axios.get(`InvoiceIns/${to.params.id}/getTotals`);
|
||||||
totalAmount.value = data.totalTaxableBase;
|
totalAmount.value = data.totalDueDay;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -153,94 +123,6 @@ async function setInvoiceCorrection(id) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function openDialog() {
|
|
||||||
quasar.dialog({
|
|
||||||
component: VnConfirm,
|
|
||||||
componentProps: {
|
|
||||||
title: t(currentAction.value.title),
|
|
||||||
promise: currentAction.value.action,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function toUnbook() {
|
|
||||||
const { data } = await axios.post(`InvoiceIns/${entityId.value}/toUnbook`);
|
|
||||||
const { isLinked, bookEntry, accountingEntries } = data;
|
|
||||||
|
|
||||||
const type = isLinked ? 'warning' : 'positive';
|
|
||||||
const message = isLinked
|
|
||||||
? t('isLinked', { bookEntry, accountingEntries })
|
|
||||||
: t('isNotLinked', { bookEntry });
|
|
||||||
|
|
||||||
quasar.notify({ type, message });
|
|
||||||
if (!isLinked) arrayData.store.data.isBooked = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function deleteInvoice() {
|
|
||||||
await axios.delete(`InvoiceIns/${entityId.value}`);
|
|
||||||
quasar.notify({
|
|
||||||
type: 'positive',
|
|
||||||
message: t('Invoice deleted'),
|
|
||||||
});
|
|
||||||
push({ path: '/invoice-in' });
|
|
||||||
}
|
|
||||||
|
|
||||||
async function cloneInvoice() {
|
|
||||||
const { data } = await axios.post(`InvoiceIns/${entityId.value}/clone`);
|
|
||||||
quasar.notify({
|
|
||||||
type: 'positive',
|
|
||||||
message: t('Invoice cloned'),
|
|
||||||
});
|
|
||||||
push({ path: `/invoice-in/${data.id}/summary` });
|
|
||||||
}
|
|
||||||
|
|
||||||
const canEditProp = (props) =>
|
|
||||||
hasAny([{ model: 'InvoiceIn', props, accessType: 'WRITE' }]);
|
|
||||||
|
|
||||||
const isAgricultural = () => {
|
|
||||||
if (!config.value) return false;
|
|
||||||
return (
|
|
||||||
invoiceIn.value?.supplier?.sageFarmerWithholdingFk ===
|
|
||||||
config?.value[0]?.sageWithholdingFk
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
function showPdfInvoice() {
|
|
||||||
if (isAgricultural())
|
|
||||||
openReport(`InvoiceIns/${entityId.value}/invoice-in-pdf`, null, '_blank');
|
|
||||||
}
|
|
||||||
|
|
||||||
function sendPdfInvoiceConfirmation() {
|
|
||||||
quasar.dialog({
|
|
||||||
component: SendEmailDialog,
|
|
||||||
componentProps: {
|
|
||||||
data: {
|
|
||||||
address: invoiceIn.value.supplier.contacts[0].email,
|
|
||||||
},
|
|
||||||
promise: sendPdfInvoice,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function sendPdfInvoice({ address }) {
|
|
||||||
if (!address)
|
|
||||||
quasar.notify({
|
|
||||||
type: 'negative',
|
|
||||||
message: t(`The email can't be empty`),
|
|
||||||
});
|
|
||||||
else
|
|
||||||
return sendEmail(`InvoiceIns/${entityId.value}/invoice-in-email`, {
|
|
||||||
recipientId: invoiceIn.value.supplier.id,
|
|
||||||
recipient: address,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function triggerMenu(type) {
|
|
||||||
currentAction.value = actions[type];
|
|
||||||
if (currentAction.value.cb) currentAction.value.cb();
|
|
||||||
else openDialog(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
const createInvoiceInCorrection = async () => {
|
const createInvoiceInCorrection = async () => {
|
||||||
const { data: correctingId } = await axios.post(
|
const { data: correctingId } = await axios.post(
|
||||||
'InvoiceIns/corrective',
|
'InvoiceIns/corrective',
|
||||||
|
@ -262,7 +144,7 @@ const createInvoiceInCorrection = async () => {
|
||||||
auto-load
|
auto-load
|
||||||
/>
|
/>
|
||||||
<FetchData
|
<FetchData
|
||||||
url="siiTypeInvoiceIns"
|
url="SiiTypeInvoiceIns"
|
||||||
:where="{ code: { like: 'R%' } }"
|
:where="{ code: { like: 'R%' } }"
|
||||||
@on-fetch="(data) => (siiTypeInvoiceIns = data)"
|
@on-fetch="(data) => (siiTypeInvoiceIns = data)"
|
||||||
auto-load
|
auto-load
|
||||||
|
@ -281,87 +163,13 @@ const createInvoiceInCorrection = async () => {
|
||||||
title="supplierRef"
|
title="supplierRef"
|
||||||
>
|
>
|
||||||
<template #menu="{ entity }">
|
<template #menu="{ entity }">
|
||||||
<InvoiceInToBook>
|
<InvoiceInDescriptorMenu :invoice="entity" />
|
||||||
<template #content="{ book }">
|
|
||||||
<QItem
|
|
||||||
v-if="!entity?.isBooked && canEditProp('toBook')"
|
|
||||||
v-ripple
|
|
||||||
clickable
|
|
||||||
@click="book(entityId)"
|
|
||||||
>
|
|
||||||
<QItemSection>{{ t('To book') }}</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
</template>
|
|
||||||
</InvoiceInToBook>
|
|
||||||
<QItem
|
|
||||||
v-if="entity?.isBooked && canEditProp('toUnbook')"
|
|
||||||
v-ripple
|
|
||||||
clickable
|
|
||||||
@click="triggerMenu('unbook')"
|
|
||||||
>
|
|
||||||
<QItemSection>
|
|
||||||
{{ t('To unbook') }}
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
<QItem
|
|
||||||
v-if="canEditProp('deleteById')"
|
|
||||||
v-ripple
|
|
||||||
clickable
|
|
||||||
@click="triggerMenu('delete')"
|
|
||||||
>
|
|
||||||
<QItemSection>{{ t('Delete invoice') }}</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
<QItem
|
|
||||||
v-if="canEditProp('clone')"
|
|
||||||
v-ripple
|
|
||||||
clickable
|
|
||||||
@click="triggerMenu('clone')"
|
|
||||||
>
|
|
||||||
<QItemSection>{{ t('Clone invoice') }}</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
<QItem
|
|
||||||
v-if="isAgricultural()"
|
|
||||||
v-ripple
|
|
||||||
clickable
|
|
||||||
@click="triggerMenu('showPdf')"
|
|
||||||
>
|
|
||||||
<QItemSection>{{ t('Show agricultural receipt as PDF') }}</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
<QItem
|
|
||||||
v-if="isAgricultural()"
|
|
||||||
v-ripple
|
|
||||||
clickable
|
|
||||||
@click="triggerMenu('sendPdf')"
|
|
||||||
>
|
|
||||||
<QItemSection
|
|
||||||
>{{ t('Send agricultural receipt as PDF') }}...</QItemSection
|
|
||||||
>
|
|
||||||
</QItem>
|
|
||||||
<QItem
|
|
||||||
v-if="!invoiceInCorrection.corrected"
|
|
||||||
v-ripple
|
|
||||||
clickable
|
|
||||||
@click="triggerMenu('correct')"
|
|
||||||
>
|
|
||||||
<QItemSection>{{ t('Create rectificative invoice') }}...</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
<QItem
|
|
||||||
v-if="entity.dmsFk"
|
|
||||||
v-ripple
|
|
||||||
clickable
|
|
||||||
@click="downloadFile(entity.dmsFk)"
|
|
||||||
>
|
|
||||||
<QItemSection>{{ t('components.smartCard.downloadFile') }}</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
</template>
|
</template>
|
||||||
<template #body="{ entity }">
|
<template #body="{ entity }">
|
||||||
<VnLv :label="t('InvoiceIn.list.issued')" :value="toDate(entity.issued)" />
|
<VnLv :label="t('invoicein.list.issued')" :value="toDate(entity.issued)" />
|
||||||
<VnLv
|
<VnLv :label="t('invoicein.summary.bookedDate')" :value="toDate(entity.booked)" />
|
||||||
:label="t('InvoiceIn.summary.bookedDate')"
|
<VnLv :label="t('invoicein.list.amount')" :value="toCurrency(totalAmount)" />
|
||||||
:value="toDate(entity.booked)"
|
<VnLv :label="t('invoicein.list.supplier')">
|
||||||
/>
|
|
||||||
<VnLv :label="t('InvoiceIn.list.amount')" :value="toCurrency(totalAmount)" />
|
|
||||||
<VnLv :label="t('InvoiceIn.list.supplier')">
|
|
||||||
<template #value>
|
<template #value>
|
||||||
<span class="link">
|
<span class="link">
|
||||||
{{ entity?.supplier?.nickname }}
|
{{ entity?.supplier?.nickname }}
|
||||||
|
@ -378,7 +186,7 @@ const createInvoiceInCorrection = async () => {
|
||||||
color="primary"
|
color="primary"
|
||||||
:to="routes.getSupplier(entity.supplierFk)"
|
:to="routes.getSupplier(entity.supplierFk)"
|
||||||
>
|
>
|
||||||
<QTooltip>{{ t('InvoiceIn.list.supplier') }}</QTooltip>
|
<QTooltip>{{ t('invoicein.list.supplier') }}</QTooltip>
|
||||||
</QBtn>
|
</QBtn>
|
||||||
<QBtn
|
<QBtn
|
||||||
size="md"
|
size="md"
|
||||||
|
@ -394,7 +202,7 @@ const createInvoiceInCorrection = async () => {
|
||||||
color="primary"
|
color="primary"
|
||||||
:to="routes.getTickets(entity.supplierFk)"
|
:to="routes.getTickets(entity.supplierFk)"
|
||||||
>
|
>
|
||||||
<QTooltip>{{ t('InvoiceIn.descriptor.ticketList') }}</QTooltip>
|
<QTooltip>{{ t('InvoiceOut.card.ticketList') }}</QTooltip>
|
||||||
</QBtn>
|
</QBtn>
|
||||||
<QBtn
|
<QBtn
|
||||||
v-if="
|
v-if="
|
||||||
|
@ -438,7 +246,7 @@ const createInvoiceInCorrection = async () => {
|
||||||
readonly
|
readonly
|
||||||
/>
|
/>
|
||||||
<VnSelect
|
<VnSelect
|
||||||
:label="`${capitalize(t('globals.class'))}`"
|
:label="`${useCapitalize(t('globals.class'))}`"
|
||||||
v-model="correctionFormData.invoiceClass"
|
v-model="correctionFormData.invoiceClass"
|
||||||
:options="siiTypeInvoiceIns"
|
:options="siiTypeInvoiceIns"
|
||||||
option-value="id"
|
option-value="id"
|
||||||
|
@ -448,27 +256,15 @@ const createInvoiceInCorrection = async () => {
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<VnSelect
|
<VnSelect
|
||||||
:label="`${capitalize(t('globals.type'))}`"
|
:label="`${useCapitalize(t('globals.type'))}`"
|
||||||
v-model="correctionFormData.invoiceType"
|
v-model="correctionFormData.invoiceType"
|
||||||
:options="cplusRectificationTypes"
|
:options="cplusRectificationTypes"
|
||||||
option-value="id"
|
option-value="id"
|
||||||
option-label="description"
|
option-label="description"
|
||||||
:required="true"
|
:required="true"
|
||||||
>
|
/>
|
||||||
<template #option="{ opt }">
|
|
||||||
<QItem>
|
|
||||||
<QItemSection>
|
|
||||||
<QItemLabel
|
|
||||||
>{{ opt.code }} -
|
|
||||||
{{ opt.description }}</QItemLabel
|
|
||||||
>
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
<div></div>
|
|
||||||
</template>
|
|
||||||
</VnSelect>
|
|
||||||
<VnSelect
|
<VnSelect
|
||||||
:label="`${capitalize(t('globals.reason'))}`"
|
:label="`${useCapitalize(t('globals.reason'))}`"
|
||||||
v-model="correctionFormData.invoiceReason"
|
v-model="correctionFormData.invoiceReason"
|
||||||
:options="invoiceCorrectionTypes"
|
:options="invoiceCorrectionTypes"
|
||||||
option-value="id"
|
option-value="id"
|
||||||
|
@ -512,31 +308,3 @@ const createInvoiceInCorrection = async () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<i18n>
|
|
||||||
en:
|
|
||||||
isNotLinked: The entry {bookEntry} has been deleted with {accountingEntries} entries
|
|
||||||
isLinked: The entry {bookEntry} has been linked to Sage. Please contact administration for further information
|
|
||||||
assertAction: Are you sure you want to {action} this invoice?
|
|
||||||
es:
|
|
||||||
book: asentar
|
|
||||||
unbook: desasentar
|
|
||||||
delete: eliminar
|
|
||||||
clone: clonar
|
|
||||||
To book: Contabilizar
|
|
||||||
To unbook: Descontabilizar
|
|
||||||
Delete invoice: Eliminar factura
|
|
||||||
Invoice deleted: Factura eliminada
|
|
||||||
Clone invoice: Clonar factura
|
|
||||||
Invoice cloned: Factura clonada
|
|
||||||
Show agricultural receipt as PDF: Ver recibo agrícola como PDF
|
|
||||||
Send agricultural receipt as PDF: Enviar recibo agrícola como PDF
|
|
||||||
Are you sure you want to send it?: Estás seguro que quieres enviarlo?
|
|
||||||
Send PDF invoice: Enviar factura a PDF
|
|
||||||
Create rectificative invoice: Crear factura rectificativa
|
|
||||||
Rectificative invoice: Factura rectificativa
|
|
||||||
Original invoice: Factura origen
|
|
||||||
Entry: entrada
|
|
||||||
isNotLinked: Se ha eliminado el asiento nº {bookEntry} con {accountingEntries} apuntes
|
|
||||||
isLinked: El asiento {bookEntry} fue enlazado a Sage, por favor contacta con administración
|
|
||||||
assertAction: Estas seguro de querer {action} esta factura?
|
|
||||||
</i18n>
|
|
||||||
|
|
|
@ -0,0 +1,206 @@
|
||||||
|
<script setup>
|
||||||
|
import { ref, computed, toRefs, reactive } from 'vue';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { useQuasar } from 'quasar';
|
||||||
|
import axios from 'axios';
|
||||||
|
import { useAcl } from 'src/composables/useAcl';
|
||||||
|
import { downloadFile } from 'src/composables/downloadFile';
|
||||||
|
import { useArrayData } from 'src/composables/useArrayData';
|
||||||
|
import { usePrintService } from 'composables/usePrintService';
|
||||||
|
import VnConfirm from 'src/components/ui/VnConfirm.vue';
|
||||||
|
import SendEmailDialog from 'components/common/SendEmailDialog.vue';
|
||||||
|
import InvoiceInToBook from '../InvoiceInToBook.vue';
|
||||||
|
|
||||||
|
const { hasAny } = useAcl();
|
||||||
|
const { t } = useI18n();
|
||||||
|
const { openReport, sendEmail } = usePrintService();
|
||||||
|
const { push, currentRoute } = useRouter();
|
||||||
|
const $props = defineProps({
|
||||||
|
invoice: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const { invoice } = toRefs($props);
|
||||||
|
const quasar = useQuasar();
|
||||||
|
const arrayData = useArrayData();
|
||||||
|
const currentAction = ref();
|
||||||
|
const config = ref();
|
||||||
|
const correctionDialogRef = ref();
|
||||||
|
const invoiceInCorrection = reactive({ correcting: [], corrected: null });
|
||||||
|
const entityId = computed(() => $props.invoice.id || +currentRoute.value.params.id);
|
||||||
|
const invoiceIn = computed(() => arrayData.store.data);
|
||||||
|
const actions = {
|
||||||
|
unbook: {
|
||||||
|
title: t('assertAction', { action: t('invoicein.descriptorMenu.unbook') }),
|
||||||
|
action: toUnbook,
|
||||||
|
},
|
||||||
|
delete: {
|
||||||
|
title: t('assertAction', { action: t('invoicein.descriptorMenu.delete') }),
|
||||||
|
action: deleteInvoice,
|
||||||
|
},
|
||||||
|
clone: {
|
||||||
|
title: t('assertAction', { action: t('invoicein.descriptorMenu.clone') }),
|
||||||
|
action: cloneInvoice,
|
||||||
|
},
|
||||||
|
showPdf: { cb: showPdfInvoice },
|
||||||
|
sendPdf: { cb: sendPdfInvoiceConfirmation },
|
||||||
|
correct: { cb: () => correctionDialogRef.value.show() },
|
||||||
|
};
|
||||||
|
const canEditProp = (props) =>
|
||||||
|
hasAny([{ model: 'InvoiceIn', props, accessType: 'WRITE' }]);
|
||||||
|
|
||||||
|
function triggerMenu(type) {
|
||||||
|
currentAction.value = actions[type];
|
||||||
|
if (currentAction.value.cb) currentAction.value.cb();
|
||||||
|
else openDialog(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
function openDialog() {
|
||||||
|
quasar.dialog({
|
||||||
|
component: VnConfirm,
|
||||||
|
componentProps: {
|
||||||
|
title: t(currentAction.value.title),
|
||||||
|
promise: currentAction.value.action,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function toUnbook() {
|
||||||
|
const { data } = await axios.post(`InvoiceIns/${entityId.value}/toUnbook`);
|
||||||
|
const { isLinked, bookEntry, accountingEntries } = data;
|
||||||
|
|
||||||
|
const type = isLinked ? 'warning' : 'positive';
|
||||||
|
const message = isLinked
|
||||||
|
? t('isLinked', { bookEntry })
|
||||||
|
: t('isNotLinked', { bookEntry, accountingEntries });
|
||||||
|
|
||||||
|
quasar.notify({ type, message });
|
||||||
|
if (!isLinked) arrayData.store.data.isBooked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function deleteInvoice() {
|
||||||
|
await axios.delete(`InvoiceIns/${entityId.value}`);
|
||||||
|
quasar.notify({
|
||||||
|
type: 'positive',
|
||||||
|
message: t('invoicein.descriptorMenu.invoiceDeleted'),
|
||||||
|
});
|
||||||
|
push({ path: '/invoice-in' });
|
||||||
|
}
|
||||||
|
|
||||||
|
async function cloneInvoice() {
|
||||||
|
const { data } = await axios.post(`InvoiceIns/${entityId.value}/clone`);
|
||||||
|
quasar.notify({
|
||||||
|
type: 'positive',
|
||||||
|
message: t('invoicein.descriptorMenu.invoiceCloned'),
|
||||||
|
});
|
||||||
|
push({ path: `/invoice-in/${data.id}/summary` });
|
||||||
|
}
|
||||||
|
|
||||||
|
const isAgricultural = () => {
|
||||||
|
if (!config.value) return false;
|
||||||
|
return (
|
||||||
|
invoiceIn.value?.supplier?.sageFarmerWithholdingFk ===
|
||||||
|
config?.value[0]?.sageWithholdingFk
|
||||||
|
);
|
||||||
|
};
|
||||||
|
function showPdfInvoice() {
|
||||||
|
if (isAgricultural()) openReport(`InvoiceIns/${entityId.value}/invoice-in-pdf`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendPdfInvoiceConfirmation() {
|
||||||
|
quasar.dialog({
|
||||||
|
component: SendEmailDialog,
|
||||||
|
componentProps: {
|
||||||
|
data: {
|
||||||
|
address: invoiceIn.value.supplier.contacts[0].email,
|
||||||
|
},
|
||||||
|
promise: sendPdfInvoice,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendPdfInvoice({ address }) {
|
||||||
|
if (!address)
|
||||||
|
quasar.notify({
|
||||||
|
type: 'negative',
|
||||||
|
message: t(`The email can't be empty`),
|
||||||
|
});
|
||||||
|
else
|
||||||
|
return sendEmail(`InvoiceIns/${entityId.value}/invoice-in-email`, {
|
||||||
|
recipientId: invoiceIn.value.supplier.id,
|
||||||
|
recipient: address,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<InvoiceInToBook>
|
||||||
|
<template #content="{ book }">
|
||||||
|
<QItem
|
||||||
|
v-if="!invoice?.isBooked && canEditProp('toBook')"
|
||||||
|
v-ripple
|
||||||
|
clickable
|
||||||
|
@click="book(entityId)"
|
||||||
|
>
|
||||||
|
<QItemSection>{{ t('invoicein.descriptorMenu.toBook') }}</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
</template>
|
||||||
|
</InvoiceInToBook>
|
||||||
|
<QItem
|
||||||
|
v-if="invoice?.isBooked && canEditProp('toUnbook')"
|
||||||
|
v-ripple
|
||||||
|
clickable
|
||||||
|
@click="triggerMenu('unbook')"
|
||||||
|
>
|
||||||
|
<QItemSection>
|
||||||
|
{{ t('invoicein.descriptorMenu.toUnbook') }}
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
<QItem
|
||||||
|
v-if="canEditProp('deleteById')"
|
||||||
|
v-ripple
|
||||||
|
clickable
|
||||||
|
@click="triggerMenu('invoicein.descriptorMenu.delete')"
|
||||||
|
>
|
||||||
|
<QItemSection>{{ t('invoicein.descriptorMenu.deleteInvoice') }}</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
<QItem v-if="canEditProp('clone')" v-ripple clickable @click="triggerMenu('clone')">
|
||||||
|
<QItemSection>{{ t('invoicein.descriptorMenu.cloneInvoice') }}</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
<QItem v-if="isAgricultural()" v-ripple clickable @click="triggerMenu('showPdf')">
|
||||||
|
<QItemSection>{{
|
||||||
|
t('invoicein.descriptorMenu.showAgriculturalPdf')
|
||||||
|
}}</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
<QItem v-if="isAgricultural()" v-ripple clickable @click="triggerMenu('sendPdf')">
|
||||||
|
<QItemSection
|
||||||
|
>{{ t('invoicein.descriptorMenu.sendAgriculturalPdf') }}...</QItemSection
|
||||||
|
>
|
||||||
|
</QItem>
|
||||||
|
<QItem
|
||||||
|
v-if="!invoiceInCorrection.corrected"
|
||||||
|
v-ripple
|
||||||
|
clickable
|
||||||
|
@click="triggerMenu('correct')"
|
||||||
|
>
|
||||||
|
<QItemSection
|
||||||
|
>{{ t('invoicein.descriptorMenu.createCorrective') }}...</QItemSection
|
||||||
|
>
|
||||||
|
</QItem>
|
||||||
|
<QItem v-if="invoice.dmsFk" v-ripple clickable @click="downloadFile(invoice.dmsFk)">
|
||||||
|
<QItemSection>{{ t('components.smartCard.downloadFile') }}</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<i18n>
|
||||||
|
en:
|
||||||
|
isNotLinked: The entry {bookEntry} has been deleted with {accountingEntries} entries
|
||||||
|
isLinked: The entry has been linked to Sage. Please contact administration for further information
|
||||||
|
assertAction: Are you sure you want to {action} this invoice?
|
||||||
|
es:
|
||||||
|
isNotLinked: Se ha eliminado el asiento nº {bookEntry} con {accountingEntries} apuntes
|
||||||
|
isLinked: El asiento fue enlazado a Sage, por favor contacta con administración
|
||||||
|
assertAction: Estas seguro de querer {action} esta factura?
|
||||||
|
</i18n>
|
|
@ -10,6 +10,7 @@ import VnLv from 'src/components/ui/VnLv.vue';
|
||||||
import SupplierDescriptorProxy from 'src/pages/Supplier/Card/SupplierDescriptorProxy.vue';
|
import SupplierDescriptorProxy from 'src/pages/Supplier/Card/SupplierDescriptorProxy.vue';
|
||||||
import InvoiceIntoBook from '../InvoiceInToBook.vue';
|
import InvoiceIntoBook from '../InvoiceInToBook.vue';
|
||||||
import VnTitle from 'src/components/common/VnTitle.vue';
|
import VnTitle from 'src/components/common/VnTitle.vue';
|
||||||
|
import InvoiceInDescriptorMenu from './InvoiceInDescriptorMenu.vue';
|
||||||
|
|
||||||
const props = defineProps({ id: { type: [Number, String], default: 0 } });
|
const props = defineProps({ id: { type: [Number, String], default: 0 } });
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
@ -26,14 +27,14 @@ const intrastatTotals = ref({ amount: 0, net: 0, stems: 0 });
|
||||||
const vatColumns = ref([
|
const vatColumns = ref([
|
||||||
{
|
{
|
||||||
name: 'expense',
|
name: 'expense',
|
||||||
label: 'InvoiceIn.summary.expense',
|
label: 'invoicein.summary.expense',
|
||||||
field: (row) => row.expenseFk,
|
field: (row) => row.expenseFk,
|
||||||
sortable: true,
|
sortable: true,
|
||||||
align: 'left',
|
align: 'left',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'landed',
|
name: 'landed',
|
||||||
label: 'InvoiceIn.summary.taxableBase',
|
label: 'invoicein.summary.taxableBase',
|
||||||
field: (row) => row.taxableBase,
|
field: (row) => row.taxableBase,
|
||||||
format: (value) => toCurrency(value),
|
format: (value) => toCurrency(value),
|
||||||
sortable: true,
|
sortable: true,
|
||||||
|
@ -41,7 +42,7 @@ const vatColumns = ref([
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'vat',
|
name: 'vat',
|
||||||
label: 'InvoiceIn.summary.sageVat',
|
label: 'invoicein.summary.sageVat',
|
||||||
field: (row) => {
|
field: (row) => {
|
||||||
if (row.taxTypeSage) return `#${row.taxTypeSage.id} : ${row.taxTypeSage.vat}`;
|
if (row.taxTypeSage) return `#${row.taxTypeSage.id} : ${row.taxTypeSage.vat}`;
|
||||||
},
|
},
|
||||||
|
@ -51,7 +52,7 @@ const vatColumns = ref([
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'transaction',
|
name: 'transaction',
|
||||||
label: 'InvoiceIn.summary.sageTransaction',
|
label: 'invoicein.summary.sageTransaction',
|
||||||
field: (row) => {
|
field: (row) => {
|
||||||
if (row.transactionTypeSage)
|
if (row.transactionTypeSage)
|
||||||
return `#${row.transactionTypeSage.id} : ${row.transactionTypeSage?.transaction}`;
|
return `#${row.transactionTypeSage.id} : ${row.transactionTypeSage?.transaction}`;
|
||||||
|
@ -62,7 +63,7 @@ const vatColumns = ref([
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'rate',
|
name: 'rate',
|
||||||
label: 'InvoiceIn.summary.rate',
|
label: 'invoicein.summary.rate',
|
||||||
field: (row) => taxRate(row.taxableBase, row.taxTypeSage?.rate),
|
field: (row) => taxRate(row.taxableBase, row.taxTypeSage?.rate),
|
||||||
format: (value) => toCurrency(value),
|
format: (value) => toCurrency(value),
|
||||||
sortable: true,
|
sortable: true,
|
||||||
|
@ -70,7 +71,7 @@ const vatColumns = ref([
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'currency',
|
name: 'currency',
|
||||||
label: 'InvoiceIn.summary.currency',
|
label: 'invoicein.summary.currency',
|
||||||
field: (row) => row.foreignValue,
|
field: (row) => row.foreignValue,
|
||||||
format: (val) => val && toCurrency(val, currency.value),
|
format: (val) => val && toCurrency(val, currency.value),
|
||||||
sortable: true,
|
sortable: true,
|
||||||
|
@ -81,21 +82,21 @@ const vatColumns = ref([
|
||||||
const dueDayColumns = ref([
|
const dueDayColumns = ref([
|
||||||
{
|
{
|
||||||
name: 'date',
|
name: 'date',
|
||||||
label: 'InvoiceIn.summary.dueDay',
|
label: 'invoicein.summary.dueDay',
|
||||||
field: (row) => toDate(row.dueDated),
|
field: (row) => toDate(row.dueDated),
|
||||||
sortable: true,
|
sortable: true,
|
||||||
align: 'left',
|
align: 'left',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'bank',
|
name: 'bank',
|
||||||
label: 'InvoiceIn.summary.bank',
|
label: 'invoicein.summary.bank',
|
||||||
field: (row) => row.bank.bank,
|
field: (row) => row.bank.bank,
|
||||||
sortable: true,
|
sortable: true,
|
||||||
align: 'left',
|
align: 'left',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'amount',
|
name: 'amount',
|
||||||
label: 'InvoiceIn.list.amount',
|
label: 'invoicein.list.amount',
|
||||||
field: (row) => row.amount,
|
field: (row) => row.amount,
|
||||||
format: (value) => toCurrency(value),
|
format: (value) => toCurrency(value),
|
||||||
sortable: true,
|
sortable: true,
|
||||||
|
@ -103,7 +104,7 @@ const dueDayColumns = ref([
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'landed',
|
name: 'landed',
|
||||||
label: 'InvoiceIn.summary.foreignValue',
|
label: 'invoicein.summary.foreignValue',
|
||||||
field: (row) => row.foreignValue,
|
field: (row) => row.foreignValue,
|
||||||
format: (val) => val && toCurrency(val, currency.value),
|
format: (val) => val && toCurrency(val, currency.value),
|
||||||
sortable: true,
|
sortable: true,
|
||||||
|
@ -114,7 +115,7 @@ const dueDayColumns = ref([
|
||||||
const intrastatColumns = ref([
|
const intrastatColumns = ref([
|
||||||
{
|
{
|
||||||
name: 'code',
|
name: 'code',
|
||||||
label: 'InvoiceIn.summary.code',
|
label: 'invoicein.summary.code',
|
||||||
field: (row) => {
|
field: (row) => {
|
||||||
return `${row.intrastat.id}: ${row.intrastat?.description}`;
|
return `${row.intrastat.id}: ${row.intrastat?.description}`;
|
||||||
},
|
},
|
||||||
|
@ -123,21 +124,21 @@ const intrastatColumns = ref([
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'amount',
|
name: 'amount',
|
||||||
label: 'InvoiceIn.list.amount',
|
label: 'invoicein.list.amount',
|
||||||
field: (row) => toCurrency(row.amount),
|
field: (row) => toCurrency(row.amount),
|
||||||
sortable: true,
|
sortable: true,
|
||||||
align: 'left',
|
align: 'left',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'net',
|
name: 'net',
|
||||||
label: 'InvoiceIn.summary.net',
|
label: 'invoicein.summary.net',
|
||||||
field: (row) => row.net,
|
field: (row) => row.net,
|
||||||
sortable: true,
|
sortable: true,
|
||||||
align: 'left',
|
align: 'left',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'stems',
|
name: 'stems',
|
||||||
label: 'InvoiceIn.summary.stems',
|
label: 'invoicein.summary.stems',
|
||||||
field: (row) => row.stems,
|
field: (row) => row.stems,
|
||||||
format: (value) => value,
|
format: (value) => value,
|
||||||
sortable: true,
|
sortable: true,
|
||||||
|
@ -145,7 +146,7 @@ const intrastatColumns = ref([
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'landed',
|
name: 'landed',
|
||||||
label: 'InvoiceIn.summary.country',
|
label: 'invoicein.summary.country',
|
||||||
field: (row) => row.country?.code,
|
field: (row) => row.country?.code,
|
||||||
format: (value) => value,
|
format: (value) => value,
|
||||||
sortable: true,
|
sortable: true,
|
||||||
|
@ -200,6 +201,9 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
|
||||||
</template>
|
</template>
|
||||||
</InvoiceIntoBook>
|
</InvoiceIntoBook>
|
||||||
</template>
|
</template>
|
||||||
|
<template #menu="{ entity }">
|
||||||
|
<InvoiceInDescriptorMenu :invoice="entity" />
|
||||||
|
</template>
|
||||||
<template #body="{ entity }">
|
<template #body="{ entity }">
|
||||||
<!--Basic Data-->
|
<!--Basic Data-->
|
||||||
<QCard class="vn-one">
|
<QCard class="vn-one">
|
||||||
|
@ -210,7 +214,7 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
|
||||||
/>
|
/>
|
||||||
</QCardSection>
|
</QCardSection>
|
||||||
<VnLv
|
<VnLv
|
||||||
:label="t('InvoiceIn.list.supplier')"
|
:label="t('invoicein.list.supplier')"
|
||||||
:value="entity.supplier?.name"
|
:value="entity.supplier?.name"
|
||||||
>
|
>
|
||||||
<template #value>
|
<template #value>
|
||||||
|
@ -221,14 +225,14 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
|
||||||
</template>
|
</template>
|
||||||
</VnLv>
|
</VnLv>
|
||||||
<VnLv
|
<VnLv
|
||||||
:label="t('InvoiceIn.list.supplierRef')"
|
:label="t('invoicein.list.supplierRef')"
|
||||||
:value="entity.supplierRef"
|
:value="entity.supplierRef"
|
||||||
/>
|
/>
|
||||||
<VnLv
|
<VnLv
|
||||||
:label="t('InvoiceIn.summary.currency')"
|
:label="t('invoicein.summary.currency')"
|
||||||
:value="entity.currency?.code"
|
:value="entity.currency?.code"
|
||||||
/>
|
/>
|
||||||
<VnLv :label="t('InvoiceIn.serial')" :value="`${entity.serial}`" />
|
<VnLv :label="t('invoicein.serial')" :value="`${entity.serial}`" />
|
||||||
<VnLv
|
<VnLv
|
||||||
:label="t('globals.country')"
|
:label="t('globals.country')"
|
||||||
:value="entity.supplier?.country?.code"
|
:value="entity.supplier?.country?.code"
|
||||||
|
@ -243,19 +247,19 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
|
||||||
</QCardSection>
|
</QCardSection>
|
||||||
<VnLv
|
<VnLv
|
||||||
:ellipsis-value="false"
|
:ellipsis-value="false"
|
||||||
:label="t('InvoiceIn.summary.issued')"
|
:label="t('invoicein.summary.issued')"
|
||||||
:value="toDate(entity.issued)"
|
:value="toDate(entity.issued)"
|
||||||
/>
|
/>
|
||||||
<VnLv
|
<VnLv
|
||||||
:label="t('InvoiceIn.summary.operated')"
|
:label="t('invoicein.summary.operated')"
|
||||||
:value="toDate(entity.operated)"
|
:value="toDate(entity.operated)"
|
||||||
/>
|
/>
|
||||||
<VnLv
|
<VnLv
|
||||||
:label="t('InvoiceIn.summary.bookEntried')"
|
:label="t('invoicein.summary.bookEntried')"
|
||||||
:value="toDate(entity.bookEntried)"
|
:value="toDate(entity.bookEntried)"
|
||||||
/>
|
/>
|
||||||
<VnLv
|
<VnLv
|
||||||
:label="t('InvoiceIn.summary.bookedDate')"
|
:label="t('invoicein.summary.bookedDate')"
|
||||||
:value="toDate(entity.booked)"
|
:value="toDate(entity.booked)"
|
||||||
/>
|
/>
|
||||||
<VnLv :label="t('globals.isVies')" :value="entity.supplier?.isVies" />
|
<VnLv :label="t('globals.isVies')" :value="entity.supplier?.isVies" />
|
||||||
|
@ -268,18 +272,18 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
|
||||||
/>
|
/>
|
||||||
</QCardSection>
|
</QCardSection>
|
||||||
<VnLv
|
<VnLv
|
||||||
:label="t('InvoiceIn.summary.sage')"
|
:label="t('invoicein.summary.sage')"
|
||||||
:value="entity.sageWithholding?.withholding"
|
:value="entity.sageWithholding?.withholding"
|
||||||
/>
|
/>
|
||||||
<VnLv
|
<VnLv
|
||||||
:label="t('InvoiceIn.summary.vat')"
|
:label="t('invoicein.summary.vat')"
|
||||||
:value="entity.expenseDeductible?.name"
|
:value="entity.expenseDeductible?.name"
|
||||||
/>
|
/>
|
||||||
<VnLv
|
<VnLv
|
||||||
:label="t('InvoiceIn.card.company')"
|
:label="t('invoicein.card.company')"
|
||||||
:value="entity.company?.code"
|
:value="entity.company?.code"
|
||||||
/>
|
/>
|
||||||
<VnLv :label="t('InvoiceIn.isBooked')" :value="invoiceIn?.isBooked" />
|
<VnLv :label="t('invoicein.isBooked')" :value="invoiceIn?.isBooked" />
|
||||||
</QCard>
|
</QCard>
|
||||||
<QCard class="vn-one">
|
<QCard class="vn-one">
|
||||||
<QCardSection class="q-pa-none">
|
<QCardSection class="q-pa-none">
|
||||||
|
@ -290,11 +294,11 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
|
||||||
</QCardSection>
|
</QCardSection>
|
||||||
<QCardSection class="q-pa-none">
|
<QCardSection class="q-pa-none">
|
||||||
<VnLv
|
<VnLv
|
||||||
:label="t('InvoiceIn.summary.taxableBase')"
|
:label="t('invoicein.summary.taxableBase')"
|
||||||
:value="toCurrency(entity.totals.totalTaxableBase)"
|
:value="toCurrency(entity.totals.totalTaxableBase)"
|
||||||
/>
|
/>
|
||||||
<VnLv label="Total" :value="toCurrency(entity.totals.totalVat)" />
|
<VnLv label="Total" :value="toCurrency(entity.totals.totalVat)" />
|
||||||
<VnLv :label="t('InvoiceIn.summary.dueTotal')">
|
<VnLv :label="t('invoicein.summary.dueTotal')">
|
||||||
<template #value>
|
<template #value>
|
||||||
<QChip
|
<QChip
|
||||||
dense
|
dense
|
||||||
|
@ -302,8 +306,8 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
|
||||||
:color="amountsNotMatch ? 'negative' : 'transparent'"
|
:color="amountsNotMatch ? 'negative' : 'transparent'"
|
||||||
:title="
|
:title="
|
||||||
amountsNotMatch
|
amountsNotMatch
|
||||||
? t('InvoiceIn.summary.noMatch')
|
? t('invoicein.summary.noMatch')
|
||||||
: t('InvoiceIn.summary.dueTotal')
|
: t('invoicein.summary.dueTotal')
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
{{ toCurrency(entity.totals.totalDueDay) }}
|
{{ toCurrency(entity.totals.totalDueDay) }}
|
||||||
|
@ -314,7 +318,7 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
|
||||||
</QCard>
|
</QCard>
|
||||||
<!--Vat-->
|
<!--Vat-->
|
||||||
<QCard v-if="entity.invoiceInTax.length" class="vat">
|
<QCard v-if="entity.invoiceInTax.length" class="vat">
|
||||||
<VnTitle :url="getLink('vat')" :text="t('InvoiceIn.card.vat')" />
|
<VnTitle :url="getLink('vat')" :text="t('invoicein.card.vat')" />
|
||||||
<QTable
|
<QTable
|
||||||
:columns="vatColumns"
|
:columns="vatColumns"
|
||||||
:rows="entity.invoiceInTax"
|
:rows="entity.invoiceInTax"
|
||||||
|
@ -362,7 +366,7 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
|
||||||
</QCard>
|
</QCard>
|
||||||
<!--Due Day-->
|
<!--Due Day-->
|
||||||
<QCard v-if="entity.invoiceInDueDay.length" class="due-day">
|
<QCard v-if="entity.invoiceInDueDay.length" class="due-day">
|
||||||
<VnTitle :url="getLink('due-day')" :text="t('InvoiceIn.card.dueDay')" />
|
<VnTitle :url="getLink('due-day')" :text="t('invoicein.card.dueDay')" />
|
||||||
<QTable :columns="dueDayColumns" :rows="entity.invoiceInDueDay" flat>
|
<QTable :columns="dueDayColumns" :rows="entity.invoiceInDueDay" flat>
|
||||||
<template #header="dueDayProps">
|
<template #header="dueDayProps">
|
||||||
<QTr :props="dueDayProps" class="bg">
|
<QTr :props="dueDayProps" class="bg">
|
||||||
|
@ -400,7 +404,7 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
|
||||||
<QCard v-if="entity.invoiceInIntrastat.length">
|
<QCard v-if="entity.invoiceInIntrastat.length">
|
||||||
<VnTitle
|
<VnTitle
|
||||||
:url="getLink('intrastat')"
|
:url="getLink('intrastat')"
|
||||||
:text="t('InvoiceIn.card.intrastat')"
|
:text="t('invoicein.card.intrastat')"
|
||||||
/>
|
/>
|
||||||
<QTable
|
<QTable
|
||||||
:columns="intrastatColumns"
|
:columns="intrastatColumns"
|
||||||
|
|
|
@ -83,7 +83,7 @@ const redirectToInvoiceInBasicData = (__, { id }) => {
|
||||||
</template>
|
</template>
|
||||||
</VnSelect>
|
</VnSelect>
|
||||||
<VnInput
|
<VnInput
|
||||||
:label="t('InvoiceIn.list.supplierRef')"
|
:label="t('invoicein.list.supplierRef')"
|
||||||
v-model="data.supplierRef"
|
v-model="data.supplierRef"
|
||||||
/>
|
/>
|
||||||
</VnRow>
|
</VnRow>
|
||||||
|
@ -97,10 +97,10 @@ const redirectToInvoiceInBasicData = (__, { id }) => {
|
||||||
map-options
|
map-options
|
||||||
hide-selected
|
hide-selected
|
||||||
:required="true"
|
:required="true"
|
||||||
:rules="validate('InvoiceIn.companyFk')"
|
:rules="validate('invoicein.companyFk')"
|
||||||
/>
|
/>
|
||||||
<VnInputDate
|
<VnInputDate
|
||||||
:label="t('InvoiceIn.summary.issued')"
|
:label="t('invoicein.summary.issued')"
|
||||||
v-model="data.issued"
|
v-model="data.issued"
|
||||||
/>
|
/>
|
||||||
</VnRow>
|
</VnRow>
|
||||||
|
|
|
@ -164,7 +164,7 @@ function handleDaysAgo(params, daysAgo) {
|
||||||
<QItem>
|
<QItem>
|
||||||
<QItemSection>
|
<QItemSection>
|
||||||
<QCheckbox
|
<QCheckbox
|
||||||
:label="$t('InvoiceIn.isBooked')"
|
:label="$t('invoicein.isBooked')"
|
||||||
v-model="params.isBooked"
|
v-model="params.isBooked"
|
||||||
@update:model-value="searchFn()"
|
@update:model-value="searchFn()"
|
||||||
toggle-indeterminate
|
toggle-indeterminate
|
||||||
|
|
|
@ -26,7 +26,7 @@ const cols = computed(() => [
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
name: 'isBooked',
|
name: 'isBooked',
|
||||||
label: t('InvoiceIn.isBooked'),
|
label: t('invoicein.isBooked'),
|
||||||
columnFilter: false,
|
columnFilter: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -41,7 +41,7 @@ const cols = computed(() => [
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
name: 'supplierFk',
|
name: 'supplierFk',
|
||||||
label: t('InvoiceIn.list.supplier'),
|
label: t('invoicein.list.supplier'),
|
||||||
columnFilter: {
|
columnFilter: {
|
||||||
component: 'select',
|
component: 'select',
|
||||||
attrs: {
|
attrs: {
|
||||||
|
@ -55,16 +55,16 @@ const cols = computed(() => [
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
name: 'supplierRef',
|
name: 'supplierRef',
|
||||||
label: t('InvoiceIn.list.supplierRef'),
|
label: t('invoicein.list.supplierRef'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
name: 'serial',
|
name: 'serial',
|
||||||
label: t('InvoiceIn.serial'),
|
label: t('invoicein.serial'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
label: t('InvoiceIn.list.issued'),
|
label: t('invoicein.list.issued'),
|
||||||
name: 'issued',
|
name: 'issued',
|
||||||
component: null,
|
component: null,
|
||||||
columnFilter: {
|
columnFilter: {
|
||||||
|
@ -74,7 +74,7 @@ const cols = computed(() => [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
label: t('InvoiceIn.list.dueDated'),
|
label: t('invoicein.list.dueDated'),
|
||||||
name: 'dueDated',
|
name: 'dueDated',
|
||||||
component: null,
|
component: null,
|
||||||
columnFilter: {
|
columnFilter: {
|
||||||
|
@ -86,12 +86,12 @@ const cols = computed(() => [
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
name: 'awbCode',
|
name: 'awbCode',
|
||||||
label: t('InvoiceIn.list.awb'),
|
label: t('invoicein.list.awb'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
name: 'amount',
|
name: 'amount',
|
||||||
label: t('InvoiceIn.list.amount'),
|
label: t('invoicein.list.amount'),
|
||||||
format: ({ amount }) => toCurrency(amount),
|
format: ({ amount }) => toCurrency(amount),
|
||||||
cardVisible: true,
|
cardVisible: true,
|
||||||
},
|
},
|
||||||
|
@ -182,7 +182,7 @@ const cols = computed(() => [
|
||||||
</template>
|
</template>
|
||||||
</VnSelect>
|
</VnSelect>
|
||||||
<VnInput
|
<VnInput
|
||||||
:label="t('InvoiceIn.list.supplierRef')"
|
:label="t('invoicein.list.supplierRef')"
|
||||||
v-model="data.supplierRef"
|
v-model="data.supplierRef"
|
||||||
/>
|
/>
|
||||||
<VnSelect
|
<VnSelect
|
||||||
|
@ -194,7 +194,7 @@ const cols = computed(() => [
|
||||||
option-label="code"
|
option-label="code"
|
||||||
:required="true"
|
:required="true"
|
||||||
/>
|
/>
|
||||||
<VnInputDate :label="t('InvoiceIn.summary.issued')" v-model="data.issued" />
|
<VnInputDate :label="t('invoicein.summary.issued')" v-model="data.issued" />
|
||||||
</template>
|
</template>
|
||||||
</VnTable>
|
</VnTable>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
InvoiceIn:
|
invoicein:
|
||||||
serial: Serial
|
serial: Serial
|
||||||
isBooked: Is booked
|
isBooked: Is booked
|
||||||
list:
|
list:
|
||||||
|
@ -12,6 +12,26 @@ InvoiceIn:
|
||||||
amount: Amount
|
amount: Amount
|
||||||
descriptor:
|
descriptor:
|
||||||
ticketList: Ticket list
|
ticketList: Ticket list
|
||||||
|
descriptorMenu:
|
||||||
|
book: Book
|
||||||
|
unbook: Unbook
|
||||||
|
delete: Delete
|
||||||
|
clone: Clone
|
||||||
|
toBook: To book
|
||||||
|
toUnbook: To unbook
|
||||||
|
deleteInvoice: Delete invoice
|
||||||
|
invoiceDeleted: invoice deleted
|
||||||
|
cloneInvoice: Clone invoice
|
||||||
|
invoiceCloned: Invoice cloned
|
||||||
|
showAgriculturalPdf: Show agricultural receipt as PDF
|
||||||
|
sendAgriculturalPdf: Send agricultural receipt as PDF
|
||||||
|
checkSendInvoice: Are you sure you want to send it?
|
||||||
|
sendPdfInvoice: Send PDF invoice
|
||||||
|
createCorrective: Create rectificative invoice
|
||||||
|
correctiveInvoice: Rectificative invoice
|
||||||
|
originalInvoice: Original invoice
|
||||||
|
entry: Entry
|
||||||
|
emailEmpty: The email can't be empty
|
||||||
card:
|
card:
|
||||||
client: Client
|
client: Client
|
||||||
company: Company
|
company: Company
|
||||||
|
@ -46,8 +66,6 @@ InvoiceIn:
|
||||||
search: Id or supplier name
|
search: Id or supplier name
|
||||||
correctedFk: Corrected
|
correctedFk: Corrected
|
||||||
isBooked: Is booked
|
isBooked: Is booked
|
||||||
invoicein:
|
|
||||||
params:
|
|
||||||
account: Ledger account
|
account: Ledger account
|
||||||
correctingFk: Rectificative
|
correctingFk: Rectificative
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
InvoiceIn:
|
invoicein:
|
||||||
serial: Serie
|
serial: Serie
|
||||||
isBooked: Contabilizada
|
isBooked: Contabilizada
|
||||||
list:
|
list:
|
||||||
|
@ -12,6 +12,26 @@ InvoiceIn:
|
||||||
amount: Importe
|
amount: Importe
|
||||||
descriptor:
|
descriptor:
|
||||||
ticketList: Listado de tickets
|
ticketList: Listado de tickets
|
||||||
|
descriptorMenu:
|
||||||
|
book: Asentar
|
||||||
|
unbook: Desasentar
|
||||||
|
delete: Eliminar
|
||||||
|
clone: Clonar
|
||||||
|
toBook: Contabilizar
|
||||||
|
toUnbook: Descontabilizar
|
||||||
|
deleteInvoice: Eliminar factura
|
||||||
|
invoiceDeleted: Factura eliminada
|
||||||
|
cloneInvoice: Clonar factura
|
||||||
|
invoiceCloned: Factura clonada
|
||||||
|
showAgriculturalPdf: Ver recibo agrícola como PDF
|
||||||
|
sendAgriculturalPdf: Enviar recibo agrícola como PDF
|
||||||
|
checkSendInvoice: ¿Estás seguro que quieres enviarlo?
|
||||||
|
sendPdfInvoice: Enviar factura a PDF
|
||||||
|
createCorrective: Crear factura rectificativa
|
||||||
|
correctiveInvoice: Factura rectificativa
|
||||||
|
originalInvoice: Factura origen
|
||||||
|
entry: Entrada
|
||||||
|
emailEmpty: El email no puede estar vacío
|
||||||
card:
|
card:
|
||||||
client: Cliente
|
client: Cliente
|
||||||
company: Empresa
|
company: Empresa
|
||||||
|
@ -43,8 +63,6 @@ InvoiceIn:
|
||||||
params:
|
params:
|
||||||
search: Id o nombre proveedor
|
search: Id o nombre proveedor
|
||||||
correctedFk: Rectificada
|
correctedFk: Rectificada
|
||||||
invoicein:
|
|
||||||
params:
|
|
||||||
account: Cuenta contable
|
account: Cuenta contable
|
||||||
correctingFk: Rectificativa
|
correctingFk: Rectificativa
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ import { getUrl } from 'src/composables/getUrl';
|
||||||
import TicketDescriptorProxy from 'src/pages/Ticket/Card/TicketDescriptorProxy.vue';
|
import TicketDescriptorProxy from 'src/pages/Ticket/Card/TicketDescriptorProxy.vue';
|
||||||
import CustomerDescriptorProxy from 'src/pages/Customer/Card/CustomerDescriptorProxy.vue';
|
import CustomerDescriptorProxy from 'src/pages/Customer/Card/CustomerDescriptorProxy.vue';
|
||||||
import VnTitle from 'src/components/common/VnTitle.vue';
|
import VnTitle from 'src/components/common/VnTitle.vue';
|
||||||
|
import InvoiceOutDescriptorMenu from './InvoiceOutDescriptorMenu.vue';
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
fetch();
|
fetch();
|
||||||
|
@ -113,6 +114,9 @@ const ticketsColumns = ref([
|
||||||
<template #header="{ entity: { invoiceOut } }">
|
<template #header="{ entity: { invoiceOut } }">
|
||||||
<div>{{ invoiceOut.ref }} - {{ invoiceOut.client?.socialName }}</div>
|
<div>{{ invoiceOut.ref }} - {{ invoiceOut.client?.socialName }}</div>
|
||||||
</template>
|
</template>
|
||||||
|
<template #menu="{ entity }">
|
||||||
|
<InvoiceOutDescriptorMenu :invoice-out-data="entity.invoiceOut" />
|
||||||
|
</template>
|
||||||
<template #body="{ entity: { invoiceOut } }">
|
<template #body="{ entity: { invoiceOut } }">
|
||||||
<QCard class="vn-one">
|
<QCard class="vn-one">
|
||||||
<VnTitle :text="t('globals.pageTitles.basicData')" />
|
<VnTitle :text="t('globals.pageTitles.basicData')" />
|
||||||
|
|
|
@ -355,7 +355,7 @@ watchEffect(selectedRows);
|
||||||
<VnSelect
|
<VnSelect
|
||||||
url="InvoiceOutSerials"
|
url="InvoiceOutSerials"
|
||||||
v-model="data.serial"
|
v-model="data.serial"
|
||||||
:label="t('InvoiceIn.serial')"
|
:label="t('invoicein.serial')"
|
||||||
:options="invoiceOutSerialsOptions"
|
:options="invoiceOutSerialsOptions"
|
||||||
option-label="description"
|
option-label="description"
|
||||||
option-value="code"
|
option-value="code"
|
||||||
|
|
|
@ -6,17 +6,16 @@ import { useI18n } from 'vue-i18n';
|
||||||
import CardDescriptor from 'src/components/ui/CardDescriptor.vue';
|
import CardDescriptor from 'src/components/ui/CardDescriptor.vue';
|
||||||
import VnLv from 'src/components/ui/VnLv.vue';
|
import VnLv from 'src/components/ui/VnLv.vue';
|
||||||
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
|
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
|
||||||
import RegularizeStockForm from 'components/RegularizeStockForm.vue';
|
|
||||||
import ItemDescriptorImage from 'src/pages/Item/Card/ItemDescriptorImage.vue';
|
import ItemDescriptorImage from 'src/pages/Item/Card/ItemDescriptorImage.vue';
|
||||||
import useCardDescription from 'src/composables/useCardDescription';
|
import useCardDescription from 'src/composables/useCardDescription';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { dashIfEmpty } from 'src/filters';
|
import { dashIfEmpty } from 'src/filters';
|
||||||
import { useArrayData } from 'src/composables/useArrayData';
|
import { useArrayData } from 'src/composables/useArrayData';
|
||||||
import { cloneItem } from 'src/pages/Item/composables/cloneItem';
|
import ItemDescriptorMenu from './ItemDescriptorMenu.vue';
|
||||||
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
id: {
|
id: {
|
||||||
type: [Number, String],
|
type: Number,
|
||||||
required: false,
|
required: false,
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
|
@ -29,7 +28,7 @@ const $props = defineProps({
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
saleFk: {
|
saleFk: {
|
||||||
type: [Number, String],
|
type: Number,
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
warehouseFk: {
|
warehouseFk: {
|
||||||
|
@ -38,7 +37,6 @@ const $props = defineProps({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const { openCloneDialog } = cloneItem();
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const warehouseConfig = ref(null);
|
const warehouseConfig = ref(null);
|
||||||
|
@ -46,7 +44,6 @@ const entityId = computed(() => {
|
||||||
return $props.id || route.params.id;
|
return $props.id || route.params.id;
|
||||||
});
|
});
|
||||||
|
|
||||||
const regularizeStockFormDialog = ref(null);
|
|
||||||
const mounted = ref();
|
const mounted = ref();
|
||||||
|
|
||||||
const arrayDataStock = useArrayData('descriptorStock', {
|
const arrayDataStock = useArrayData('descriptorStock', {
|
||||||
|
@ -61,14 +58,14 @@ onMounted(async () => {
|
||||||
const data = ref(useCardDescription());
|
const data = ref(useCardDescription());
|
||||||
const setData = async (entity) => {
|
const setData = async (entity) => {
|
||||||
if (!entity) return;
|
if (!entity) return;
|
||||||
data.value = useCardDescription(entity?.name, entity?.id);
|
data.value = useCardDescription(entity.name, entity.id);
|
||||||
await updateStock();
|
await updateStock();
|
||||||
};
|
};
|
||||||
|
|
||||||
const getItemConfigs = async () => {
|
const getItemConfigs = async () => {
|
||||||
const { data } = await axios.get('ItemConfigs/findOne');
|
const { data } = await axios.get('ItemConfigs/findOne');
|
||||||
if (!data) return;
|
if (!data) return;
|
||||||
return (warehouseConfig.value = data.warehouseFk);
|
warehouseConfig.value = data.warehouseFk;
|
||||||
};
|
};
|
||||||
const updateStock = async () => {
|
const updateStock = async () => {
|
||||||
if (!mounted.value) return;
|
if (!mounted.value) return;
|
||||||
|
@ -89,10 +86,6 @@ const updateStock = async () => {
|
||||||
if (storeData?.itemFk == entityId.value) return;
|
if (storeData?.itemFk == entityId.value) return;
|
||||||
await stock.fetch({});
|
await stock.fetch({});
|
||||||
};
|
};
|
||||||
|
|
||||||
const openRegularizeStockForm = () => {
|
|
||||||
regularizeStockFormDialog.value.show();
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -105,24 +98,12 @@ const openRegularizeStockForm = () => {
|
||||||
:url="`Items/${entityId}/getCard`"
|
:url="`Items/${entityId}/getCard`"
|
||||||
@on-fetch="setData"
|
@on-fetch="setData"
|
||||||
>
|
>
|
||||||
<template #menu="{}">
|
<template #menu>
|
||||||
<QItem v-ripple clickable @click="openRegularizeStockForm()">
|
<ItemDescriptorMenu
|
||||||
<QItemSection>
|
:entity-id="entityId"
|
||||||
{{ t('Regularize stock') }}
|
:warehouse-fk="warehouseFk"
|
||||||
<QDialog ref="regularizeStockFormDialog">
|
@regularized="updateStock"
|
||||||
<RegularizeStockForm
|
/>
|
||||||
:item-fk="entityId"
|
|
||||||
:warehouse-fk="warehouseFk"
|
|
||||||
@on-data-saved="updateStock()"
|
|
||||||
/>
|
|
||||||
</QDialog>
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
<QItem v-ripple clickable @click="openCloneDialog(entityId)">
|
|
||||||
<QItemSection>
|
|
||||||
{{ t('globals.clone') }}
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
</template>
|
</template>
|
||||||
<template #before>
|
<template #before>
|
||||||
<ItemDescriptorImage
|
<ItemDescriptorImage
|
||||||
|
@ -191,7 +172,6 @@ const openRegularizeStockForm = () => {
|
||||||
|
|
||||||
<i18n>
|
<i18n>
|
||||||
es:
|
es:
|
||||||
Regularize stock: Regularizar stock
|
|
||||||
Inactive article: Artículo inactivo
|
Inactive article: Artículo inactivo
|
||||||
</i18n>
|
</i18n>
|
||||||
|
|
||||||
|
|
|
@ -131,7 +131,6 @@ const handlePhotoUpdated = (evt = false) => {
|
||||||
|
|
||||||
<i18n>
|
<i18n>
|
||||||
es:
|
es:
|
||||||
Regularize stock: Regularizar stock
|
|
||||||
All it's properties will be copied: Todas sus propiedades serán copiadas
|
All it's properties will be copied: Todas sus propiedades serán copiadas
|
||||||
Do you want to clone this item?: ¿Desea clonar este artículo?
|
Do you want to clone this item?: ¿Desea clonar este artículo?
|
||||||
warehouseText: Calculado sobre el almacén de { warehouseName }
|
warehouseText: Calculado sobre el almacén de { warehouseName }
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
<script setup>
|
||||||
|
import RegularizeStockForm from 'components/RegularizeStockForm.vue';
|
||||||
|
import { cloneItem } from 'src/pages/Item/composables/cloneItem';
|
||||||
|
|
||||||
|
const { openCloneDialog } = cloneItem();
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
entityId: {
|
||||||
|
type: Number,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
warehouseFk: {
|
||||||
|
type: Number,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
defineEmits(['regularized']);
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<QItem v-ripple clickable @click="$refs.regularizeStockFormDialog.show()">
|
||||||
|
<QItemSection>
|
||||||
|
{{ $t('item.regularizeStock') }}
|
||||||
|
<QDialog ref="regularizeStockFormDialog">
|
||||||
|
<RegularizeStockForm
|
||||||
|
:item-fk="entityId"
|
||||||
|
:warehouse-fk="warehouseFk"
|
||||||
|
@on-data-saved="$emit('regularized')"
|
||||||
|
/>
|
||||||
|
</QDialog>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
<QItem v-ripple clickable @click="openCloneDialog(entityId)">
|
||||||
|
<QItemSection>
|
||||||
|
{{ $t('globals.clone') }}
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.weekdaysBtn {
|
||||||
|
margin: 1%;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -8,6 +8,7 @@ import VnLv from 'src/components/ui/VnLv.vue';
|
||||||
import ItemDescriptorImage from 'src/pages/Item/Card/ItemDescriptorImage.vue';
|
import ItemDescriptorImage from 'src/pages/Item/Card/ItemDescriptorImage.vue';
|
||||||
import VnUserLink from 'src/components/ui/VnUserLink.vue';
|
import VnUserLink from 'src/components/ui/VnUserLink.vue';
|
||||||
import VnTitle from 'src/components/common/VnTitle.vue';
|
import VnTitle from 'src/components/common/VnTitle.vue';
|
||||||
|
import ItemDescriptorMenu from './ItemDescriptorMenu.vue';
|
||||||
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
id: {
|
id: {
|
||||||
|
@ -43,10 +44,13 @@ const getUrl = (id, param) => `#/Item/${id}/${param}`;
|
||||||
<template #header="{ entity: { item } }">
|
<template #header="{ entity: { item } }">
|
||||||
{{ item.id }} - {{ item.name }}
|
{{ item.id }} - {{ item.name }}
|
||||||
</template>
|
</template>
|
||||||
|
<template #menu>
|
||||||
|
<ItemDescriptorMenu :entity-id="entityId" :warehouse-fk="warehouseFk" />
|
||||||
|
</template>
|
||||||
<template #body="{ entity: { item, tags, visible, available, botanical } }">
|
<template #body="{ entity: { item, tags, visible, available, botanical } }">
|
||||||
<QCard class="vn-one photo">
|
<QCard class="vn-one photo">
|
||||||
<ItemDescriptorImage
|
<ItemDescriptorImage
|
||||||
:entity-id="Number(entityId)"
|
:entity-id="entityId"
|
||||||
:visible="visible"
|
:visible="visible"
|
||||||
:available="available"
|
:available="available"
|
||||||
:show-edit-button="false"
|
:show-edit-button="false"
|
||||||
|
@ -89,7 +93,7 @@ const getUrl = (id, param) => `#/Item/${id}/${param}`;
|
||||||
<QCard class="vn-one">
|
<QCard class="vn-one">
|
||||||
<VnTitle
|
<VnTitle
|
||||||
:url="getUrl(entityId, 'basic-data')"
|
:url="getUrl(entityId, 'basic-data')"
|
||||||
:text="t('item.summary.basicData')"
|
:text="t('item.summary.otherData')"
|
||||||
/>
|
/>
|
||||||
<VnLv
|
<VnLv
|
||||||
:label="t('item.summary.intrastatCode')"
|
:label="t('item.summary.intrastatCode')"
|
||||||
|
|
|
@ -152,7 +152,7 @@ const columns = computed(() => [
|
||||||
},
|
},
|
||||||
columnField: {
|
columnField: {
|
||||||
component: null,
|
component: null,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('item.list.category'),
|
label: t('item.list.category'),
|
||||||
|
@ -391,7 +391,7 @@ onBeforeMount(async () => {
|
||||||
{{ row?.subName.toUpperCase() }}
|
{{ row?.subName.toUpperCase() }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<FetchedTags :item="row" :columns="3" />
|
<FetchedTags :item="row" />
|
||||||
</template>
|
</template>
|
||||||
<template #more-create-dialog="{ data }">
|
<template #more-create-dialog="{ data }">
|
||||||
<VnInput
|
<VnInput
|
||||||
|
@ -498,5 +498,4 @@ es:
|
||||||
Create Item: Crear artículo
|
Create Item: Crear artículo
|
||||||
You can search by id: Puedes buscar por id
|
You can search by id: Puedes buscar por id
|
||||||
Preview: Vista previa
|
Preview: Vista previa
|
||||||
Regularize stock: Regularizar stock
|
|
||||||
</i18n>
|
</i18n>
|
||||||
|
|
|
@ -172,24 +172,22 @@ const changeQuantity = async (request) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
await axios.patch(`Sales/${request.saleFk}`, params);
|
await axios.patch(`Sales/${request.saleFk}`, params);
|
||||||
notify(t('globals.dataSaved'), 'positive');
|
}
|
||||||
confirmRequest(request);
|
await confirmRequest(request);
|
||||||
} else confirmRequest(request);
|
notify(t('globals.dataSaved'), 'positive');
|
||||||
};
|
};
|
||||||
|
|
||||||
const confirmRequest = async (request) => {
|
const confirmRequest = async (request) => {
|
||||||
if (request.itemFk && request.saleQuantity) {
|
if (!request.itemFk || !request.saleQuantity) return;
|
||||||
const params = {
|
const params = {
|
||||||
itemFk: request.itemFk,
|
itemFk: request.itemFk,
|
||||||
quantity: request.saleQuantity,
|
quantity: request.saleQuantity,
|
||||||
attenderFk: request.attenderFk,
|
attenderFk: request.attenderFk,
|
||||||
};
|
};
|
||||||
|
|
||||||
const { data } = await axios.post(`TicketRequests/${request.id}/confirm`, params);
|
const { data } = await axios.post(`TicketRequests/${request.id}/confirm`, params);
|
||||||
request.itemDescription = data.concept;
|
request.itemDescription = data.concept;
|
||||||
request.isOk = true;
|
request.isOk = true;
|
||||||
notify(t('globals.dataSaved'), 'positive');
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const getState = (isOk) => {
|
const getState = (isOk) => {
|
||||||
|
|
|
@ -58,6 +58,7 @@ lastEntries:
|
||||||
pvp: PVP
|
pvp: PVP
|
||||||
label: Label
|
label: Label
|
||||||
grouping: Grouping
|
grouping: Grouping
|
||||||
|
packing: Packing
|
||||||
quantity: Quantity
|
quantity: Quantity
|
||||||
cost: Cost
|
cost: Cost
|
||||||
kg: Kg.
|
kg: Kg.
|
||||||
|
@ -219,3 +220,4 @@ item:
|
||||||
minSalesQuantity: 'Cantidad mínima de venta'
|
minSalesQuantity: 'Cantidad mínima de venta'
|
||||||
genus: 'Genus'
|
genus: 'Genus'
|
||||||
specie: 'Specie'
|
specie: 'Specie'
|
||||||
|
regularizeStock: Regularize stock
|
||||||
|
|
|
@ -58,6 +58,7 @@ lastEntries:
|
||||||
pvp: PVP
|
pvp: PVP
|
||||||
label: Eti.
|
label: Eti.
|
||||||
grouping: Grouping
|
grouping: Grouping
|
||||||
|
packing: Packing
|
||||||
quantity: Cantidad
|
quantity: Cantidad
|
||||||
cost: Coste
|
cost: Coste
|
||||||
kg: Kg.
|
kg: Kg.
|
||||||
|
@ -210,6 +211,7 @@ item:
|
||||||
minSalesQuantity: 'Cantidad mínima de venta'
|
minSalesQuantity: 'Cantidad mínima de venta'
|
||||||
genus: 'Genus'
|
genus: 'Genus'
|
||||||
specie: 'Specie'
|
specie: 'Specie'
|
||||||
|
regularizeStock: Regularizar stock
|
||||||
buyRequest:
|
buyRequest:
|
||||||
ticketId: 'ID Ticket'
|
ticketId: 'ID Ticket'
|
||||||
shipped: 'F. envío'
|
shipped: 'F. envío'
|
||||||
|
|
|
@ -1,38 +1,12 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { computed } from 'vue';
|
import VnCardBeta from 'components/common/VnCardBeta.vue';
|
||||||
import { useRoute } from 'vue-router';
|
|
||||||
import VnCard from 'components/common/VnCard.vue';
|
|
||||||
import OrderDescriptor from 'pages/Order/Card/OrderDescriptor.vue';
|
import OrderDescriptor from 'pages/Order/Card/OrderDescriptor.vue';
|
||||||
import OrderFilter from './OrderFilter.vue';
|
|
||||||
import OrderSearchbar from './OrderSearchbar.vue';
|
|
||||||
import OrderCatalogFilter from './OrderCatalogFilter.vue';
|
|
||||||
const config = {
|
|
||||||
OrderCatalog: OrderCatalogFilter,
|
|
||||||
};
|
|
||||||
const route = useRoute();
|
|
||||||
|
|
||||||
const routeName = computed(() => route.name);
|
|
||||||
const customRouteRedirectName = computed(() => {
|
|
||||||
const route = config[routeName.value];
|
|
||||||
if (route) return null;
|
|
||||||
return 'OrderList';
|
|
||||||
});
|
|
||||||
const customFilterPanel = computed(() => {
|
|
||||||
const filterPanel = config[routeName.value] ?? OrderFilter;
|
|
||||||
return filterPanel;
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<VnCard
|
<VnCardBeta
|
||||||
data-key="Order"
|
data-key="Order"
|
||||||
base-url="Orders"
|
base-url="Orders"
|
||||||
:descriptor="OrderDescriptor"
|
:descriptor="OrderDescriptor"
|
||||||
:filter-panel="customFilterPanel"
|
/>
|
||||||
:search-data-key="customRouteRedirectName"
|
|
||||||
>
|
|
||||||
<template #searchbar>
|
|
||||||
<OrderSearchbar />
|
|
||||||
</template>
|
|
||||||
</VnCard>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -15,15 +15,18 @@ const router = useRouter();
|
||||||
const stateStore = useStateStore();
|
const stateStore = useStateStore();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const dataKey = 'OrderCatalogList';
|
const dataKey = 'OrderCatalogList';
|
||||||
const arrayData = useArrayData(dataKey);
|
const catalogParams = {
|
||||||
const store = arrayData.store;
|
|
||||||
const tags = ref([]);
|
|
||||||
const itemRefs = ref({});
|
|
||||||
|
|
||||||
let catalogParams = {
|
|
||||||
orderFk: route.params.id,
|
orderFk: route.params.id,
|
||||||
orderBy: JSON.stringify({ field: 'relevancy DESC, name', way: 'ASC', isTag: false }),
|
orderBy: JSON.stringify({ field: 'relevancy DESC, name', way: 'ASC', isTag: false }),
|
||||||
};
|
};
|
||||||
|
const arrayData = useArrayData(dataKey, {
|
||||||
|
url: 'Orders/CatalogFilter',
|
||||||
|
limit: 50,
|
||||||
|
userParams: catalogParams,
|
||||||
|
});
|
||||||
|
const store = arrayData.store;
|
||||||
|
const tags = ref([]);
|
||||||
|
const itemRefs = ref({});
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
stateStore.rightDrawer = true;
|
stateStore.rightDrawer = true;
|
||||||
|
@ -66,7 +69,6 @@ function extractValueTags(items) {
|
||||||
);
|
);
|
||||||
tagValue.value = resultValueTags;
|
tagValue.value = resultValueTags;
|
||||||
}
|
}
|
||||||
const autoLoad = computed(() => !!JSON.parse(route?.query.table ?? '{}')?.categoryFk);
|
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => store.data,
|
() => store.data,
|
||||||
|
@ -78,16 +80,15 @@ watch(
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<VnSearchbar
|
<Teleport to="#section-searchbar" v-if="stateStore.isHeaderMounted()">
|
||||||
:data-key="dataKey"
|
<VnSearchbar
|
||||||
:user-params="catalogParams"
|
:data-key="dataKey"
|
||||||
:static-params="['orderFk', 'orderBy']"
|
:redirect="false"
|
||||||
:redirect="false"
|
:label="t('Search items')"
|
||||||
url="Orders/CatalogFilter"
|
:info="t('You can search items by name or id')"
|
||||||
:label="t('Search items')"
|
:search-remove-params="false"
|
||||||
:info="t('You can search items by name or id')"
|
/>
|
||||||
:search-remove-params="false"
|
</Teleport>
|
||||||
/>
|
|
||||||
<Teleport to="#right-panel" v-if="stateStore.isHeaderMounted()">
|
<Teleport to="#right-panel" v-if="stateStore.isHeaderMounted()">
|
||||||
<OrderCatalogFilter
|
<OrderCatalogFilter
|
||||||
:data-key="dataKey"
|
:data-key="dataKey"
|
||||||
|
@ -98,13 +99,7 @@ watch(
|
||||||
</Teleport>
|
</Teleport>
|
||||||
<QPage class="column items-center q-pa-md" data-cy="orderCatalogPage">
|
<QPage class="column items-center q-pa-md" data-cy="orderCatalogPage">
|
||||||
<div class="full-width">
|
<div class="full-width">
|
||||||
<VnPaginate
|
<VnPaginate :data-key="dataKey">
|
||||||
:data-key="dataKey"
|
|
||||||
url="Orders/CatalogFilter"
|
|
||||||
:limit="50"
|
|
||||||
:user-params="catalogParams"
|
|
||||||
:auto-load="autoLoad"
|
|
||||||
>
|
|
||||||
<template #body="{ rows }">
|
<template #body="{ rows }">
|
||||||
<div class="catalog-list">
|
<div class="catalog-list">
|
||||||
<div v-if="rows && !rows?.length" class="no-result">
|
<div v-if="rows && !rows?.length" class="no-result">
|
||||||
|
|
|
@ -9,7 +9,6 @@ import useCardDescription from 'src/composables/useCardDescription';
|
||||||
import CardDescriptor from 'components/ui/CardDescriptor.vue';
|
import CardDescriptor from 'components/ui/CardDescriptor.vue';
|
||||||
import VnLv from 'src/components/ui/VnLv.vue';
|
import VnLv from 'src/components/ui/VnLv.vue';
|
||||||
import FetchData from 'components/FetchData.vue';
|
import FetchData from 'components/FetchData.vue';
|
||||||
import OrderDescriptorMenu from 'pages/Order/Card/OrderDescriptorMenu.vue';
|
|
||||||
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
|
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
|
||||||
|
|
||||||
const DEFAULT_ITEMS = 0;
|
const DEFAULT_ITEMS = 0;
|
||||||
|
@ -94,9 +93,6 @@ const total = ref(0);
|
||||||
@on-fetch="setData"
|
@on-fetch="setData"
|
||||||
data-key="orderData"
|
data-key="orderData"
|
||||||
>
|
>
|
||||||
<template #menu="{ entity }">
|
|
||||||
<OrderDescriptorMenu :order="entity" />
|
|
||||||
</template>
|
|
||||||
<template #body="{ entity }">
|
<template #body="{ entity }">
|
||||||
<VnLv
|
<VnLv
|
||||||
:label="t('globals.state')"
|
:label="t('globals.state')"
|
||||||
|
|
|
@ -208,15 +208,28 @@ async function remove(item) {
|
||||||
async function handleConfirm() {
|
async function handleConfirm() {
|
||||||
const result = await confirm(route.params.id);
|
const result = await confirm(route.params.id);
|
||||||
if (result) {
|
if (result) {
|
||||||
|
const sale = await axios.get(`OrderRows`, {
|
||||||
|
params: {
|
||||||
|
filter: JSON.stringify({
|
||||||
|
where: { orderFk: route.params.id },
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const ticket = await axios.get(`Sales`, {
|
||||||
|
params: {
|
||||||
|
filter: JSON.stringify({
|
||||||
|
where: { id: sale.data[0].saleFk },
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
});
|
||||||
quasar.notify({
|
quasar.notify({
|
||||||
message: t('globals.dataSaved'),
|
message: t('globals.dataSaved'),
|
||||||
type: 'positive',
|
type: 'positive',
|
||||||
});
|
});
|
||||||
router.push({
|
router.push({
|
||||||
name: 'TicketList',
|
name: 'TicketSale',
|
||||||
query: {
|
params: { id: ticket.data[0].ticketFk },
|
||||||
table: JSON.stringify({ clientFk: descriptorData.store.data.clientFk }),
|
query: { table: JSON.stringify({ filter: { limit: 20, skip: 0 } }) },
|
||||||
},
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
<script setup>
|
|
||||||
import { useI18n } from 'vue-i18n';
|
|
||||||
import VnSearchbar from 'components/ui/VnSearchbar.vue';
|
|
||||||
|
|
||||||
const { t } = useI18n();
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<VnSearchbar
|
|
||||||
data-key="OrderList"
|
|
||||||
url="Orders/filter"
|
|
||||||
:label="t('Search order')"
|
|
||||||
:info="t('Search orders by ticket id')"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped lang="scss"></style>
|
|
||||||
<i18n>
|
|
||||||
es:
|
|
||||||
Search order: Buscar orden
|
|
||||||
Search orders by ticket id: Buscar pedido por id ticket
|
|
||||||
</i18n>
|
|
|
@ -12,6 +12,7 @@ import CustomerDescriptorProxy from 'pages/Customer/Card/CustomerDescriptorProxy
|
||||||
import FetchedTags from 'components/ui/FetchedTags.vue';
|
import FetchedTags from 'components/ui/FetchedTags.vue';
|
||||||
import VnTitle from 'src/components/common/VnTitle.vue';
|
import VnTitle from 'src/components/common/VnTitle.vue';
|
||||||
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
|
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
|
||||||
|
import OrderDescriptorMenu from 'pages/Order/Card/OrderDescriptorMenu.vue';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
@ -91,6 +92,9 @@ async function handleConfirm() {
|
||||||
<QTooltip>{{ t('order.summary.confirmLines') }}</QTooltip>
|
<QTooltip>{{ t('order.summary.confirmLines') }}</QTooltip>
|
||||||
</QBtn>
|
</QBtn>
|
||||||
</template>
|
</template>
|
||||||
|
<template #menu="{ entity }">
|
||||||
|
<OrderDescriptorMenu :order="entity" />
|
||||||
|
</template>
|
||||||
<template #body="{ entity }">
|
<template #body="{ entity }">
|
||||||
<QCard class="vn-one">
|
<QCard class="vn-one">
|
||||||
<VnTitle
|
<VnTitle
|
||||||
|
|
|
@ -8,15 +8,14 @@ import { useRoute } from 'vue-router';
|
||||||
|
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import OrderSummary from 'pages/Order/Card/OrderSummary.vue';
|
import OrderSummary from 'pages/Order/Card/OrderSummary.vue';
|
||||||
import OrderSearchbar from './Card/OrderSearchbar.vue';
|
|
||||||
import OrderFilter from './Card/OrderFilter.vue';
|
import OrderFilter from './Card/OrderFilter.vue';
|
||||||
import RightMenu from 'src/components/common/RightMenu.vue';
|
|
||||||
import CustomerDescriptorProxy from '../Customer/Card/CustomerDescriptorProxy.vue';
|
import CustomerDescriptorProxy from '../Customer/Card/CustomerDescriptorProxy.vue';
|
||||||
import WorkerDescriptorProxy from '../Worker/Card/WorkerDescriptorProxy.vue';
|
import WorkerDescriptorProxy from '../Worker/Card/WorkerDescriptorProxy.vue';
|
||||||
|
|
||||||
import VnTable from 'src/components/VnTable/VnTable.vue';
|
import VnTable from 'src/components/VnTable/VnTable.vue';
|
||||||
import VnInputDate from 'src/components/common/VnInputDate.vue';
|
import VnInputDate from 'src/components/common/VnInputDate.vue';
|
||||||
import VnSelect from 'src/components/common/VnSelect.vue';
|
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||||
|
import VnSection from 'src/components/common/VnSection.vue';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { viewSummary } = useSummaryDialog();
|
const { viewSummary } = useSummaryDialog();
|
||||||
|
@ -24,6 +23,8 @@ const tableRef = ref();
|
||||||
const agencyList = ref([]);
|
const agencyList = ref([]);
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const addressOptions = ref([]);
|
const addressOptions = ref([]);
|
||||||
|
const dataKey = 'OrderList';
|
||||||
|
|
||||||
const columns = computed(() => [
|
const columns = computed(() => [
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
|
@ -178,117 +179,126 @@ const getDateColor = (date) => {
|
||||||
if (difference < 0) return 'bg-success';
|
if (difference < 0) return 'bg-success';
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<OrderSearchbar />
|
<VnSection
|
||||||
<RightMenu>
|
:data-key="dataKey"
|
||||||
<template #right-panel>
|
:columns="columns"
|
||||||
|
prefix="order"
|
||||||
|
:array-data-props="{
|
||||||
|
url: 'Orders/filter',
|
||||||
|
order: ['landed DESC', 'clientFk ASC', 'id DESC'],
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<template #rightMenu>
|
||||||
<OrderFilter data-key="OrderList" />
|
<OrderFilter data-key="OrderList" />
|
||||||
</template>
|
</template>
|
||||||
</RightMenu>
|
<template #body>
|
||||||
<VnTable
|
<VnTable
|
||||||
ref="tableRef"
|
ref="tableRef"
|
||||||
data-key="OrderList"
|
:data-key="dataKey"
|
||||||
url="Orders/filter"
|
:create="{
|
||||||
:order="['landed DESC', 'clientFk ASC', 'id DESC']"
|
urlCreate: 'Orders/new',
|
||||||
:create="{
|
title: t('module.cerateOrder'),
|
||||||
urlCreate: 'Orders/new',
|
onDataSaved: (url) => {
|
||||||
title: t('module.cerateOrder'),
|
tableRef.redirect(`${url}/catalog`);
|
||||||
onDataSaved: (url) => {
|
},
|
||||||
tableRef.redirect(`${url}/catalog`);
|
formInitialData: {
|
||||||
},
|
active: true,
|
||||||
formInitialData: {
|
addressId: null,
|
||||||
active: true,
|
clientFk: null,
|
||||||
addressId: null,
|
},
|
||||||
clientFk: null,
|
}"
|
||||||
},
|
:user-params="{ showEmpty: false }"
|
||||||
}"
|
:columns="columns"
|
||||||
:user-params="{ showEmpty: false }"
|
:right-search="false"
|
||||||
:columns="columns"
|
redirect="order"
|
||||||
:right-search="false"
|
|
||||||
redirect="order"
|
|
||||||
>
|
|
||||||
<template #column-clientFk="{ row }">
|
|
||||||
<span class="link" @click.stop>
|
|
||||||
{{ row?.clientName }}
|
|
||||||
<CustomerDescriptorProxy :id="row?.clientFk" />
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<template #column-salesPersonFk="{ row }">
|
|
||||||
<span class="link" @click.stop>
|
|
||||||
{{ row?.name }}
|
|
||||||
<WorkerDescriptorProxy :id="row?.salesPersonFk" />
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<template #column-landed="{ row }">
|
|
||||||
<span v-if="getDateColor(row.landed)">
|
|
||||||
<QChip :class="getDateColor(row.landed)" dense square>
|
|
||||||
{{ toDate(row?.landed) }}
|
|
||||||
</QChip>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<template #more-create-dialog="{ data }">
|
|
||||||
<VnSelect
|
|
||||||
url="Clients"
|
|
||||||
:include="{ relation: 'addresses' }"
|
|
||||||
v-model="data.clientFk"
|
|
||||||
:label="t('module.customer')"
|
|
||||||
@update:model-value="(id) => fetchClientAddress(id, data)"
|
|
||||||
>
|
>
|
||||||
<template #option="scope">
|
<template #column-clientFk="{ row }">
|
||||||
<QItem v-bind="scope.itemProps">
|
<span class="link" @click.stop>
|
||||||
<QItemSection>
|
{{ row?.clientName }}
|
||||||
<QItemLabel>
|
<CustomerDescriptorProxy :id="row?.clientFk" />
|
||||||
{{ scope.opt.name }}
|
</span>
|
||||||
</QItemLabel>
|
|
||||||
<QItemLabel caption>
|
|
||||||
{{ `#${scope.opt.id}` }}
|
|
||||||
</QItemLabel>
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
</template>
|
</template>
|
||||||
</VnSelect>
|
<template #column-salesPersonFk="{ row }">
|
||||||
<VnSelect
|
<span class="link" @click.stop>
|
||||||
v-model="data.addressId"
|
{{ row?.name }}
|
||||||
:options="addressOptions"
|
<WorkerDescriptorProxy :id="row?.salesPersonFk" />
|
||||||
:label="t('module.address')"
|
</span>
|
||||||
option-value="id"
|
|
||||||
option-label="nickname"
|
|
||||||
@update:model-value="() => fetchAgencies(data)"
|
|
||||||
>
|
|
||||||
<template #option="scope">
|
|
||||||
<QItem v-bind="scope.itemProps">
|
|
||||||
<QItemSection>
|
|
||||||
<QItemLabel
|
|
||||||
:class="{
|
|
||||||
'color-vn-label': !scope.opt?.isActive,
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
{{
|
|
||||||
`${
|
|
||||||
!scope.opt?.isActive
|
|
||||||
? t('basicData.inactive')
|
|
||||||
: ''
|
|
||||||
} `
|
|
||||||
}}
|
|
||||||
{{ scope.opt?.nickname }}: {{ scope.opt?.street }},
|
|
||||||
{{ scope.opt?.city }}
|
|
||||||
</QItemLabel>
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
</template>
|
</template>
|
||||||
</VnSelect>
|
<template #column-landed="{ row }">
|
||||||
<VnInputDate
|
<span v-if="getDateColor(row.landed)">
|
||||||
v-model="data.landed"
|
<QChip :class="getDateColor(row.landed)" dense square>
|
||||||
:label="t('module.landed')"
|
{{ toDate(row?.landed) }}
|
||||||
@update:model-value="() => fetchAgencies(data)"
|
</QChip>
|
||||||
/>
|
</span>
|
||||||
<VnSelect
|
</template>
|
||||||
v-model="data.agencyModeId"
|
<template #more-create-dialog="{ data }">
|
||||||
:label="t('module.agency')"
|
<VnSelect
|
||||||
:options="agencyList"
|
url="Clients"
|
||||||
option-value="agencyModeFk"
|
:include="{ relation: 'addresses' }"
|
||||||
option-label="agencyMode"
|
v-model="data.clientFk"
|
||||||
/>
|
:label="t('module.customer')"
|
||||||
|
@update:model-value="(id) => fetchClientAddress(id, data)"
|
||||||
|
>
|
||||||
|
<template #option="scope">
|
||||||
|
<QItem v-bind="scope.itemProps">
|
||||||
|
<QItemSection>
|
||||||
|
<QItemLabel>
|
||||||
|
{{ scope.opt.name }}
|
||||||
|
</QItemLabel>
|
||||||
|
<QItemLabel caption>
|
||||||
|
{{ `#${scope.opt.id}` }}
|
||||||
|
</QItemLabel>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
</template>
|
||||||
|
</VnSelect>
|
||||||
|
<VnSelect
|
||||||
|
v-model="data.addressId"
|
||||||
|
:options="addressOptions"
|
||||||
|
:label="t('module.address')"
|
||||||
|
option-value="id"
|
||||||
|
option-label="nickname"
|
||||||
|
@update:model-value="() => fetchAgencies(data)"
|
||||||
|
>
|
||||||
|
<template #option="scope">
|
||||||
|
<QItem v-bind="scope.itemProps">
|
||||||
|
<QItemSection>
|
||||||
|
<QItemLabel
|
||||||
|
:class="{
|
||||||
|
'color-vn-label': !scope.opt?.isActive,
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
{{
|
||||||
|
`${
|
||||||
|
!scope.opt?.isActive
|
||||||
|
? t('basicData.inactive')
|
||||||
|
: ''
|
||||||
|
} `
|
||||||
|
}}
|
||||||
|
{{ scope.opt?.nickname }}:
|
||||||
|
{{ scope.opt?.street }},
|
||||||
|
{{ scope.opt?.city }}
|
||||||
|
</QItemLabel>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
</template>
|
||||||
|
</VnSelect>
|
||||||
|
<VnInputDate
|
||||||
|
v-model="data.landed"
|
||||||
|
:label="t('module.landed')"
|
||||||
|
@update:model-value="() => fetchAgencies(data)"
|
||||||
|
/>
|
||||||
|
<VnSelect
|
||||||
|
v-model="data.agencyModeId"
|
||||||
|
:label="t('module.agency')"
|
||||||
|
:options="agencyList"
|
||||||
|
option-value="agencyModeFk"
|
||||||
|
option-label="agencyMode"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</VnTable>
|
||||||
</template>
|
</template>
|
||||||
</VnTable>
|
</VnSection>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -21,3 +21,26 @@ lines:
|
||||||
image: Image
|
image: Image
|
||||||
params:
|
params:
|
||||||
tagGroups: Tags
|
tagGroups: Tags
|
||||||
|
order:
|
||||||
|
field:
|
||||||
|
salesPersonFk: Sales Person
|
||||||
|
form:
|
||||||
|
clientFk: Client
|
||||||
|
addressFk: Address
|
||||||
|
agencyModeFk: Agency
|
||||||
|
list:
|
||||||
|
newOrder: New Order
|
||||||
|
summary:
|
||||||
|
basket: Basket
|
||||||
|
notConfirmed: Not confirmed
|
||||||
|
created: Created
|
||||||
|
createdFrom: Created From
|
||||||
|
address: Address
|
||||||
|
total: Total
|
||||||
|
items: Items
|
||||||
|
orderTicketList: Order Ticket List
|
||||||
|
amount: Amount
|
||||||
|
confirm: Confirm
|
||||||
|
confirmLines: Confirm lines
|
||||||
|
search: Search orders
|
||||||
|
searchInfo: You can search orders by ticket id
|
||||||
|
|
|
@ -21,3 +21,29 @@ lines:
|
||||||
image: Imagen
|
image: Imagen
|
||||||
params:
|
params:
|
||||||
tagGroups: Tags
|
tagGroups: Tags
|
||||||
|
order:
|
||||||
|
field:
|
||||||
|
salesPersonFk: Comercial
|
||||||
|
form:
|
||||||
|
clientFk: Cliente
|
||||||
|
addressFk: Dirección
|
||||||
|
agencyModeFk: Agencia
|
||||||
|
list:
|
||||||
|
newOrder: Nuevo Pedido
|
||||||
|
summary:
|
||||||
|
basket: Cesta
|
||||||
|
notConfirmed: No confirmada
|
||||||
|
created: Creado
|
||||||
|
createdFrom: Creado desde
|
||||||
|
address: Dirección
|
||||||
|
total: Total
|
||||||
|
vat: IVA
|
||||||
|
state: Estado
|
||||||
|
alias: Alias
|
||||||
|
items: Artículos
|
||||||
|
orderTicketList: Tickets del pedido
|
||||||
|
amount: Monto
|
||||||
|
confirm: Confirmar
|
||||||
|
confirmLines: Confirmar lineas
|
||||||
|
search: Buscar pedido
|
||||||
|
searchInfo: Buscar pedidos por el número de ticket
|
||||||
|
|
|
@ -52,7 +52,7 @@ async function actualizeVolume() {
|
||||||
const params = { isOk: true };
|
const params = { isOk: true };
|
||||||
await axios.post(`Routes/${routeId}/updateVolume`, params);
|
await axios.post(`Routes/${routeId}/updateVolume`, params);
|
||||||
quasar.notify({
|
quasar.notify({
|
||||||
message: t('globals.dataUpdated'),
|
message: t('globals.dataSaved'),
|
||||||
type: 'positive',
|
type: 'positive',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import CustomerDescriptorProxy from 'pages/Customer/Card/CustomerDescriptorProxy
|
||||||
import TicketDescriptorProxy from 'pages/Ticket/Card/TicketDescriptorProxy.vue';
|
import TicketDescriptorProxy from 'pages/Ticket/Card/TicketDescriptorProxy.vue';
|
||||||
import VnLv from 'components/ui/VnLv.vue';
|
import VnLv from 'components/ui/VnLv.vue';
|
||||||
import VnTitle from 'src/components/common/VnTitle.vue';
|
import VnTitle from 'src/components/common/VnTitle.vue';
|
||||||
|
import RouteDescriptorMenu from './RouteDescriptorMenu.vue';
|
||||||
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
id: {
|
id: {
|
||||||
|
@ -128,6 +129,9 @@ const ticketColumns = ref([
|
||||||
<template #header="{ entity }">
|
<template #header="{ entity }">
|
||||||
<span>{{ `${entity?.route.id} - ${entity?.route?.description}` }}</span>
|
<span>{{ `${entity?.route.id} - ${entity?.route?.description}` }}</span>
|
||||||
</template>
|
</template>
|
||||||
|
<template #menu="{ entity }">
|
||||||
|
<RouteDescriptorMenu :route="entity.route" />
|
||||||
|
</template>
|
||||||
<template #body="{ entity }">
|
<template #body="{ entity }">
|
||||||
<QCard class="vn-max">
|
<QCard class="vn-max">
|
||||||
<VnTitle
|
<VnTitle
|
||||||
|
|
|
@ -10,6 +10,7 @@ import VnTitle from 'src/components/common/VnTitle.vue';
|
||||||
import CardSummary from 'components/ui/CardSummary.vue';
|
import CardSummary from 'components/ui/CardSummary.vue';
|
||||||
import SupplierDescriptorProxy from 'pages/Supplier/Card/SupplierDescriptorProxy.vue';
|
import SupplierDescriptorProxy from 'pages/Supplier/Card/SupplierDescriptorProxy.vue';
|
||||||
import VnLinkPhone from 'components/ui/VnLinkPhone.vue';
|
import VnLinkPhone from 'components/ui/VnLinkPhone.vue';
|
||||||
|
import RoadmapDescriptorMenu from './RoadmapDescriptorMenu.vue';
|
||||||
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
id: {
|
id: {
|
||||||
|
@ -86,6 +87,9 @@ const filter = {
|
||||||
<template #header="{ entity }">
|
<template #header="{ entity }">
|
||||||
<span>{{ `${entity?.id} - ${entity?.name}` }}</span>
|
<span>{{ `${entity?.id} - ${entity?.name}` }}</span>
|
||||||
</template>
|
</template>
|
||||||
|
<template #menu="{ entity }">
|
||||||
|
<RoadmapDescriptorMenu :route="entity" />
|
||||||
|
</template>
|
||||||
<template #body="{ entity }">
|
<template #body="{ entity }">
|
||||||
<QCard class="vn-one">
|
<QCard class="vn-one">
|
||||||
<VnTitle
|
<VnTitle
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { useQuasar } from 'quasar';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import VnConfirm from 'components/ui/VnConfirm.vue';
|
import VnConfirm from 'components/ui/VnConfirm.vue';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
shelving: {
|
shelving: {
|
||||||
|
@ -14,8 +15,11 @@ const $props = defineProps({
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const quasar = useQuasar();
|
const quasar = useQuasar();
|
||||||
|
const route = useRoute();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const emit = defineEmits(['onRemove']);
|
||||||
|
|
||||||
function confirmRemove() {
|
function confirmRemove() {
|
||||||
quasar.dialog({
|
quasar.dialog({
|
||||||
component: VnConfirm,
|
component: VnConfirm,
|
||||||
|
@ -32,11 +36,12 @@ async function remove() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await axios.delete(`Shelvings/${$props.shelving.id}`);
|
await axios.delete(`Shelvings/${$props.shelving.id}`);
|
||||||
await router.push({ name: 'ShelvingList' });
|
if (route.name != 'ShelvingList') await router.push({ name: 'ShelvingList' });
|
||||||
quasar.notify({
|
quasar.notify({
|
||||||
message: t('globals.dataDeleted'),
|
message: t('globals.dataDeleted'),
|
||||||
type: 'positive',
|
type: 'positive',
|
||||||
});
|
});
|
||||||
|
emit('onRemove', {});
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { computed } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import CardSummary from 'components/ui/CardSummary.vue';
|
import CardSummary from 'components/ui/CardSummary.vue';
|
||||||
import VnLv from 'components/ui/VnLv.vue';
|
import VnLv from 'components/ui/VnLv.vue';
|
||||||
import VnUserLink from 'components/ui/VnUserLink.vue';
|
import VnUserLink from 'components/ui/VnUserLink.vue';
|
||||||
|
import ShelvingDescriptorMenu from './ShelvingDescriptorMenu.vue';
|
||||||
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
id: {
|
id: {
|
||||||
|
@ -14,7 +15,7 @@ const $props = defineProps({
|
||||||
});
|
});
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
const summary = ref({});
|
||||||
const entityId = computed(() => $props.id || route.params.id);
|
const entityId = computed(() => $props.id || route.params.id);
|
||||||
|
|
||||||
const filter = {
|
const filter = {
|
||||||
|
@ -43,7 +44,13 @@ const filter = {
|
||||||
data-key="ShelvingSummary"
|
data-key="ShelvingSummary"
|
||||||
>
|
>
|
||||||
<template #header="{ entity }">
|
<template #header="{ entity }">
|
||||||
<div>{{ entity.id }} - {{ entity.code }}</div>
|
<div>{{ entity.code }}</div>
|
||||||
|
</template>
|
||||||
|
<template #menu="{ entity }">
|
||||||
|
<ShelvingDescriptorMenu
|
||||||
|
:shelving="entity"
|
||||||
|
@on-remove="$refs.summary.fetch()"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #body="{ entity }">
|
<template #body="{ entity }">
|
||||||
<QCard class="vn-one">
|
<QCard class="vn-one">
|
||||||
|
|
|
@ -96,7 +96,6 @@ function toTicketUrl(section) {
|
||||||
ref="summaryRef"
|
ref="summaryRef"
|
||||||
:url="`Tickets/${entityId}/summary`"
|
:url="`Tickets/${entityId}/summary`"
|
||||||
data-key="TicketSummary"
|
data-key="TicketSummary"
|
||||||
data-cy="ticketSummary"
|
|
||||||
>
|
>
|
||||||
<template #header-left>
|
<template #header-left>
|
||||||
<VnToSummary
|
<VnToSummary
|
||||||
|
@ -114,7 +113,7 @@ function toTicketUrl(section) {
|
||||||
{{ entity.nickname }}
|
{{ entity.nickname }}
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #header-right="{ entity }">
|
<template #header-right>
|
||||||
<div>
|
<div>
|
||||||
<QBtnDropdown
|
<QBtnDropdown
|
||||||
ref="stateBtnDropdownRef"
|
ref="stateBtnDropdownRef"
|
||||||
|
@ -133,18 +132,11 @@ function toTicketUrl(section) {
|
||||||
@update:model-value="changeState"
|
@update:model-value="changeState"
|
||||||
/>
|
/>
|
||||||
</QBtnDropdown>
|
</QBtnDropdown>
|
||||||
<QBtn color="white" dense flat icon="more_vert" round size="md">
|
|
||||||
<QTooltip>
|
|
||||||
{{ t('components.cardDescriptor.moreOptions') }}
|
|
||||||
</QTooltip>
|
|
||||||
<QMenu>
|
|
||||||
<QList>
|
|
||||||
<TicketDescriptorMenu :ticket="entity" />
|
|
||||||
</QList>
|
|
||||||
</QMenu>
|
|
||||||
</QBtn>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
<template #menu="{ entity }">
|
||||||
|
<TicketDescriptorMenu :ticket="entity" />
|
||||||
|
</template>
|
||||||
<template #body="{ entity }">
|
<template #body="{ entity }">
|
||||||
<QCard class="vn-one">
|
<QCard class="vn-one">
|
||||||
<VnTitle
|
<VnTitle
|
||||||
|
@ -258,7 +250,7 @@ function toTicketUrl(section) {
|
||||||
<QCard class="vn-one" v-if="entity.notes.length">
|
<QCard class="vn-one" v-if="entity.notes.length">
|
||||||
<VnTitle
|
<VnTitle
|
||||||
:url="toTicketUrl('observation')"
|
:url="toTicketUrl('observation')"
|
||||||
:text="t('globals.pageTitles.notes')"
|
:text="t('ticket.pageTitles.notes')"
|
||||||
/>
|
/>
|
||||||
<QVirtualScroll
|
<QVirtualScroll
|
||||||
:items="entity.notes"
|
:items="entity.notes"
|
||||||
|
|
|
@ -11,6 +11,7 @@ import FetchData from 'src/components/FetchData.vue';
|
||||||
import VnRow from 'components/ui/VnRow.vue';
|
import VnRow from 'components/ui/VnRow.vue';
|
||||||
import { toDate, toCurrency } from 'src/filters';
|
import { toDate, toCurrency } from 'src/filters';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
import TravelDescriptorMenuItems from './TravelDescriptorMenuItems.vue';
|
||||||
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
id: {
|
id: {
|
||||||
|
@ -242,7 +243,9 @@ const getLink = (param) => `#/travel/${entityId.value}/${param}`;
|
||||||
<template #header>
|
<template #header>
|
||||||
<span>{{ travel.id }} - {{ travel.ref }}</span>
|
<span>{{ travel.id }} - {{ travel.ref }}</span>
|
||||||
</template>
|
</template>
|
||||||
|
<template #menu="{ entity }">
|
||||||
|
<TravelDescriptorMenuItems :travel="entity" />
|
||||||
|
</template>
|
||||||
<template #body>
|
<template #body>
|
||||||
<QCard class="vn-one">
|
<QCard class="vn-one">
|
||||||
<QCardSection class="q-pa-none">
|
<QCardSection class="q-pa-none">
|
||||||
|
|
|
@ -6,11 +6,10 @@ import CardDescriptor from 'src/components/ui/CardDescriptor.vue';
|
||||||
import VnLv from 'src/components/ui/VnLv.vue';
|
import VnLv from 'src/components/ui/VnLv.vue';
|
||||||
import VnLinkPhone from 'src/components/ui/VnLinkPhone.vue';
|
import VnLinkPhone from 'src/components/ui/VnLinkPhone.vue';
|
||||||
import VnChangePassword from 'src/components/common/VnChangePassword.vue';
|
import VnChangePassword from 'src/components/common/VnChangePassword.vue';
|
||||||
import { useState } from 'src/composables/useState';
|
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import VnImg from 'src/components/ui/VnImg.vue';
|
import VnImg from 'src/components/ui/VnImg.vue';
|
||||||
import EditPictureForm from 'components/EditPictureForm.vue';
|
import EditPictureForm from 'components/EditPictureForm.vue';
|
||||||
import DepartmentDescriptorProxy from 'src/pages/Department/Card/DepartmentDescriptorProxy.vue';
|
import WorkerDescriptorMenu from './WorkerDescriptorMenu.vue';
|
||||||
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
id: {
|
id: {
|
||||||
|
@ -28,8 +27,6 @@ const image = ref(null);
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const state = useState();
|
|
||||||
const user = state.getUser();
|
|
||||||
const showEditPhotoForm = ref(false);
|
const showEditPhotoForm = ref(false);
|
||||||
const toggleEditPictureForm = () => {
|
const toggleEditPictureForm = () => {
|
||||||
showEditPhotoForm.value = !showEditPhotoForm.value;
|
showEditPhotoForm.value = !showEditPhotoForm.value;
|
||||||
|
@ -45,18 +42,6 @@ const getIsExcluded = async () => {
|
||||||
workerExcluded.value = data.exists;
|
workerExcluded.value = data.exists;
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleExcluded = async () => {
|
|
||||||
if (workerExcluded.value)
|
|
||||||
await axios.delete(`WorkerDisableExcludeds/${entityId.value}`);
|
|
||||||
else
|
|
||||||
await axios.post(`WorkerDisableExcludeds`, {
|
|
||||||
workerFk: entityId.value,
|
|
||||||
dated: new Date(),
|
|
||||||
});
|
|
||||||
|
|
||||||
workerExcluded.value = !workerExcluded.value;
|
|
||||||
};
|
|
||||||
|
|
||||||
const handlePhotoUpdated = (evt = false) => {
|
const handlePhotoUpdated = (evt = false) => {
|
||||||
image.value.reload(evt);
|
image.value.reload(evt);
|
||||||
};
|
};
|
||||||
|
@ -72,25 +57,11 @@ const handlePhotoUpdated = (evt = false) => {
|
||||||
@on-fetch="getIsExcluded"
|
@on-fetch="getIsExcluded"
|
||||||
>
|
>
|
||||||
<template #menu="{ entity }">
|
<template #menu="{ entity }">
|
||||||
<QItem v-ripple clickable @click="handleExcluded">
|
<WorkerDescriptorMenu
|
||||||
<QItemSection>
|
:worker="entity"
|
||||||
{{
|
:is-excluded="workerExcluded"
|
||||||
workerExcluded
|
@show-dialog="$refs.changePassRef.show"
|
||||||
? t('Click to allow the user to be disabled')
|
/>
|
||||||
: t('Click to exclude the user from getting disabled')
|
|
||||||
}}
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
<QItem
|
|
||||||
v-if="!entity.user.emailVerified && user.id != entity.id"
|
|
||||||
v-ripple
|
|
||||||
clickable
|
|
||||||
@click="$refs.changePassRef.show"
|
|
||||||
>
|
|
||||||
<QItemSection>
|
|
||||||
{{ t('globals.changePass') }}
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
</template>
|
</template>
|
||||||
<template #before>
|
<template #before>
|
||||||
<div class="relative-position">
|
<div class="relative-position">
|
||||||
|
@ -144,14 +115,10 @@ const handlePhotoUpdated = (evt = false) => {
|
||||||
:value="entity.user?.emailUser?.email"
|
:value="entity.user?.emailUser?.email"
|
||||||
copy
|
copy
|
||||||
/>
|
/>
|
||||||
<VnLv :label="t('worker.list.department')">
|
<VnLv
|
||||||
<template #value>
|
:label="t('worker.list.department')"
|
||||||
<span class="link" v-text="entity.department?.department?.name" />
|
:value="entity.department ? entity.department.department.name : null"
|
||||||
<DepartmentDescriptorProxy
|
/>
|
||||||
:id="entity.department?.department?.id"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</VnLv>
|
|
||||||
<VnLv :value="entity.phone">
|
<VnLv :value="entity.phone">
|
||||||
<template #label>
|
<template #label>
|
||||||
{{ t('globals.phone') }}
|
{{ t('globals.phone') }}
|
||||||
|
@ -211,8 +178,6 @@ const handlePhotoUpdated = (evt = false) => {
|
||||||
|
|
||||||
<i18n>
|
<i18n>
|
||||||
es:
|
es:
|
||||||
Go to client: Ir a cliente
|
|
||||||
Go to user: Ir al usuario
|
|
||||||
Click to allow the user to be disabled: Marcar para deshabilitar
|
Click to allow the user to be disabled: Marcar para deshabilitar
|
||||||
Click to exclude the user from getting disabled: Marcar para no deshabilitar
|
Click to exclude the user from getting disabled: Marcar para no deshabilitar
|
||||||
</i18n>
|
</i18n>
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
<script setup>
|
||||||
|
import { computed, ref, toRefs } from 'vue';
|
||||||
|
import axios from 'axios';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { useState } from 'src/composables/useState';
|
||||||
|
|
||||||
|
const $props = defineProps({
|
||||||
|
worker: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
isExcluded: {
|
||||||
|
type: Boolean,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const route = useRoute();
|
||||||
|
const { t } = useI18n();
|
||||||
|
const state = useState();
|
||||||
|
const user = state.getUser();
|
||||||
|
const { worker } = toRefs($props);
|
||||||
|
const workerExcluded = ref($props.isExcluded);
|
||||||
|
const entityId = computed(() => {
|
||||||
|
return $props.worker.id || route.params.id;
|
||||||
|
});
|
||||||
|
const emit = defineEmits(['show-dialog']);
|
||||||
|
const handleExcluded = async () => {
|
||||||
|
if (workerExcluded.value)
|
||||||
|
await axios.delete(`WorkerDisableExcludeds/${entityId.value}`);
|
||||||
|
else
|
||||||
|
await axios.post(`WorkerDisableExcludeds`, {
|
||||||
|
workerFk: entityId.value,
|
||||||
|
dated: new Date(),
|
||||||
|
});
|
||||||
|
|
||||||
|
workerExcluded.value = !workerExcluded.value;
|
||||||
|
};
|
||||||
|
|
||||||
|
const showChangePasswordDialog = () => {
|
||||||
|
emit('show-dialog', true);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<QItem v-ripple clickable @click="handleExcluded">
|
||||||
|
<QItemSection>
|
||||||
|
{{
|
||||||
|
workerExcluded
|
||||||
|
? t('Click to allow the user to be disabled')
|
||||||
|
: t('Click to exclude the user from getting disabled')
|
||||||
|
}}
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
<QItem
|
||||||
|
v-if="!worker.user.emailVerified && user.id == worker.id"
|
||||||
|
v-ripple
|
||||||
|
clickable
|
||||||
|
@click="showChangePasswordDialog"
|
||||||
|
>
|
||||||
|
<QItemSection>
|
||||||
|
{{ t('globals.changePass') }}
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
</template>
|
|
@ -1,68 +1,28 @@
|
||||||
|
src/pages/Worker/Card/WorkerPBX.vue
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { watch, ref } from 'vue';
|
|
||||||
import { useI18n } from 'vue-i18n';
|
|
||||||
import { useRoute } from 'vue-router';
|
|
||||||
|
|
||||||
import { useState } from 'src/composables/useState';
|
|
||||||
|
|
||||||
import FormModel from 'src/components/FormModel.vue';
|
import FormModel from 'src/components/FormModel.vue';
|
||||||
import VnRow from 'components/ui/VnRow.vue';
|
|
||||||
import VnInput from 'src/components/common/VnInput.vue';
|
import VnInput from 'src/components/common/VnInput.vue';
|
||||||
|
|
||||||
const { t } = useI18n();
|
|
||||||
const state = useState();
|
|
||||||
const route = useRoute();
|
|
||||||
const workerPBXForm = ref();
|
|
||||||
const extension = ref(null);
|
|
||||||
|
|
||||||
const filter = {
|
|
||||||
include: [
|
|
||||||
{
|
|
||||||
relation: 'sip',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => route.params.id,
|
|
||||||
() => state.set('extension', null)
|
|
||||||
);
|
|
||||||
|
|
||||||
const onFetch = (data) => {
|
|
||||||
state.set('extension', data?.sip?.extension);
|
|
||||||
extension.value = state.get('extension');
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateModelValue = (data) => {
|
|
||||||
state.set('extension', data);
|
|
||||||
workerPBXForm.value.hasChanges = true;
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<FormModel
|
<FormModel
|
||||||
ref="workerPBXForm"
|
model="WorkerPbx"
|
||||||
:filter="filter"
|
:url="`Workers/${$route.params.id}/sip`"
|
||||||
:url="`Workers/${route.params.id}`"
|
|
||||||
url-update="Sips"
|
url-update="Sips"
|
||||||
auto-load
|
|
||||||
:mapper="
|
:mapper="
|
||||||
() => ({
|
({ userFk, extension }) => ({
|
||||||
userFk: +route.params.id,
|
userFk,
|
||||||
extension,
|
extension,
|
||||||
})
|
})
|
||||||
"
|
"
|
||||||
model="DeviceProductionUser"
|
auto-load
|
||||||
@on-fetch="onFetch"
|
|
||||||
>
|
>
|
||||||
<template #form="{}">
|
<template #form="{ data }">
|
||||||
<VnRow>
|
<VnInput
|
||||||
<VnInput
|
:label="$t('worker.summary.sipExtension')"
|
||||||
:label="t('worker.summary.sipExtension')"
|
v-model="data.extension"
|
||||||
v-model="extension"
|
/>
|
||||||
@update:model-value="updateModelValue"
|
|
||||||
/>
|
|
||||||
</VnRow>
|
|
||||||
</template>
|
</template>
|
||||||
</FormModel>
|
</FormModel>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -11,6 +11,7 @@ import VnTitle from 'src/components/common/VnTitle.vue';
|
||||||
import RoleDescriptorProxy from 'src/pages/Account/Role/Card/RoleDescriptorProxy.vue';
|
import RoleDescriptorProxy from 'src/pages/Account/Role/Card/RoleDescriptorProxy.vue';
|
||||||
import DepartmentDescriptorProxy from 'src/pages/Department/Card/DepartmentDescriptorProxy.vue';
|
import DepartmentDescriptorProxy from 'src/pages/Department/Card/DepartmentDescriptorProxy.vue';
|
||||||
import { useAdvancedSummary } from 'src/composables/useAdvancedSummary';
|
import { useAdvancedSummary } from 'src/composables/useAdvancedSummary';
|
||||||
|
import WorkerDescriptorMenu from './WorkerDescriptorMenu.vue';
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
@ -42,6 +43,9 @@ onBeforeMount(async () => {
|
||||||
<template #header="{ entity }">
|
<template #header="{ entity }">
|
||||||
<div>{{ entity.id }} - {{ entity.firstName }} {{ entity.lastName }}</div>
|
<div>{{ entity.id }} - {{ entity.firstName }} {{ entity.lastName }}</div>
|
||||||
</template>
|
</template>
|
||||||
|
<template #menu="{ entity }">
|
||||||
|
<WorkerDescriptorMenu :worker="entity" :is-excluded="workerExcluded" />
|
||||||
|
</template>
|
||||||
<template #body="{ entity: worker }">
|
<template #body="{ entity: worker }">
|
||||||
<QCard class="vn-one">
|
<QCard class="vn-one">
|
||||||
<VnTitle :url="basicDataUrl" :text="t('globals.summary.basicData')" />
|
<VnTitle :url="basicDataUrl" :text="t('globals.summary.basicData')" />
|
||||||
|
|
|
@ -100,6 +100,16 @@ const agencyOptions = ref([]);
|
||||||
required="true"
|
required="true"
|
||||||
clearable
|
clearable
|
||||||
/>
|
/>
|
||||||
|
<VnInput
|
||||||
|
v-model="data.priceOptimum"
|
||||||
|
:label="t('Price optimum')"
|
||||||
|
type="number"
|
||||||
|
min="0"
|
||||||
|
required="true"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
</VnRow>
|
||||||
|
<VnRow>
|
||||||
<VnInput
|
<VnInput
|
||||||
v-model="data.bonus"
|
v-model="data.bonus"
|
||||||
:label="t('Bonus')"
|
:label="t('Bonus')"
|
||||||
|
@ -107,8 +117,6 @@ const agencyOptions = ref([]);
|
||||||
min="0"
|
min="0"
|
||||||
clearable
|
clearable
|
||||||
/>
|
/>
|
||||||
</VnRow>
|
|
||||||
<VnRow>
|
|
||||||
<VnSelect
|
<VnSelect
|
||||||
:label="t('Distribution point')"
|
:label="t('Distribution point')"
|
||||||
v-model="data.addressFk"
|
v-model="data.addressFk"
|
||||||
|
@ -152,6 +160,7 @@ es:
|
||||||
Traveling days: Dias de viaje
|
Traveling days: Dias de viaje
|
||||||
Closing: Cierre
|
Closing: Cierre
|
||||||
Price: Precio
|
Price: Precio
|
||||||
|
Price optimum: Precio óptimo
|
||||||
Bonus: Bonificación
|
Bonus: Bonificación
|
||||||
Inflation: Inflación
|
Inflation: Inflación
|
||||||
Volumetric: Volumétrico
|
Volumetric: Volumétrico
|
||||||
|
|
|
@ -182,13 +182,19 @@ onMounted(() => {
|
||||||
min="0"
|
min="0"
|
||||||
/>
|
/>
|
||||||
<VnInput
|
<VnInput
|
||||||
v-model="eventInclusionFormData.bonus"
|
v-model="eventInclusionFormData.priceOptimum"
|
||||||
:label="t('zone.bonus')"
|
:label="t('list.priceOptimum')"
|
||||||
type="number"
|
type="number"
|
||||||
min="0"
|
min="0"
|
||||||
/>
|
/>
|
||||||
</VnRow>
|
</VnRow>
|
||||||
<VnRow>
|
<VnRow>
|
||||||
|
<VnInput
|
||||||
|
v-model="eventInclusionFormData.bonus"
|
||||||
|
:label="t('zone.bonus')"
|
||||||
|
type="number"
|
||||||
|
min="0"
|
||||||
|
/>
|
||||||
<VnInput
|
<VnInput
|
||||||
v-model="eventInclusionFormData.m3Max"
|
v-model="eventInclusionFormData.m3Max"
|
||||||
:label="t('zone.m3Max')"
|
:label="t('zone.m3Max')"
|
||||||
|
|
|
@ -11,6 +11,7 @@ import { getUrl } from 'src/composables/getUrl';
|
||||||
import { toCurrency } from 'filters/index';
|
import { toCurrency } from 'filters/index';
|
||||||
import { toTimeFormat } from 'src/filters/date';
|
import { toTimeFormat } from 'src/filters/date';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
import ZoneDescriptorMenuItems from './ZoneDescriptorMenuItems.vue';
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
@ -79,6 +80,9 @@ onMounted(async () => {
|
||||||
<template #header="{ entity }">
|
<template #header="{ entity }">
|
||||||
<div>#{{ entity.id }} - {{ entity.name }}</div>
|
<div>#{{ entity.id }} - {{ entity.name }}</div>
|
||||||
</template>
|
</template>
|
||||||
|
<template #menu="{ entity }">
|
||||||
|
<ZoneDescriptorMenuItems :zone="entity" />
|
||||||
|
</template>
|
||||||
<template #body="{ entity: zone }">
|
<template #body="{ entity: zone }">
|
||||||
<QCard class="vn-one">
|
<QCard class="vn-one">
|
||||||
<VnTitle :url="zoneUrl + `basic-data`" :text="t('summary.basicData')" />
|
<VnTitle :url="zoneUrl + `basic-data`" :text="t('summary.basicData')" />
|
||||||
|
|
|
@ -22,6 +22,7 @@ list:
|
||||||
agency: Agencia
|
agency: Agencia
|
||||||
close: Cierre
|
close: Cierre
|
||||||
price: Precio
|
price: Precio
|
||||||
|
priceOptimum: Precio óptimo
|
||||||
create: Crear zona
|
create: Crear zona
|
||||||
openSummary: Detalles
|
openSummary: Detalles
|
||||||
searchZone: Buscar zonas
|
searchZone: Buscar zonas
|
||||||
|
|
|
@ -1,19 +1,12 @@
|
||||||
import { RouterView } from 'vue-router';
|
import { RouterView } from 'vue-router';
|
||||||
|
|
||||||
export default {
|
const claimCard = {
|
||||||
name: 'Claim',
|
name: 'ClaimCard',
|
||||||
path: '/claim',
|
path: ':id',
|
||||||
|
component: () => import('src/pages/Claim/Card/ClaimCard.vue'),
|
||||||
|
redirect: { name: 'ClaimSummary' },
|
||||||
meta: {
|
meta: {
|
||||||
title: 'claims',
|
menu: [
|
||||||
icon: 'vn:claims',
|
|
||||||
moduleName: 'Claim',
|
|
||||||
keyBinding: 'r',
|
|
||||||
},
|
|
||||||
component: RouterView,
|
|
||||||
redirect: { name: 'ClaimMain' },
|
|
||||||
menus: {
|
|
||||||
main: ['ClaimList'],
|
|
||||||
card: [
|
|
||||||
'ClaimBasicData',
|
'ClaimBasicData',
|
||||||
'ClaimLines',
|
'ClaimLines',
|
||||||
'ClaimPhotos',
|
'ClaimPhotos',
|
||||||
|
@ -23,109 +16,125 @@ export default {
|
||||||
'ClaimLog',
|
'ClaimLog',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'summary',
|
||||||
|
name: 'ClaimSummary',
|
||||||
|
meta: {
|
||||||
|
title: 'summary',
|
||||||
|
icon: 'launch',
|
||||||
|
},
|
||||||
|
component: () => import('src/pages/Claim/Card/ClaimSummary.vue'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'basic-data',
|
||||||
|
name: 'ClaimBasicData',
|
||||||
|
meta: {
|
||||||
|
title: 'basicData',
|
||||||
|
icon: 'vn:settings',
|
||||||
|
acls: [{ model: 'Claim', props: 'findById', accessType: 'READ' }],
|
||||||
|
},
|
||||||
|
component: () => import('src/pages/Claim/Card/ClaimBasicData.vue'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'lines',
|
||||||
|
name: 'ClaimLines',
|
||||||
|
meta: {
|
||||||
|
title: 'lines',
|
||||||
|
icon: 'vn:details',
|
||||||
|
},
|
||||||
|
component: () => import('src/pages/Claim/Card/ClaimLines.vue'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'photos',
|
||||||
|
name: 'ClaimPhotos',
|
||||||
|
meta: {
|
||||||
|
title: 'photos',
|
||||||
|
icon: 'image',
|
||||||
|
},
|
||||||
|
component: () => import('src/pages/Claim/Card/ClaimPhoto.vue'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'notes',
|
||||||
|
name: 'ClaimNotes',
|
||||||
|
meta: {
|
||||||
|
title: 'notes',
|
||||||
|
icon: 'draft',
|
||||||
|
},
|
||||||
|
component: () => import('src/pages/Claim/Card/ClaimNotes.vue'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'development',
|
||||||
|
name: 'ClaimDevelopment',
|
||||||
|
meta: {
|
||||||
|
title: 'development',
|
||||||
|
icon: 'vn:traceability',
|
||||||
|
acls: [
|
||||||
|
{
|
||||||
|
model: 'ClaimDevelopment',
|
||||||
|
props: '*',
|
||||||
|
accessType: 'WRITE',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
component: () => import('src/pages/Claim/Card/ClaimDevelopment.vue'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'action',
|
||||||
|
name: 'ClaimAction',
|
||||||
|
meta: {
|
||||||
|
title: 'action',
|
||||||
|
icon: 'vn:actions',
|
||||||
|
},
|
||||||
|
component: () => import('src/pages/Claim/Card/ClaimAction.vue'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'log',
|
||||||
|
name: 'ClaimLog',
|
||||||
|
meta: {
|
||||||
|
title: 'log',
|
||||||
|
icon: 'history',
|
||||||
|
},
|
||||||
|
component: () => import('src/pages/Claim/Card/ClaimLog.vue'),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Claim',
|
||||||
|
path: '/claim',
|
||||||
|
meta: {
|
||||||
|
title: 'claims',
|
||||||
|
icon: 'vn:claims',
|
||||||
|
moduleName: 'Claim',
|
||||||
|
keyBinding: 'r',
|
||||||
|
menu: ['ClaimList'],
|
||||||
|
},
|
||||||
|
component: RouterView,
|
||||||
|
redirect: { name: 'ClaimMain' },
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
name: 'ClaimMain',
|
name: 'ClaimMain',
|
||||||
path: '',
|
path: '',
|
||||||
component: () => import('src/components/common/VnModule.vue'),
|
component: () => import('src/components/common/VnModule.vue'),
|
||||||
redirect: { name: 'ClaimList' },
|
redirect: { name: 'ClaimIndexMain' },
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
name: 'ClaimList',
|
path: '',
|
||||||
path: 'list',
|
name: 'ClaimIndexMain',
|
||||||
meta: {
|
redirect: { name: 'ClaimList' },
|
||||||
title: 'list',
|
|
||||||
icon: 'view_list',
|
|
||||||
},
|
|
||||||
component: () => import('src/pages/Claim/ClaimList.vue'),
|
component: () => import('src/pages/Claim/ClaimList.vue'),
|
||||||
},
|
children: [
|
||||||
],
|
{
|
||||||
},
|
name: 'ClaimList',
|
||||||
{
|
path: 'list',
|
||||||
name: 'ClaimCard',
|
meta: {
|
||||||
path: ':id',
|
title: 'list',
|
||||||
component: () => import('src/pages/Claim/Card/ClaimCard.vue'),
|
icon: 'view_list',
|
||||||
redirect: { name: 'ClaimSummary' },
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
name: 'ClaimSummary',
|
|
||||||
path: 'summary',
|
|
||||||
meta: {
|
|
||||||
title: 'summary',
|
|
||||||
icon: 'launch',
|
|
||||||
},
|
|
||||||
component: () => import('src/pages/Claim/Card/ClaimSummary.vue'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'ClaimBasicData',
|
|
||||||
path: 'basic-data',
|
|
||||||
meta: {
|
|
||||||
title: 'basicData',
|
|
||||||
icon: 'vn:settings',
|
|
||||||
acls: [{ model: 'Claim', props: 'findById', accessType: 'READ' }],
|
|
||||||
},
|
|
||||||
component: () => import('src/pages/Claim/Card/ClaimBasicData.vue'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'ClaimLines',
|
|
||||||
path: 'lines',
|
|
||||||
meta: {
|
|
||||||
title: 'lines',
|
|
||||||
icon: 'vn:details',
|
|
||||||
},
|
|
||||||
component: () => import('src/pages/Claim/Card/ClaimLines.vue'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'ClaimPhotos',
|
|
||||||
path: 'photos',
|
|
||||||
meta: {
|
|
||||||
title: 'photos',
|
|
||||||
icon: 'image',
|
|
||||||
},
|
|
||||||
component: () => import('src/pages/Claim/Card/ClaimPhoto.vue'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'ClaimNotes',
|
|
||||||
path: 'notes',
|
|
||||||
meta: {
|
|
||||||
title: 'notes',
|
|
||||||
icon: 'draft',
|
|
||||||
},
|
|
||||||
component: () => import('src/pages/Claim/Card/ClaimNotes.vue'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'ClaimDevelopment',
|
|
||||||
path: 'development',
|
|
||||||
meta: {
|
|
||||||
title: 'development',
|
|
||||||
icon: 'vn:traceability',
|
|
||||||
acls: [
|
|
||||||
{
|
|
||||||
model: 'ClaimDevelopment',
|
|
||||||
props: '*',
|
|
||||||
accessType: 'WRITE',
|
|
||||||
},
|
},
|
||||||
],
|
},
|
||||||
},
|
claimCard,
|
||||||
component: () => import('src/pages/Claim/Card/ClaimDevelopment.vue'),
|
],
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'ClaimAction',
|
|
||||||
path: 'action',
|
|
||||||
meta: {
|
|
||||||
title: 'action',
|
|
||||||
icon: 'vn:actions',
|
|
||||||
},
|
|
||||||
component: () => import('src/pages/Claim/Card/ClaimAction.vue'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'ClaimLog',
|
|
||||||
path: 'log',
|
|
||||||
meta: {
|
|
||||||
title: 'log',
|
|
||||||
icon: 'history',
|
|
||||||
},
|
|
||||||
component: () => import('src/pages/Claim/Card/ClaimLog.vue'),
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,50 +1,123 @@
|
||||||
import { RouterView } from 'vue-router';
|
import { RouterView } from 'vue-router';
|
||||||
|
|
||||||
|
const entryCard = {
|
||||||
|
name: 'EntryCard',
|
||||||
|
path: ':id',
|
||||||
|
component: () => import('src/pages/Entry/Card/EntryCard.vue'),
|
||||||
|
redirect: { name: 'EntrySummary' },
|
||||||
|
meta: {
|
||||||
|
menu: [
|
||||||
|
'EntryBasicData',
|
||||||
|
'EntryBuys',
|
||||||
|
'EntryNotes',
|
||||||
|
'EntryDms',
|
||||||
|
'EntryLog',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'summary',
|
||||||
|
name: 'EntrySummary',
|
||||||
|
meta: {
|
||||||
|
title: 'summary',
|
||||||
|
icon: 'launch',
|
||||||
|
},
|
||||||
|
component: () => import('src/pages/Entry/Card/EntrySummary.vue'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'basic-data',
|
||||||
|
name: 'EntryBasicData',
|
||||||
|
meta: {
|
||||||
|
title: 'basicData',
|
||||||
|
icon: 'vn:settings',
|
||||||
|
},
|
||||||
|
component: () => import('src/pages/Entry/Card/EntryBasicData.vue'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'buys',
|
||||||
|
name: 'EntryBuys',
|
||||||
|
meta: {
|
||||||
|
title: 'buys',
|
||||||
|
icon: 'vn:lines',
|
||||||
|
},
|
||||||
|
component: () => import('src/pages/Entry/Card/EntryBuys.vue'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'buys/import',
|
||||||
|
name: 'EntryBuysImport',
|
||||||
|
component: () => import('src/pages/Entry/Card/EntryBuysImport.vue'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'notes',
|
||||||
|
name: 'EntryNotes',
|
||||||
|
meta: {
|
||||||
|
title: 'notes',
|
||||||
|
icon: 'vn:notes',
|
||||||
|
},
|
||||||
|
component: () => import('src/pages/Entry/Card/EntryNotes.vue'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'dms',
|
||||||
|
name: 'EntryDms',
|
||||||
|
meta: {
|
||||||
|
title: 'dms',
|
||||||
|
icon: 'smb_share',
|
||||||
|
},
|
||||||
|
component: () => import('src/pages/Entry/Card/EntryDms.vue'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'log',
|
||||||
|
name: 'EntryLog',
|
||||||
|
meta: {
|
||||||
|
title: 'log',
|
||||||
|
icon: 'vn:History',
|
||||||
|
},
|
||||||
|
component: () => import('src/pages/Entry/Card/EntryLog.vue'),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
path: '/entry',
|
|
||||||
name: 'Entry',
|
name: 'Entry',
|
||||||
|
path: '/entry',
|
||||||
meta: {
|
meta: {
|
||||||
title: 'entries',
|
title: 'entries',
|
||||||
icon: 'vn:entry',
|
icon: 'vn:entry',
|
||||||
moduleName: 'Entry',
|
moduleName: 'Entry',
|
||||||
keyBinding: 'e',
|
keyBinding: 'e',
|
||||||
},
|
menu: [
|
||||||
component: RouterView,
|
|
||||||
redirect: { name: 'EntryMain' },
|
|
||||||
menus: {
|
|
||||||
main: [
|
|
||||||
'EntryList',
|
'EntryList',
|
||||||
'MyEntries',
|
'MyEntries',
|
||||||
'EntryLatestBuys',
|
'EntryLatestBuys',
|
||||||
'EntryStockBought',
|
'EntryStockBought',
|
||||||
'EntryWasteRecalc',
|
'EntryWasteRecalc',
|
||||||
],
|
]
|
||||||
card: ['EntryBasicData', 'EntryBuys', 'EntryNotes', 'EntryDms', 'EntryLog'],
|
|
||||||
},
|
},
|
||||||
|
component: RouterView,
|
||||||
|
redirect: { name: 'EntryMain' },
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: '',
|
|
||||||
name: 'EntryMain',
|
name: 'EntryMain',
|
||||||
|
path: '',
|
||||||
component: () => import('src/components/common/VnModule.vue'),
|
component: () => import('src/components/common/VnModule.vue'),
|
||||||
redirect: { name: 'EntryList' },
|
redirect: { name: 'EntryIndexMain' },
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'list',
|
path:'',
|
||||||
name: 'EntryList',
|
name: 'EntryIndexMain',
|
||||||
meta: {
|
redirect: { name: 'EntryList' },
|
||||||
title: 'list',
|
|
||||||
icon: 'view_list',
|
|
||||||
},
|
|
||||||
component: () => import('src/pages/Entry/EntryList.vue'),
|
component: () => import('src/pages/Entry/EntryList.vue'),
|
||||||
},
|
children: [
|
||||||
{
|
{
|
||||||
path: 'my',
|
name: 'EntryList',
|
||||||
name: 'MyEntries',
|
path: 'list',
|
||||||
meta: {
|
meta: {
|
||||||
title: 'labeler',
|
title: 'list',
|
||||||
icon: 'sell',
|
icon: 'view_list',
|
||||||
},
|
},
|
||||||
component: () => import('src/pages/Entry/MyEntries.vue'),
|
},
|
||||||
|
entryCard,
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'create',
|
path: 'create',
|
||||||
|
@ -54,6 +127,15 @@ export default {
|
||||||
icon: 'add',
|
icon: 'add',
|
||||||
},
|
},
|
||||||
component: () => import('src/pages/Entry/EntryCreate.vue'),
|
component: () => import('src/pages/Entry/EntryCreate.vue'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'my',
|
||||||
|
name: 'MyEntries',
|
||||||
|
meta: {
|
||||||
|
title: 'labeler',
|
||||||
|
icon: 'sell',
|
||||||
|
},
|
||||||
|
component: () => import('src/pages/Entry/MyEntries.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'latest-buys',
|
path: 'latest-buys',
|
||||||
|
@ -84,72 +166,5 @@ export default {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: 'EntryCard',
|
|
||||||
path: ':id',
|
|
||||||
component: () => import('src/pages/Entry/Card/EntryCard.vue'),
|
|
||||||
redirect: { name: 'EntrySummary' },
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
name: 'EntrySummary',
|
|
||||||
path: 'summary',
|
|
||||||
meta: {
|
|
||||||
title: 'summary',
|
|
||||||
icon: 'launch',
|
|
||||||
},
|
|
||||||
component: () => import('src/pages/Entry/Card/EntrySummary.vue'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'basic-data',
|
|
||||||
name: 'EntryBasicData',
|
|
||||||
meta: {
|
|
||||||
title: 'basicData',
|
|
||||||
icon: 'vn:settings',
|
|
||||||
},
|
|
||||||
component: () => import('src/pages/Entry/Card/EntryBasicData.vue'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'buys',
|
|
||||||
name: 'EntryBuys',
|
|
||||||
meta: {
|
|
||||||
title: 'buys',
|
|
||||||
icon: 'vn:lines',
|
|
||||||
},
|
|
||||||
component: () => import('src/pages/Entry/Card/EntryBuys.vue'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'buys/import',
|
|
||||||
name: 'EntryBuysImport',
|
|
||||||
component: () => import('src/pages/Entry/Card/EntryBuysImport.vue'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'notes',
|
|
||||||
name: 'EntryNotes',
|
|
||||||
meta: {
|
|
||||||
title: 'notes',
|
|
||||||
icon: 'vn:notes',
|
|
||||||
},
|
|
||||||
component: () => import('src/pages/Entry/Card/EntryNotes.vue'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'dms',
|
|
||||||
name: 'EntryDms',
|
|
||||||
meta: {
|
|
||||||
title: 'dms',
|
|
||||||
icon: 'smb_share',
|
|
||||||
},
|
|
||||||
component: () => import('src/pages/Entry/Card/EntryDms.vue'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'log',
|
|
||||||
name: 'EntryLog',
|
|
||||||
meta: {
|
|
||||||
title: 'log',
|
|
||||||
icon: 'vn:History',
|
|
||||||
},
|
|
||||||
component: () => import('src/pages/Entry/Card/EntryLog.vue'),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
};
|
};
|
|
@ -1,35 +1,102 @@
|
||||||
import { RouterView } from 'vue-router';
|
import { RouterView } from 'vue-router';
|
||||||
|
|
||||||
|
const orderCard = {
|
||||||
|
name: 'OrderCard',
|
||||||
|
path: ':id',
|
||||||
|
component: () => import('src/pages/Order/Card/OrderCard.vue'),
|
||||||
|
redirect: { name: 'OrderSummary' },
|
||||||
|
meta: {
|
||||||
|
menu: [
|
||||||
|
'OrderBasicData',
|
||||||
|
'OrderCatalog',
|
||||||
|
'OrderVolume',
|
||||||
|
'OrderLines',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'summary',
|
||||||
|
name: 'OrderSummary',
|
||||||
|
meta: {
|
||||||
|
title: 'summary',
|
||||||
|
icon: 'launch',
|
||||||
|
},
|
||||||
|
component: () => import('src/pages/Order/Card/OrderSummary.vue'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'basic-data',
|
||||||
|
name: 'OrderBasicData',
|
||||||
|
meta: {
|
||||||
|
title: 'basicData',
|
||||||
|
icon: 'vn:settings',
|
||||||
|
},
|
||||||
|
component: () => import('src/pages/Order/Card/OrderBasicData.vue'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'catalog',
|
||||||
|
name: 'OrderCatalog',
|
||||||
|
meta: {
|
||||||
|
title: 'catalog',
|
||||||
|
icon: 'vn:basket',
|
||||||
|
},
|
||||||
|
component: () => import('src/pages/Order/Card/OrderCatalog.vue'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'volume',
|
||||||
|
name: 'OrderVolume',
|
||||||
|
meta: {
|
||||||
|
title: 'volume',
|
||||||
|
icon: 'vn:volume',
|
||||||
|
},
|
||||||
|
component: () => import('src/pages/Order/Card/OrderVolume.vue'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'line',
|
||||||
|
name: 'OrderLines',
|
||||||
|
meta: {
|
||||||
|
title: 'lines',
|
||||||
|
icon: 'vn:lines',
|
||||||
|
},
|
||||||
|
component: () => import('src/pages/Order/Card/OrderLines.vue'),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
path: '/order',
|
|
||||||
name: 'Order',
|
name: 'Order',
|
||||||
|
path: '/order',
|
||||||
meta: {
|
meta: {
|
||||||
title: 'order',
|
title: 'order',
|
||||||
icon: 'vn:basket',
|
icon: 'vn:basket',
|
||||||
moduleName: 'Order',
|
moduleName: 'Order',
|
||||||
keyBinding: 'o',
|
keyBinding: 'o',
|
||||||
|
menu: ['OrderList'],
|
||||||
},
|
},
|
||||||
component: RouterView,
|
component: RouterView,
|
||||||
redirect: { name: 'OrderMain' },
|
redirect: { name: 'OrderMain' },
|
||||||
menus: {
|
|
||||||
main: ['OrderList'],
|
|
||||||
card: ['OrderBasicData', 'OrderCatalog', 'OrderVolume', 'OrderLines'],
|
|
||||||
},
|
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: '',
|
|
||||||
name: 'OrderMain',
|
name: 'OrderMain',
|
||||||
|
path: '',
|
||||||
component: () => import('src/components/common/VnModule.vue'),
|
component: () => import('src/components/common/VnModule.vue'),
|
||||||
redirect: { name: 'OrderList' },
|
redirect: { name: 'OrderIndexMain' },
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'list',
|
path: '',
|
||||||
name: 'OrderList',
|
name: 'OrderIndexMain',
|
||||||
meta: {
|
redirect: { name: 'OrderList' },
|
||||||
title: 'orderList',
|
|
||||||
icon: 'view_list',
|
|
||||||
},
|
|
||||||
component: () => import('src/pages/Order/OrderList.vue'),
|
component: () => import('src/pages/Order/OrderList.vue'),
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: 'OrderList',
|
||||||
|
path: 'list',
|
||||||
|
meta: {
|
||||||
|
title: 'orderList',
|
||||||
|
icon: 'view_list',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
orderCard,
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'create',
|
path: 'create',
|
||||||
|
@ -42,58 +109,5 @@ export default {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: 'OrderCard',
|
|
||||||
path: ':id',
|
|
||||||
component: () => import('src/pages/Order/Card/OrderCard.vue'),
|
|
||||||
redirect: { name: 'OrderSummary' },
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
name: 'OrderSummary',
|
|
||||||
path: 'summary',
|
|
||||||
meta: {
|
|
||||||
title: 'summary',
|
|
||||||
icon: 'launch',
|
|
||||||
},
|
|
||||||
component: () => import('src/pages/Order/Card/OrderSummary.vue'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'OrderBasicData',
|
|
||||||
path: 'basic-data',
|
|
||||||
meta: {
|
|
||||||
title: 'basicData',
|
|
||||||
icon: 'vn:settings',
|
|
||||||
},
|
|
||||||
component: () => import('src/pages/Order/Card/OrderBasicData.vue'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'OrderCatalog',
|
|
||||||
path: 'catalog',
|
|
||||||
meta: {
|
|
||||||
title: 'catalog',
|
|
||||||
icon: 'vn:basket',
|
|
||||||
},
|
|
||||||
component: () => import('src/pages/Order/Card/OrderCatalog.vue'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'OrderVolume',
|
|
||||||
path: 'volume',
|
|
||||||
meta: {
|
|
||||||
title: 'volume',
|
|
||||||
icon: 'vn:volume',
|
|
||||||
},
|
|
||||||
component: () => import('src/pages/Order/Card/OrderVolume.vue'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'OrderLines',
|
|
||||||
path: 'line',
|
|
||||||
meta: {
|
|
||||||
title: 'lines',
|
|
||||||
icon: 'vn:lines',
|
|
||||||
},
|
|
||||||
component: () => import('src/pages/Order/Card/OrderLines.vue'),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
};
|
};
|
|
@ -7,10 +7,16 @@ import useNotify from 'src/composables/useNotify.js';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
|
||||||
const { notify } = useNotify();
|
const { notify } = useNotify();
|
||||||
|
const initInvoicing = {
|
||||||
|
invoicing: false,
|
||||||
|
nRequests: 0,
|
||||||
|
nPdfs: 0,
|
||||||
|
totalPdfs: 0,
|
||||||
|
addressIndex: 0,
|
||||||
|
errors: [],
|
||||||
|
};
|
||||||
export const useInvoiceOutGlobalStore = defineStore({
|
export const useInvoiceOutGlobalStore = defineStore({
|
||||||
id: 'invoiceOutGlobal',
|
id: 'invoiceOutGlobal',
|
||||||
|
|
||||||
state: () => ({
|
state: () => ({
|
||||||
initialDataLoading: true,
|
initialDataLoading: true,
|
||||||
formInitialData: {
|
formInitialData: {
|
||||||
|
@ -24,15 +30,11 @@ export const useInvoiceOutGlobalStore = defineStore({
|
||||||
addresses: [],
|
addresses: [],
|
||||||
minInvoicingDate: null,
|
minInvoicingDate: null,
|
||||||
parallelism: null,
|
parallelism: null,
|
||||||
invoicing: false,
|
|
||||||
isInvoicing: false,
|
|
||||||
status: null,
|
status: null,
|
||||||
addressIndex: 0,
|
|
||||||
errors: [],
|
|
||||||
printer: null,
|
printer: null,
|
||||||
nRequests: 0,
|
formData: null,
|
||||||
nPdfs: 0,
|
...initInvoicing,
|
||||||
totalPdfs: 0,
|
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
async init() {
|
async init() {
|
||||||
|
@ -93,8 +95,6 @@ export const useInvoiceOutGlobalStore = defineStore({
|
||||||
},
|
},
|
||||||
|
|
||||||
async makeInvoice(formData, clientsToInvoice) {
|
async makeInvoice(formData, clientsToInvoice) {
|
||||||
this.invoicing = true;
|
|
||||||
const promises = [];
|
|
||||||
try {
|
try {
|
||||||
this.printer = formData.printer;
|
this.printer = formData.printer;
|
||||||
const params = {
|
const params = {
|
||||||
|
@ -119,11 +119,13 @@ export const useInvoiceOutGlobalStore = defineStore({
|
||||||
);
|
);
|
||||||
throw new Error("There aren't addresses to invoice");
|
throw new Error("There aren't addresses to invoice");
|
||||||
}
|
}
|
||||||
|
this.formData = formData;
|
||||||
this.status = 'invoicing';
|
this.status = 'invoicing';
|
||||||
for (let index = 0; index < this.parallelism; index++) {
|
//reset data
|
||||||
promises.push(this.invoiceClient(formData, index));
|
for (const key in initInvoicing) {
|
||||||
|
this[key] = initInvoicing[key];
|
||||||
}
|
}
|
||||||
await Promise.all(promises);
|
this.invoiceClient();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.handleError(err);
|
this.handleError(err);
|
||||||
}
|
}
|
||||||
|
@ -182,45 +184,43 @@ export const useInvoiceOutGlobalStore = defineStore({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
async invoiceClient(formData, index) {
|
async invoiceClient() {
|
||||||
const address = this.addresses[index];
|
if (this.invoicing || this.nRequests >= this.parallelism) return;
|
||||||
|
const address = this.addresses[this.addressIndex];
|
||||||
if (!address || !this.status || this.status == 'stopping') {
|
if (!address || !this.status || this.status == 'stopping') {
|
||||||
this.status = 'stopping';
|
this.status = 'stopping';
|
||||||
this.invoicing = false;
|
this.invoicing = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
this.invoicing = true;
|
||||||
|
this.nRequests++;
|
||||||
const params = {
|
const params = {
|
||||||
clientId: address.clientId,
|
clientId: address.clientId,
|
||||||
addressId: address.id,
|
addressId: address.id,
|
||||||
invoiceDate: new Date(formData.invoiceDate),
|
invoiceDate: new Date(this.formData.invoiceDate),
|
||||||
maxShipped: new Date(formData.maxShipped),
|
maxShipped: new Date(this.formData.maxShipped),
|
||||||
companyFk: formData.companyFk,
|
companyFk: this.formData.companyFk,
|
||||||
serialType: formData.serialType,
|
serialType: this.formData.serialType,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.invoicing = true;
|
|
||||||
|
|
||||||
const { data } = await axios.post('InvoiceOuts/invoiceClient', params);
|
const { data } = await axios.post('InvoiceOuts/invoiceClient', params);
|
||||||
|
if (data) this.makePdfAndNotify(data, address);
|
||||||
if (data) await this.makePdfAndNotify(data, address);
|
|
||||||
this.isInvoicing = false;
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err?.response?.status >= 400 && err?.response?.status < 500) {
|
if (err?.response?.status >= 400 && err?.response?.status < 500) {
|
||||||
this.invoiceClientError(address, err.response?.data?.error?.message);
|
this.invoiceClientError(address, err.response?.data?.error?.message);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
this.invoicing = false;
|
|
||||||
notify(
|
notify(
|
||||||
'invoiceOut.globalInvoices.errors.criticalInvoiceError',
|
'invoiceOut.globalInvoices.errors.criticalInvoiceError',
|
||||||
'negative'
|
'negative'
|
||||||
);
|
);
|
||||||
throw new Error('Critical invoicing error, process stopped');
|
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
|
this.invoicing = false;
|
||||||
|
this.nRequests--;
|
||||||
this.addressIndex++;
|
this.addressIndex++;
|
||||||
if (this.status != 'stopping')
|
this.invoiceClient();
|
||||||
await this.invoiceClient(formData, this.addressIndex);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -231,9 +231,11 @@ export const useInvoiceOutGlobalStore = defineStore({
|
||||||
const params = { printerFk: this.printer };
|
const params = { printerFk: this.printer };
|
||||||
await axios.post(`InvoiceOuts/${invoiceId}/makePdfAndNotify`, params);
|
await axios.post(`InvoiceOuts/${invoiceId}/makePdfAndNotify`, params);
|
||||||
this.nPdfs++;
|
this.nPdfs++;
|
||||||
this.nRequests--;
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.invoiceClientError(client, err.response?.data?.error?.message, true);
|
this.invoiceClientError(client, err.response?.data?.error?.message, true);
|
||||||
|
} finally {
|
||||||
|
this.nRequests--;
|
||||||
|
this.invoiceClient();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/// <reference types="cypress" />
|
/// <reference types="cypress" />
|
||||||
|
|
||||||
describe('InvoiceInCorrective', () => {
|
describe('InvoiceInCorrective', () => {
|
||||||
const createRectificative = '.q-menu > .q-list > :nth-child(6) > .q-item__section';
|
const createCorrective = '.q-menu > .q-list > :nth-child(6) > .q-item__section';
|
||||||
const rectificativeSection = '.q-drawer-container .q-list > a:nth-child(6)';
|
const rectificativeSection = '.q-drawer-container .q-list > a:nth-child(6)';
|
||||||
const saveDialog = '.q-card > .q-card__actions > .q-btn--standard ';
|
const saveDialog = '.q-card > .q-card__actions > .q-btn--standard ';
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ describe('InvoiceInCorrective', () => {
|
||||||
|
|
||||||
cy.openActionsDescriptor();
|
cy.openActionsDescriptor();
|
||||||
|
|
||||||
cy.get(createRectificative).click();
|
cy.get(createCorrective).click();
|
||||||
cy.get(saveDialog).click();
|
cy.get(saveDialog).click();
|
||||||
cy.wait('@corrective').then((interception) => {
|
cy.wait('@corrective').then((interception) => {
|
||||||
const correctingId = interception.response.body;
|
const correctingId = interception.response.body;
|
||||||
|
|
Loading…
Reference in New Issue