#8225 use VnMoreOptions #1194

Merged
jon merged 11 commits from 8225-UseSameMoreOptions into dev 2025-01-13 09:17:18 +00:00
45 changed files with 596 additions and 467 deletions

View File

@ -44,7 +44,7 @@ const onDataSaved = (data) => {
<FormModelPopup
url-create="Items/regularize"
model="Items"
:title="t('Regularize stock')"
:title="t('item.regularizeStock')"
:form-initial-data="regularizeFormData"
@on-data-saved="onDataSaved($event)"
>

View File

@ -6,6 +6,7 @@ import { useArrayData } from 'composables/useArrayData';
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
import { useState } from 'src/composables/useState';
import { useRoute } from 'vue-router';
import VnMoreOptions from './VnMoreOptions.vue';
const $props = defineProps({
url: {
@ -47,7 +48,6 @@ let store;
let entity;
const isLoading = ref(false);
const isSameDataKey = computed(() => $props.dataKey === route.meta.moduleName);
const menuRef = ref();
defineExpose({ getData });
onBeforeMount(async () => {
@ -159,25 +159,11 @@ const toModule = computed(() =>
</QTooltip>
</QBtn>
</RouterLink>
<QBtn
v-if="$slots.menu"
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" :entity="entity" :menu-ref="menuRef" />
</QList>
</QMenu>
</QBtn>
<VnMoreOptions v-if="$slots.menu">
<template #menu="{ menuRef }">
<slot name="menu" :entity="entity" :menu-ref="menuRef" />
</template>
</VnMoreOptions>
</div>
<slot name="before" />
<div class="body q-py-sm">
@ -222,8 +208,8 @@ const toModule = computed(() =>
/>
</template>
<style lang="scss" scoped>
:deep(.body) {
<style lang="scss">
.body {
background-color: var(--vn-section-color);
.text-h5 {
font-size: 20px;
@ -262,7 +248,9 @@ const toModule = computed(() =>
}
}
}
</style>
<style lang="scss" scoped>
.title {
overflow: hidden;
text-overflow: ellipsis;

View File

@ -1,10 +1,11 @@
<script setup>
import { ref, computed, watch, onBeforeMount, onMounted } from 'vue';
import { ref, computed, watch, onBeforeMount } from 'vue';
import { useRoute } from 'vue-router';
import SkeletonSummary from 'components/ui/SkeletonSummary.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import { useArrayData } from 'src/composables/useArrayData';
import { isDialogOpened } from 'src/filters';
import { useStateStore } from 'src/stores/useStateStore';
import VnMoreOptions from './VnMoreOptions.vue';
const props = defineProps({
url: {
@ -40,7 +41,6 @@ const { store } = arrayData;
const entity = computed(() => (Array.isArray(store.data) ? store.data[0] : store.data));
const isLoading = ref(false);
const stateStore = useStateStore();
defineExpose({
entity,
fetch,
@ -52,9 +52,6 @@ onBeforeMount(async () => {
watch(props, async () => await fetch());
});
onMounted(() => {
stateStore.rightDrawerChangeValue(false);
});
async function fetch() {
store.url = props.url;
store.filter = props.filter ?? {};
@ -64,6 +61,7 @@ async function fetch() {
isLoading.value = false;
}
</script>
<template>
<div class="summary container">
<QCard class="cardSummary">
@ -84,11 +82,16 @@ async function fetch() {
<span v-else></span>
</slot>
<slot name="header" :entity="entity" dense>
{{ entity.id + ' - ' + entity.name }}
</slot>
<slot name="header-right" :entity="entity">
<span></span>
<VnLv :label="`${entity.id} -`" :value="entity.name" />
</slot>
<span class="row no-wrap">
<slot name="header-right" :entity="entity" />
<VnMoreOptions v-if="$slots.menu && isDialogOpened()">
<template #menu="{ menuRef }">
<slot name="menu" :entity="entity" :menu-ref="menuRef" />
</template>
</VnMoreOptions>
</span>
</div>
<div class="summaryBody row q-mb-md">
<slot name="body" :entity="entity" />
@ -97,6 +100,7 @@ async function fetch() {
</QCard>
</div>
</template>
<style lang="scss">
.summary.container {
display: flex;

View File

@ -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>

View File

@ -0,0 +1,6 @@
import axios from 'axios';
export default async (id) => {
const { data } = await axios.get(`Accounts/${id}/exists`);
return data.exists;
};

View File

@ -1,13 +1,13 @@
<script setup>
import { ref, computed } from 'vue';
import { ref, computed, onMounted } from 'vue';
import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import useCardDescription from 'src/composables/useCardDescription';
import AccountDescriptorMenu from './AccountDescriptorMenu.vue';
import FetchData from 'src/components/FetchData.vue';
import VnImg from 'src/components/ui/VnImg.vue';
import useHasAccount from 'src/composables/useHasAccount.js';
const $props = defineProps({
id: {
@ -23,6 +23,7 @@ const entityId = computed(() => {
return $props.id || route.params.id;
});
const data = ref(useCardDescription());
const hasAccount = ref();
const setData = (entity) => (data.value = useCardDescription(entity.nickname, entity.id));
const filter = {
@ -30,18 +31,16 @@ const filter = {
fields: ['id', 'nickname', 'name', 'role'],
include: { relation: 'role', scope: { fields: ['id', 'name'] } },
};
const hasAccount = ref(false);
onMounted(async () => {
hasAccount.value = await useHasAccount(entityId.value);
});
</script>
<template>
<FetchData
:url="`Accounts/${entityId}/exists`"
auto-load
@on-fetch="(data) => (hasAccount = data.exists)"
/>
<CardDescriptor
ref="descriptor"
url="VnUsers/preview"
:url="`VnUsers/preview`"
:filter="filter"
module="Account"
@on-fetch="setData"
@ -50,7 +49,7 @@ const hasAccount = ref(false);
:subtitle="data.subtitle"
>
<template #menu>
<AccountDescriptorMenu :has-account="hasAccount" />
<AccountDescriptorMenu :entity-id="entityId" />
</template>
<template #before>
<VnImg :id="entityId" collection="user" resolution="520x520" class="photo">
jon marked this conversation as resolved Outdated

esto?

esto?
@ -74,7 +73,7 @@ const hasAccount = ref(false);
<VnLv :label="t('account.card.nickname')" :value="entity.name" />
<VnLv :label="t('account.card.role')" :value="entity.role.name" />
</template>
<template #icons="{ entity }">
<template #actions="{ entity }">
<QCardActions class="q-gutter-x-md">
<QIcon
v-if="!entity.active"
@ -82,7 +81,7 @@ const hasAccount = ref(false);
name="vn:disabled"
flat
round
size="xs"
size="sm"
class="fill-icon"
>
<QTooltip>{{ t('account.card.deactivated') }}</QTooltip>
@ -93,7 +92,7 @@ const hasAccount = ref(false);
v-if="hasAccount"
flat
round
size="xs"
size="sm"
class="fill-icon"
>
<QTooltip>{{ t('account.card.enabled') }}</QTooltip>

View File

@ -1,37 +1,37 @@
<script setup>
import axios from 'axios';
import { computed, ref, toRefs } from 'vue';
import { computed, onMounted, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import { useVnConfirm } from 'composables/useVnConfirm';
import { useRoute } from 'vue-router';
import { useAcl } from 'src/composables/useAcl';
import { useArrayData } from 'src/composables/useArrayData';
import VnConfirm from 'src/components/ui/VnConfirm.vue';
import VnChangePassword from 'src/components/common/VnChangePassword.vue';
import { useQuasar } from 'quasar';
import useNotify from 'src/composables/useNotify.js';
import useHasAccount from 'src/composables/useHasAccount.js';
import VnInputPassword from 'src/components/common/VnInputPassword.vue';
const $props = defineProps({
hasAccount: {
type: Boolean,
default: false,
entityId: {
type: Number,
required: true,
},
});
const { t } = useI18n();
const { hasAccount } = toRefs($props);
const { openConfirmationModal } = useVnConfirm();
const route = useRoute();
const { notify } = useQuasar();
const { notify } = useNotify();
const account = computed(() => useArrayData('AccountId').store.data[0]);
account.value.hasAccount = hasAccount.value;
const entityId = computed(() => +route.params.id);
onMounted(async () => {
account.value.hasAccount = await useHasAccount($props.entityId);
});
async function updateStatusAccount(active) {
if (active) {
await axios.post(`Accounts`, { id: entityId.value });
await axios.post(`Accounts`, { id: $props.entityId });
} else {
await axios.delete(`Accounts/${entityId.value}`);
await axios.delete(`Accounts/${$props.entityId}`);
}
account.value.hasAccount = active;
@ -42,7 +42,7 @@ async function updateStatusAccount(active) {
});
}
async function updateStatusUser(active) {
await axios.patch(`VnUsers/${entityId.value}`, { active });
await axios.patch(`VnUsers/${$props.entityId}`, { active });
account.value.active = active;
const status = active ? 'activate' : 'deactivate';
notify({
@ -105,6 +105,7 @@ async function sync() {
class="full-width"
clearable
clear-icon="close"
type="password"
/>
</template>
</VnConfirm>

View File

@ -9,6 +9,7 @@ import AccountMailAliasCreateForm from './AccountMailAliasCreateForm.vue';
import { useVnConfirm } from 'composables/useVnConfirm';
import { useArrayData } from 'composables/useArrayData';
import useNotify from 'src/composables/useNotify.js';
import useHasAccount from 'src/composables/useHasAccount.js';
import axios from 'axios';
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) => {
await axios.delete(`${urlPath}/${row.id}`);
fetchMailAliases();
@ -79,7 +70,7 @@ const fetchMailAliases = async () => {
const getAccountData = async (reload = true) => {
loading.value = true;
hasAccount.value = await fetchAccountExistence();
hasAccount.value = await useHasAccount(route.params.id);
if (!hasAccount.value) {
loading.value = false;
store.data = [];

View File

@ -9,6 +9,7 @@ import VnRow from 'components/ui/VnRow.vue';
import axios from 'axios';
import { useStateStore } from 'stores/useStateStore';
import useNotify from 'src/composables/useNotify.js';
import useHasAccount from 'src/composables/useHasAccount';
const { t } = useI18n();
const route = useRoute();
@ -30,23 +31,9 @@ const hasDataChanged = computed(
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 () => {
try {
const response = await axios.get(`MailForwards/${route.params.id}`);
return response.data;
} catch {
return null;
}
const response = await axios.get(`MailForwards/${route.params.id}`);
return response.data;
};
const deleteMailForward = async () => {
@ -72,7 +59,7 @@ const setInitialData = async () => {
loading.value = true;
initialData.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) {
loading.value = false;
return;

View File

@ -7,6 +7,7 @@ import CardSummary from 'components/ui/CardSummary.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import { useArrayData } from 'src/composables/useArrayData';
import AccountDescriptorMenu from './AccountDescriptorMenu.vue';
const route = useRoute();
const { t } = useI18n();
@ -31,12 +32,14 @@ const filter = {
<template>
<CardSummary
data-key="AccountId"
ref="AccountSummary"
url="VnUsers/preview"
:filter="filter"
@on-fetch="(data) => (account = data)"
>
<template #header>{{ account.id }} - {{ account.nickname }}</template>
<template #menu="">
<AccountDescriptorMenu :entity-id="entityId" />
</template>
<template #body>
<QCard class="vn-one">
<QCardSection class="q-pa-none">

View File

@ -19,6 +19,7 @@ import ClaimNotes from 'src/pages/Claim/Card/ClaimNotes.vue';
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
import CustomerDescriptorProxy from 'src/pages/Customer/Card/CustomerDescriptorProxy.vue';
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
import ClaimDescriptorMenu from './ClaimDescriptorMenu.vue';
const route = useRoute();
const router = useRouter();
@ -228,6 +229,9 @@ function claimUrl(section) {
</QList>
</QBtnDropdown>
</template>
<template #menu="{ entity }">
<ClaimDescriptorMenu :claim="entity.claim" />
</template>
<template #body="{ entity: { claim, salesClaimed, developments } }">
<QCard class="vn-one" v-if="$route.name != 'ClaimSummary'">
<VnTitle

View File

@ -12,6 +12,7 @@ import VnLinkMail from 'src/components/ui/VnLinkMail.vue';
import CustomerSummaryTable from 'src/pages/Customer/components/CustomerSummaryTable.vue';
import VnTitle from 'src/components/common/VnTitle.vue';
import VnRow from 'src/components/ui/VnRow.vue';
import CustomerDescriptorMenu from './CustomerDescriptorMenu.vue';
const route = useRoute();
const { t } = useI18n();
const grafanaUrl = 'https://grafana.verdnatura.es';
@ -70,6 +71,9 @@ const sumRisk = ({ clientRisks }) => {
data-key="CustomerSummary"
module-name="Customer"
>
<template #menu="{ entity }">
<CustomerDescriptorMenu :customer="entity" />
</template>
<template #body="{ entity }">
<QCard class="vn-one">
<VnTitle
@ -94,14 +98,13 @@ const sumRisk = ({ clientRisks }) => {
:phone-number="entity.mobile"
:channel="entity.country?.saySimpleCountry?.channel"
class="q-ml-xs"
:country="entity.country?.code"
/>
</template>
</VnLv>
<VnLv :value="entity.email" copy
><template #label>
{{ t('globals.params.email') }}
<VnLinkMail :email="entity.email"></VnLinkMail> </template
<VnLinkMail email="entity.email"></VnLinkMail> </template
></VnLv>
<VnLv
:label="t('customer.summary.salesPerson')"
@ -173,7 +176,7 @@ const sumRisk = ({ clientRisks }) => {
:label="t('customer.summary.notifyByEmail')"
:value="entity.isToBeMailed"
/>
<VnLv :label="t('globals.isVies')" :value="entity.isVies" />
<VnLv :label="t('customer.summary.vies')" :value="entity.isVies" />
</VnRow>
</QCard>
<QCard class="vn-one">

View File

@ -7,9 +7,9 @@ import CardDescriptor from 'components/ui/CardDescriptor.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import { toDate } from 'src/filters';
import { usePrintService } from 'composables/usePrintService';
import { getUrl } from 'src/composables/getUrl';
import filter from './EntryFilter.js';
import EntryDescriptorMenu from './EntryDescriptorMenu.vue';
const $props = defineProps({
id: {
@ -21,7 +21,6 @@ const $props = defineProps({
const route = useRoute();
const { t } = useI18n();
const { openReport } = usePrintService();
const entryDescriptorRef = ref(null);
const url = ref();
@ -52,10 +51,6 @@ const getEntryRedirectionFilter = (entry) => {
to,
});
};
const showEntryReport = () => {
openReport(`Entries/${route.params.id}/entry-order-pdf`);
};
</script>
<template>
@ -68,14 +63,12 @@ const showEntryReport = () => {
data-key="Entry"
>
<template #menu="{ entity }">
<QItem v-ripple clickable @click="showEntryReport(entity)">
<QItemSection>{{ t('Show entry report') }}</QItemSection>
</QItem>
<EntryDescriptorMenu :id="entity.id" />
</template>
<template #body="{ entity }">
<VnLv :label="t('globals.agency')" :value="entity.travel?.agency?.name" />
<VnLv :label="t('globals.shipped')" :value="toDate(entity.travel?.shipped)" />
<VnLv :label="t('globals.landed')" :value="toDate(entity.travel?.landed)" />
<VnLv :label="t('shipped')" :value="toDate(entity.travel?.shipped)" />
<VnLv :label="t('landed')" :value="toDate(entity.travel?.landed)" />
<VnLv
:label="t('globals.warehouseOut')"
:value="entity.travel?.warehouseOut?.name"
@ -154,7 +147,6 @@ es:
Supplier card: Ficha del proveedor
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
Show entry report: Ver informe del pedido
Go to module index: Ir al índice del modulo
Inventory entry: Es inventario
Virtual entry: Es una redada

View File

@ -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>

View File

@ -12,6 +12,7 @@ import { getUrl } from 'src/composables/getUrl';
import axios from 'axios';
import FetchedTags from 'src/components/ui/FetchedTags.vue';
import VnToSummary from 'src/components/ui/VnToSummary.vue';
import EntryDescriptorMenu from './EntryDescriptorMenu.vue';
import VnRow from 'src/components/ui/VnRow.vue';
import VnTitle from 'src/components/common/VnTitle.vue';
@ -172,6 +173,9 @@ const fetchEntryBuys = async () => {
<template #header>
<span>{{ entry.id }} - {{ entry.supplier.nickname }}</span>
</template>
<template #menu="{ entity }">
<EntryDescriptorMenu :id="entity.id" />
</template>
<template #body>
<QCard class="vn-one">
<VnTitle
@ -207,7 +211,10 @@ const fetchEntryBuys = async () => {
:label="t('entry.summary.travelAgency')"
: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
:label="t('globals.warehouseOut')"
:value="entry.travel.warehouseOut?.name"

View File

@ -243,7 +243,6 @@ const columns = computed(() => [
<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

View File

@ -1,6 +1,7 @@
entryList:
list:
inventoryEntry: Inventory entry
showEntryReport: Show entry report
entryFilter:
filter:
search: General search

View File

@ -4,6 +4,7 @@ You can search by entry reference: Puedes buscar por referencia de la entrada
entryList:
list:
inventoryEntry: Es inventario
showEntryReport: Ver informe del pedido
entryFilter:
filter:
search: Búsqueda general

View File

@ -1,60 +1,30 @@
<script setup>
import { ref, reactive, computed, onBeforeMount, capitalize } from 'vue';
import { ref, reactive, computed, onBeforeMount } from 'vue';
import { useRouter, onBeforeRouteUpdate } from 'vue-router';
import { useI18n } from 'vue-i18n';
import { useQuasar } from 'quasar';
import axios from 'axios';
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 CardDescriptor from 'components/ui/CardDescriptor.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 { useCapitalize } from 'src/composables/useCapitalize';
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 { push, currentRoute } = useRouter();
const quasar = useQuasar();
const { hasAny } = useAcl();
const { t } = useI18n();
const { openReport, sendEmail } = usePrintService();
const arrayData = useArrayData();
const invoiceIn = computed(() => arrayData.store.data);
const cardDescriptorRef = ref();
const correctionDialogRef = ref();
const entityId = computed(() => $props.id || +currentRoute.value.params.id);
const totalAmount = ref();
const currentAction = ref();
const config = ref();
const cplusRectificationTypes = ref([]);
const siiTypeInvoiceIns = ref([]);
jon marked this conversation as resolved Outdated

si el archivo es invoiceIn es extraño aquí un out

si el archivo es invoiceIn es extraño aquí un out
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 = {
include: [
{
@ -90,7 +60,7 @@ const routes = reactive({
return {
name: 'InvoiceInList',
query: {
table: JSON.stringify({ supplierFk: id }),
params: JSON.stringify({ supplierFk: id }),
},
};
},
@ -99,7 +69,7 @@ const routes = reactive({
return {
name: 'InvoiceInList',
query: {
table: JSON.stringify({ correctedFk: entityId.value }),
params: JSON.stringify({ correctedFk: entityId.value }),
},
};
}
@ -118,21 +88,21 @@ const routes = reactive({
const correctionFormData = reactive({
invoiceReason: 2,
invoiceType: 2,
invoiceClass: 8,
invoiceClass: 6,
});
const isNotFilled = computed(() => Object.values(correctionFormData).includes(null));
onBeforeMount(async () => {
await setInvoiceCorrection(entityId.value);
const { data } = await axios.get(`InvoiceIns/${entityId.value}/getTotals`);
totalAmount.value = data.totalTaxableBase;
totalAmount.value = data.totalDueDay;
});
onBeforeRouteUpdate(async (to, from) => {
if (to.params.id !== from.params.id) {
await setInvoiceCorrection(to.params.id);
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 { data: correctingId } = await axios.post(
'InvoiceIns/corrective',
@ -262,7 +144,7 @@ const createInvoiceInCorrection = async () => {
auto-load
/>
<FetchData
url="siiTypeInvoiceIns"
url="SiiTypeInvoiceIns"
jon marked this conversation as resolved Outdated

es correcto el outs?

es correcto el outs?
:where="{ code: { like: 'R%' } }"
@on-fetch="(data) => (siiTypeInvoiceIns = data)"
auto-load
@ -281,87 +163,13 @@ const createInvoiceInCorrection = async () => {
title="supplierRef"
>
<template #menu="{ entity }">
<InvoiceInToBook>
<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>
<InvoiceInDescriptorMenu :invoice="entity" />
</template>
<template #body="{ entity }">
<VnLv :label="t('InvoiceIn.list.issued')" :value="toDate(entity.issued)" />
<VnLv
:label="t('InvoiceIn.summary.bookedDate')"
:value="toDate(entity.booked)"
/>
<VnLv :label="t('InvoiceIn.list.amount')" :value="toCurrency(totalAmount)" />
<VnLv :label="t('InvoiceIn.list.supplier')">
<VnLv :label="t('invoiceIn.list.issued')" :value="toDate(entity.issued)" />
<VnLv :label="t('invoiceIn.summary.booked')" :value="toDate(entity.booked)" />
<VnLv :label="t('invoiceIn.list.amount')" :value="toCurrency(totalAmount)" />
<VnLv :label="t('invoiceIn.list.supplier')">
<template #value>
<span class="link">
{{ entity?.supplier?.nickname }}
@ -378,7 +186,7 @@ const createInvoiceInCorrection = async () => {
color="primary"
:to="routes.getSupplier(entity.supplierFk)"
>
<QTooltip>{{ t('InvoiceIn.list.supplier') }}</QTooltip>
<QTooltip>{{ t('invoiceIn.list.supplier') }}</QTooltip>
</QBtn>
<QBtn
size="md"
@ -394,7 +202,7 @@ const createInvoiceInCorrection = async () => {
color="primary"
:to="routes.getTickets(entity.supplierFk)"
>
<QTooltip>{{ t('InvoiceIn.descriptor.ticketList') }}</QTooltip>
<QTooltip>{{ t('invoiceOut.card.ticketList') }}</QTooltip>
</QBtn>
<QBtn
v-if="
@ -438,7 +246,7 @@ const createInvoiceInCorrection = async () => {
readonly
/>
<VnSelect
:label="`${capitalize(t('globals.class'))}`"
:label="`${useCapitalize(t('globals.class'))}`"
v-model="correctionFormData.invoiceClass"
:options="siiTypeInvoiceIns"
option-value="id"
@ -448,27 +256,15 @@ const createInvoiceInCorrection = async () => {
</QItemSection>
<QItemSection>
<VnSelect
:label="`${capitalize(t('globals.type'))}`"
:label="`${useCapitalize(t('globals.type'))}`"
v-model="correctionFormData.invoiceType"
:options="cplusRectificationTypes"
option-value="id"
option-label="description"
:required="true"
>
<template #option="{ opt }">
<QItem>
<QItemSection>
<QItemLabel
>{{ opt.code }} -
{{ opt.description }}</QItemLabel
>
</QItemSection>
</QItem>
<div></div>
</template>
</VnSelect>
/>
<VnSelect
:label="`${capitalize(t('globals.reason'))}`"
:label="`${useCapitalize(t('globals.reason'))}`"
v-model="correctionFormData.invoiceReason"
:options="invoiceCorrectionTypes"
option-value="id"
@ -512,31 +308,3 @@ const createInvoiceInCorrection = async () => {
}
}
</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 {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>

View File

@ -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 {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>

View File

@ -10,6 +10,7 @@ import VnLv from 'src/components/ui/VnLv.vue';
import SupplierDescriptorProxy from 'src/pages/Supplier/Card/SupplierDescriptorProxy.vue';
import InvoiceIntoBook from '../InvoiceInToBook.vue';
import VnTitle from 'src/components/common/VnTitle.vue';
import InvoiceInDescriptorMenu from './InvoiceInDescriptorMenu.vue';
const props = defineProps({ id: { type: [Number, String], default: 0 } });
const { t } = useI18n();
@ -200,6 +201,9 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
</template>
</InvoiceIntoBook>
</template>
<template #menu="{ entity }">
<InvoiceInDescriptorMenu :invoice="entity" />
</template>
<template #body="{ entity }">
<!--Basic Data-->
<QCard class="vn-one">

View File

@ -12,6 +12,26 @@ InvoiceIn:
amount: Amount
descriptor:
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
jon marked this conversation as resolved Outdated

createCorrective

elimina el uso de la palabra Rectificative por corrective

createCorrective elimina el uso de la palabra Rectificative por corrective
correctiveInvoice: Rectificative invoice
originalInvoice: Original invoice
entry: Entry
emailEmpty: The email can't be empty
card:
client: Client
company: Company
@ -50,4 +70,3 @@ invoicein:
params:
account: Ledger account
correctingFk: Rectificative

View File

@ -12,6 +12,26 @@ InvoiceIn:
amount: Importe
descriptor:
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:
client: Cliente
jon marked this conversation as resolved Outdated

Estás

Estás
company: Empresa
@ -47,4 +67,3 @@ invoicein:
params:
account: Cuenta contable
correctingFk: Rectificativa

View File

@ -10,6 +10,7 @@ import { getUrl } from 'src/composables/getUrl';
import TicketDescriptorProxy from 'src/pages/Ticket/Card/TicketDescriptorProxy.vue';
import CustomerDescriptorProxy from 'src/pages/Customer/Card/CustomerDescriptorProxy.vue';
import VnTitle from 'src/components/common/VnTitle.vue';
import InvoiceOutDescriptorMenu from './InvoiceOutDescriptorMenu.vue';
onMounted(async () => {
fetch();
@ -113,6 +114,9 @@ const ticketsColumns = ref([
<template #header="{ entity: { invoiceOut } }">
<div>{{ invoiceOut.ref }} - {{ invoiceOut.client?.socialName }}</div>
</template>
<template #menu="{ entity }">
<InvoiceOutDescriptorMenu :invoice-out-data="entity.invoiceOut" />
</template>
<template #body="{ entity: { invoiceOut } }">
<QCard class="vn-one">
<VnTitle :text="t('globals.pageTitles.basicData')" />

View File

@ -6,17 +6,16 @@ import { useI18n } from 'vue-i18n';
import CardDescriptor from 'src/components/ui/CardDescriptor.vue';
import VnLv from 'src/components/ui/VnLv.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 useCardDescription from 'src/composables/useCardDescription';
import axios from 'axios';
import { dashIfEmpty } from 'src/filters';
import { useArrayData } from 'src/composables/useArrayData';
import { cloneItem } from 'src/pages/Item/composables/cloneItem';
import ItemDescriptorMenu from './ItemDescriptorMenu.vue';
const $props = defineProps({
id: {
type: [Number, String],
type: Number,
required: false,
default: null,
},
@ -29,7 +28,7 @@ const $props = defineProps({
default: null,
},
saleFk: {
type: [Number, String],
type: Number,
default: null,
},
warehouseFk: {
@ -38,7 +37,6 @@ const $props = defineProps({
},
});
const { openCloneDialog } = cloneItem();
const route = useRoute();
const { t } = useI18n();
const warehouseConfig = ref(null);
@ -46,7 +44,6 @@ const entityId = computed(() => {
return $props.id || route.params.id;
});
const regularizeStockFormDialog = ref(null);
const mounted = ref();
const arrayDataStock = useArrayData('descriptorStock', {
@ -61,14 +58,14 @@ onMounted(async () => {
const data = ref(useCardDescription());
const setData = async (entity) => {
if (!entity) return;
data.value = useCardDescription(entity?.name, entity?.id);
data.value = useCardDescription(entity.name, entity.id);
await updateStock();
};
const getItemConfigs = async () => {
const { data } = await axios.get('ItemConfigs/findOne');
if (!data) return;
return (warehouseConfig.value = data.warehouseFk);
warehouseConfig.value = data.warehouseFk;
};
const updateStock = async () => {
if (!mounted.value) return;
@ -89,10 +86,6 @@ const updateStock = async () => {
if (storeData?.itemFk == entityId.value) return;
await stock.fetch({});
};
const openRegularizeStockForm = () => {
regularizeStockFormDialog.value.show();
};
</script>
<template>
@ -105,24 +98,12 @@ const openRegularizeStockForm = () => {
:url="`Items/${entityId}/getCard`"
@on-fetch="setData"
>
<template #menu="{}">
<QItem v-ripple clickable @click="openRegularizeStockForm()">
<QItemSection>
{{ t('Regularize stock') }}
<QDialog ref="regularizeStockFormDialog">
<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 #menu>
<ItemDescriptorMenu
:entity-id="entityId"
:warehouse-fk="warehouseFk"
@regularized="updateStock"
/>
</template>
<template #before>
<ItemDescriptorImage
@ -191,7 +172,6 @@ const openRegularizeStockForm = () => {
<i18n>
es:
Regularize stock: Regularizar stock
Inactive article: Artículo inactivo
</i18n>

View File

@ -131,7 +131,6 @@ const handlePhotoUpdated = (evt = false) => {
<i18n>
es:
Regularize stock: Regularizar stock
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?
warehouseText: Calculado sobre el almacén de { warehouseName }

View File

@ -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>

View File

@ -8,6 +8,7 @@ import VnLv from 'src/components/ui/VnLv.vue';
import ItemDescriptorImage from 'src/pages/Item/Card/ItemDescriptorImage.vue';
import VnUserLink from 'src/components/ui/VnUserLink.vue';
import VnTitle from 'src/components/common/VnTitle.vue';
import ItemDescriptorMenu from './ItemDescriptorMenu.vue';
const $props = defineProps({
id: {
@ -43,10 +44,13 @@ const getUrl = (id, param) => `#/Item/${id}/${param}`;
<template #header="{ entity: { item } }">
{{ item.id }} - {{ item.name }}
</template>
<template #menu>
<ItemDescriptorMenu :entity-id="entityId" :warehouse-fk="warehouseFk" />
</template>
<template #body="{ entity: { item, tags, visible, available, botanical } }">
<QCard class="vn-one photo">
<ItemDescriptorImage
:entity-id="Number(entityId)"
:entity-id="entityId"
:visible="visible"
:available="available"
:show-edit-button="false"
@ -89,7 +93,7 @@ const getUrl = (id, param) => `#/Item/${id}/${param}`;
<QCard class="vn-one">
<VnTitle
:url="getUrl(entityId, 'basic-data')"
:text="t('item.summary.basicData')"
:text="t('item.summary.otherData')"
/>
<VnLv
:label="t('item.summary.intrastatCode')"

View File

@ -152,7 +152,7 @@ const columns = computed(() => [
},
columnField: {
component: null,
}
},
},
{
label: t('item.list.category'),
@ -498,5 +498,4 @@ es:
Create Item: Crear artículo
You can search by id: Puedes buscar por id
Preview: Vista previa
Regularize stock: Regularizar stock
</i18n>

View File

@ -219,3 +219,4 @@ item:
minSalesQuantity: 'Cantidad mínima de venta'
genus: 'Genus'
specie: 'Specie'
regularizeStock: Regularize stock

View File

@ -210,6 +210,7 @@ item:
minSalesQuantity: 'Cantidad mínima de venta'
genus: 'Genus'
specie: 'Specie'
regularizeStock: Regularizar stock
buyRequest:
ticketId: 'ID Ticket'
shipped: 'F. envío'

View File

@ -9,7 +9,6 @@ import useCardDescription from 'src/composables/useCardDescription';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import FetchData from 'components/FetchData.vue';
import OrderDescriptorMenu from 'pages/Order/Card/OrderDescriptorMenu.vue';
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
const DEFAULT_ITEMS = 0;
@ -94,9 +93,6 @@ const total = ref(0);
@on-fetch="setData"
data-key="orderData"
>
<template #menu="{ entity }">
<OrderDescriptorMenu :order="entity" />
</template>
<template #body="{ entity }">
<VnLv
:label="t('globals.state')"

View File

@ -12,6 +12,7 @@ import CustomerDescriptorProxy from 'pages/Customer/Card/CustomerDescriptorProxy
import FetchedTags from 'components/ui/FetchedTags.vue';
import VnTitle from 'src/components/common/VnTitle.vue';
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
import OrderDescriptorMenu from 'pages/Order/Card/OrderDescriptorMenu.vue';
const { t } = useI18n();
const route = useRoute();
@ -91,6 +92,9 @@ async function handleConfirm() {
<QTooltip>{{ t('order.summary.confirmLines') }}</QTooltip>
</QBtn>
</template>
<template #menu="{ entity }">
<OrderDescriptorMenu :order="entity" />
</template>
<template #body="{ entity }">
<QCard class="vn-one">
<VnTitle

View File

@ -52,7 +52,7 @@ async function actualizeVolume() {
const params = { isOk: true };
await axios.post(`Routes/${routeId}/updateVolume`, params);
quasar.notify({
message: t('globals.dataUpdated'),
message: t('globals.dataSaved'),
type: 'positive',
});
}

View File

@ -12,6 +12,7 @@ import CustomerDescriptorProxy from 'pages/Customer/Card/CustomerDescriptorProxy
import TicketDescriptorProxy from 'pages/Ticket/Card/TicketDescriptorProxy.vue';
import VnLv from 'components/ui/VnLv.vue';
import VnTitle from 'src/components/common/VnTitle.vue';
import RouteDescriptorMenu from './RouteDescriptorMenu.vue';
const $props = defineProps({
id: {
@ -128,6 +129,9 @@ const ticketColumns = ref([
<template #header="{ entity }">
<span>{{ `${entity?.route.id} - ${entity?.route?.description}` }}</span>
</template>
<template #menu="{ entity }">
<RouteDescriptorMenu :route="entity.route" />
</template>
<template #body="{ entity }">
<QCard class="vn-max">
<VnTitle

View File

@ -10,6 +10,7 @@ import VnTitle from 'src/components/common/VnTitle.vue';
import CardSummary from 'components/ui/CardSummary.vue';
import SupplierDescriptorProxy from 'pages/Supplier/Card/SupplierDescriptorProxy.vue';
import VnLinkPhone from 'components/ui/VnLinkPhone.vue';
import RoadmapDescriptorMenu from './RoadmapDescriptorMenu.vue';
const $props = defineProps({
id: {
@ -86,6 +87,9 @@ const filter = {
<template #header="{ entity }">
<span>{{ `${entity?.id} - ${entity?.name}` }}</span>
</template>
<template #menu="{ entity }">
<RoadmapDescriptorMenu :route="entity" />
</template>
<template #body="{ entity }">
<QCard class="vn-one">
<VnTitle

View File

@ -4,6 +4,7 @@ import { useQuasar } from 'quasar';
import { useI18n } from 'vue-i18n';
import { useRouter } from 'vue-router';
import VnConfirm from 'components/ui/VnConfirm.vue';
import { useRoute } from 'vue-router';
const $props = defineProps({
shelving: {
@ -14,8 +15,11 @@ const $props = defineProps({
const router = useRouter();
const quasar = useQuasar();
const route = useRoute();
const { t } = useI18n();
const emit = defineEmits(['onRemove']);
function confirmRemove() {
quasar.dialog({
component: VnConfirm,
@ -32,11 +36,12 @@ async function remove() {
return;
}
await axios.delete(`Shelvings/${$props.shelving.id}`);
await router.push({ name: 'ShelvingList' });
if (route.name != 'ShelvingList') await router.push({ name: 'ShelvingList' });
quasar.notify({
message: t('globals.dataDeleted'),
type: 'positive',
});
emit('onRemove', {});
}
</script>
<template>

View File

@ -1,10 +1,11 @@
<script setup>
import { computed } from 'vue';
import { computed, ref } from 'vue';
import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import CardSummary from 'components/ui/CardSummary.vue';
import VnLv from 'components/ui/VnLv.vue';
import VnUserLink from 'components/ui/VnUserLink.vue';
import ShelvingDescriptorMenu from './ShelvingDescriptorMenu.vue';
const $props = defineProps({
id: {
@ -14,7 +15,7 @@ const $props = defineProps({
});
const route = useRoute();
const { t } = useI18n();
const summary = ref({});
const entityId = computed(() => $props.id || route.params.id);
const filter = {
@ -43,7 +44,13 @@ const filter = {
data-key="ShelvingSummary"
>
<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 #body="{ entity }">
<QCard class="vn-one">

View File

@ -96,7 +96,6 @@ function toTicketUrl(section) {
ref="summaryRef"
:url="`Tickets/${entityId}/summary`"
data-key="TicketSummary"
data-cy="ticketSummary"
>
<template #header-left>
<VnToSummary
@ -114,7 +113,7 @@ function toTicketUrl(section) {
{{ entity.nickname }}
</div>
</template>
<template #header-right="{ entity }">
<template #header-right>
<div>
<QBtnDropdown
ref="stateBtnDropdownRef"
@ -133,18 +132,11 @@ function toTicketUrl(section) {
@update:model-value="changeState"
/>
</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>
</template>
<template #menu="{ entity }">
<TicketDescriptorMenu :ticket="entity" />
</template>
<template #body="{ entity }">
<QCard class="vn-one">
<VnTitle
@ -258,7 +250,7 @@ function toTicketUrl(section) {
<QCard class="vn-one" v-if="entity.notes.length">
<VnTitle
:url="toTicketUrl('observation')"
:text="t('globals.pageTitles.notes')"
:text="t('ticket.pageTitles.notes')"
/>
<QVirtualScroll
:items="entity.notes"

View File

@ -11,6 +11,7 @@ import FetchData from 'src/components/FetchData.vue';
import VnRow from 'components/ui/VnRow.vue';
import { toDate, toCurrency } from 'src/filters';
import axios from 'axios';
import TravelDescriptorMenuItems from './TravelDescriptorMenuItems.vue';
const $props = defineProps({
id: {
@ -242,7 +243,9 @@ const getLink = (param) => `#/travel/${entityId.value}/${param}`;
<template #header>
<span>{{ travel.id }} - {{ travel.ref }}</span>
</template>
<template #menu="{ entity }">
<TravelDescriptorMenuItems :travel="entity" />
</template>
<template #body>
<QCard class="vn-one">
<QCardSection class="q-pa-none">

View File

@ -6,11 +6,10 @@ import CardDescriptor from 'src/components/ui/CardDescriptor.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import VnLinkPhone from 'src/components/ui/VnLinkPhone.vue';
import VnChangePassword from 'src/components/common/VnChangePassword.vue';
import { useState } from 'src/composables/useState';
import axios from 'axios';
import VnImg from 'src/components/ui/VnImg.vue';
import EditPictureForm from 'components/EditPictureForm.vue';
import DepartmentDescriptorProxy from 'src/pages/Department/Card/DepartmentDescriptorProxy.vue';
import WorkerDescriptorMenu from './WorkerDescriptorMenu.vue';
const $props = defineProps({
id: {
@ -28,8 +27,6 @@ const image = ref(null);
const route = useRoute();
const { t } = useI18n();
const state = useState();
const user = state.getUser();
const showEditPhotoForm = ref(false);
const toggleEditPictureForm = () => {
showEditPhotoForm.value = !showEditPhotoForm.value;
@ -45,18 +42,6 @@ const getIsExcluded = async () => {
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) => {
image.value.reload(evt);
};
@ -72,25 +57,11 @@ const handlePhotoUpdated = (evt = false) => {
@on-fetch="getIsExcluded"
>
<template #menu="{ entity }">
<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="!entity.user.emailVerified && user.id != entity.id"
v-ripple
clickable
@click="$refs.changePassRef.show"
>
<QItemSection>
{{ t('globals.changePass') }}
</QItemSection>
</QItem>
<WorkerDescriptorMenu
:worker="entity"
:is-excluded="workerExcluded"
@show-dialog="$refs.changePassRef.show"
/>
</template>
<template #before>
<div class="relative-position">
@ -144,14 +115,10 @@ const handlePhotoUpdated = (evt = false) => {
:value="entity.user?.emailUser?.email"
copy
/>
<VnLv :label="t('worker.list.department')">
<template #value>
<span class="link" v-text="entity.department?.department?.name" />
<DepartmentDescriptorProxy
:id="entity.department?.department?.id"
/>
</template>
</VnLv>
<VnLv
:label="t('worker.list.department')"
:value="entity.department ? entity.department.department.name : null"
/>
<VnLv :value="entity.phone">
<template #label>
{{ t('globals.phone') }}
@ -211,8 +178,6 @@ const handlePhotoUpdated = (evt = false) => {
<i18n>
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 exclude the user from getting disabled: Marcar para no deshabilitar
</i18n>

View File

@ -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>

View File

@ -11,6 +11,7 @@ import VnTitle from 'src/components/common/VnTitle.vue';
import RoleDescriptorProxy from 'src/pages/Account/Role/Card/RoleDescriptorProxy.vue';
import DepartmentDescriptorProxy from 'src/pages/Department/Card/DepartmentDescriptorProxy.vue';
import { useAdvancedSummary } from 'src/composables/useAdvancedSummary';
import WorkerDescriptorMenu from './WorkerDescriptorMenu.vue';
const route = useRoute();
const { t } = useI18n();
@ -42,6 +43,9 @@ onBeforeMount(async () => {
<template #header="{ entity }">
<div>{{ entity.id }} - {{ entity.firstName }} {{ entity.lastName }}</div>
</template>
<template #menu="{ entity }">
<WorkerDescriptorMenu :worker="entity" :is-excluded="workerExcluded" />
</template>
<template #body="{ entity: worker }">
<QCard class="vn-one">
<VnTitle :url="basicDataUrl" :text="t('globals.summary.basicData')" />

View File

@ -11,6 +11,7 @@ import { getUrl } from 'src/composables/getUrl';
import { toCurrency } from 'filters/index';
import { toTimeFormat } from 'src/filters/date';
import axios from 'axios';
import ZoneDescriptorMenuItems from './ZoneDescriptorMenuItems.vue';
const route = useRoute();
const { t } = useI18n();
@ -79,6 +80,9 @@ onMounted(async () => {
<template #header="{ entity }">
<div>#{{ entity.id }} - {{ entity.name }}</div>
</template>
<template #menu="{ entity }">
<ZoneDescriptorMenuItems :zone="entity" />
</template>
<template #body="{ entity: zone }">
<QCard class="vn-one">
<VnTitle :url="zoneUrl + `basic-data`" :text="t('summary.basicData')" />

View File

@ -1,7 +1,7 @@
/// <reference types="cypress" />
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 saveDialog = '.q-card > .q-card__actions > .q-btn--standard ';
@ -13,7 +13,7 @@ describe('InvoiceInCorrective', () => {
cy.openActionsDescriptor();
cy.get(createRectificative).click();
cy.get(createCorrective).click();
cy.get(saveDialog).click();
cy.wait('@corrective').then((interception) => {
const correctingId = interception.response.body;