Merge branch 'dev' into 6553-workerBusiness
gitea/salix-front/pipeline/pr-dev There was a failure building this commit
Details
gitea/salix-front/pipeline/pr-dev There was a failure building this commit
Details
This commit is contained in:
commit
962ae4ca96
|
@ -31,3 +31,7 @@ yarn-error.log*
|
||||||
# Cypress directories and files
|
# Cypress directories and files
|
||||||
/test/cypress/videos
|
/test/cypress/videos
|
||||||
/test/cypress/screenshots
|
/test/cypress/screenshots
|
||||||
|
|
||||||
|
# VitePress directories and files
|
||||||
|
/docs/.vitepress/cache
|
||||||
|
/docs/.vuepress
|
||||||
|
|
|
@ -30,9 +30,11 @@ export default defineConfig({
|
||||||
testFiles: '**/*.spec.js',
|
testFiles: '**/*.spec.js',
|
||||||
supportFile: 'test/cypress/support/unit.js',
|
supportFile: 'test/cypress/support/unit.js',
|
||||||
},
|
},
|
||||||
setupNodeEvents(on, config) {
|
setupNodeEvents: async (on, config) => {
|
||||||
import('cypress-mochawesome-reporter/plugin').then((plugin) => plugin.default(on));
|
const plugin = await import('cypress-mochawesome-reporter/plugin');
|
||||||
// implement node event listeners here
|
plugin.default(on);
|
||||||
|
|
||||||
|
return config;
|
||||||
},
|
},
|
||||||
viewportWidth: 1280,
|
viewportWidth: 1280,
|
||||||
viewportHeight: 720,
|
viewportHeight: 720,
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
import { defineConfig } from 'vitepress';
|
||||||
|
|
||||||
|
// https://vitepress.dev/reference/site-config
|
||||||
|
export default defineConfig({
|
||||||
|
title: 'Lilium',
|
||||||
|
description: 'Lilium docs',
|
||||||
|
themeConfig: {
|
||||||
|
// https://vitepress.dev/reference/default-theme-config
|
||||||
|
nav: [
|
||||||
|
{ text: 'Home', link: '/' },
|
||||||
|
{ text: 'Components', link: '/components/vnInput' },
|
||||||
|
{ text: 'Composables', link: '/composables/useArrayData' },
|
||||||
|
],
|
||||||
|
|
||||||
|
sidebar: [
|
||||||
|
{
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
text: 'Components',
|
||||||
|
collapsible: true,
|
||||||
|
collapsed: true,
|
||||||
|
items: [{ text: 'VnInput', link: '/components/vnInput' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Composables',
|
||||||
|
collapsible: true,
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{ text: 'useArrayData', link: '/composables/useArrayData' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
socialLinks: [{ icon: 'github', link: 'https://github.com/vuejs/vitepress' }],
|
||||||
|
},
|
||||||
|
});
|
|
@ -0,0 +1,136 @@
|
||||||
|
# VnInput
|
||||||
|
|
||||||
|
`VnInput` is a custom input component that provides various useful features such as validation, input clearing, and more.
|
||||||
|
|
||||||
|
## Props
|
||||||
|
|
||||||
|
### `modelValue`
|
||||||
|
|
||||||
|
- **Type:** `String | Number`
|
||||||
|
- **Default:** `null`
|
||||||
|
- **Description:** The value of the model bound to the component.
|
||||||
|
|
||||||
|
### `isOutlined`
|
||||||
|
|
||||||
|
- **Type:** `Boolean`
|
||||||
|
- **Default:** `false`
|
||||||
|
- **Description:** If `true`, the component is rendered with an outlined style.
|
||||||
|
|
||||||
|
### `info`
|
||||||
|
|
||||||
|
- **Type:** `String`
|
||||||
|
- **Default:** `''`
|
||||||
|
- **Description:** Additional information displayed alongside the component.
|
||||||
|
|
||||||
|
### `clearable`
|
||||||
|
|
||||||
|
- **Type:** `Boolean`
|
||||||
|
- **Default:** `true`
|
||||||
|
- **Description:** If `true`, the component shows a button to clear the input.
|
||||||
|
|
||||||
|
### `emptyToNull`
|
||||||
|
|
||||||
|
- **Type:** `Boolean`
|
||||||
|
- **Default:** `true`
|
||||||
|
- **Description:** If `true`, converts empty inputs to `null`.
|
||||||
|
|
||||||
|
### `insertable`
|
||||||
|
|
||||||
|
- **Type:** `Boolean`
|
||||||
|
- **Default:** `false`
|
||||||
|
- **Description:** If `true`, allows the insertion of new values.
|
||||||
|
|
||||||
|
### `maxlength`
|
||||||
|
|
||||||
|
- **Type:** `Number`
|
||||||
|
- **Default:** `null`
|
||||||
|
- **Description:** The maximum number of characters allowed in the input.
|
||||||
|
|
||||||
|
### `uppercase`
|
||||||
|
|
||||||
|
- **Type:** `Boolean`
|
||||||
|
- **Default:** `false`
|
||||||
|
- **Description:** If `true`, converts the input text to uppercase.
|
||||||
|
|
||||||
|
## Emits
|
||||||
|
|
||||||
|
### `update:modelValue`
|
||||||
|
|
||||||
|
- **Description:** Emits the updated model value.
|
||||||
|
- **Behavior:** This event is emitted whenever the input value changes. It is used to update the model value bound to the component.
|
||||||
|
|
||||||
|
### `update:options`
|
||||||
|
|
||||||
|
- **Description:** Emits the updated options.
|
||||||
|
- **Behavior:** This event is emitted when the component's options change. It is useful for components with dynamic options.
|
||||||
|
|
||||||
|
### `keyup.enter`
|
||||||
|
|
||||||
|
- **Description:** Emits an event when the Enter key is pressed.
|
||||||
|
- **Behavior:** This event is emitted whenever the Enter key is pressed while the input is focused. It can be used to handle specific actions when the input is confirmed.
|
||||||
|
|
||||||
|
### `remove`
|
||||||
|
|
||||||
|
- **Description:** Emits an event to remove the current value.
|
||||||
|
- **Behavior:** This event is emitted when the clear button (close icon) is clicked. It is used to handle the removal of the current input value.
|
||||||
|
|
||||||
|
## Functions
|
||||||
|
|
||||||
|
### `focus`
|
||||||
|
|
||||||
|
- **Description:** Focuses the input.
|
||||||
|
- **Behavior:** This function is exposed so it can be called from outside the component. It uses `vnInputRef.value.focus()` to focus the input.
|
||||||
|
|
||||||
|
### `handleKeydown`
|
||||||
|
|
||||||
|
- **Description:** Handles the `keydown` event of the input.
|
||||||
|
- **Behavior:** This function is called whenever a key is pressed while the input is focused. If the pressed key is `Backspace`, it does nothing. If `insertable` is `true` and the pressed key is a number, it calls `handleInsertMode`.
|
||||||
|
|
||||||
|
### `handleInsertMode`
|
||||||
|
|
||||||
|
- **Description:** Handles the insertion mode of values.
|
||||||
|
- **Behavior:** This function is called when `insertable` is `true` and a numeric key is pressed. It inserts the value at the cursor position and updates the input value. Then, it moves the cursor to the correct position.
|
||||||
|
|
||||||
|
### `handleUppercase`
|
||||||
|
|
||||||
|
- **Description:** Converts the input value to uppercase.
|
||||||
|
- **Behavior:** This function is called when the uppercase icon is clicked. It converts the current input value to uppercase.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<VnInput
|
||||||
|
v-model="inputValue"
|
||||||
|
:isOutlined="true"
|
||||||
|
info="Additional information"
|
||||||
|
:clearable="true"
|
||||||
|
:emptyToNull="true"
|
||||||
|
:insertable="false"
|
||||||
|
:maxlength="50"
|
||||||
|
:uppercase="true"
|
||||||
|
@update:modelValue="handleUpdate"
|
||||||
|
@keyup.enter="handleEnter"
|
||||||
|
@remove="handleRemove"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import VnInput from 'src/components/common/VnInput.vue';
|
||||||
|
|
||||||
|
const inputValue = ref('');
|
||||||
|
|
||||||
|
const handleUpdate = (value) => {
|
||||||
|
console.log('Updated value:', value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleEnter = () => {
|
||||||
|
console.log('Enter pressed');
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleRemove = () => {
|
||||||
|
console.log('Value removed');
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
```
|
|
@ -0,0 +1,215 @@
|
||||||
|
# useArrayData
|
||||||
|
|
||||||
|
`useArrayData` is a composable function that provides a set of utilities for managing array data in a Vue component. It leverages Pinia for state management and provides various methods for fetching, filtering, and manipulating data.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { useArrayData } from 'src/composables/useArrayData';
|
||||||
|
|
||||||
|
const {
|
||||||
|
fetch,
|
||||||
|
applyFilter,
|
||||||
|
addFilter,
|
||||||
|
getCurrentFilter,
|
||||||
|
setCurrentFilter,
|
||||||
|
addFilterWhere,
|
||||||
|
addOrder,
|
||||||
|
deleteOrder,
|
||||||
|
refresh,
|
||||||
|
destroy,
|
||||||
|
loadMore,
|
||||||
|
store,
|
||||||
|
totalRows,
|
||||||
|
updateStateParams,
|
||||||
|
isLoading,
|
||||||
|
deleteOption,
|
||||||
|
reset,
|
||||||
|
resetPagination,
|
||||||
|
} = useArrayData('myKey', userOptions);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Parameters
|
||||||
|
|
||||||
|
### `key`
|
||||||
|
|
||||||
|
- **Type:** `String`
|
||||||
|
- **Description:** A unique key to identify the data store.
|
||||||
|
|
||||||
|
### `userOptions`
|
||||||
|
|
||||||
|
- **Type:** `Object`
|
||||||
|
- **Description:** An object containing user-defined options for configuring the data store.
|
||||||
|
|
||||||
|
## Methods
|
||||||
|
|
||||||
|
### `fetch`
|
||||||
|
|
||||||
|
Fetches data from the server.
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
- **`options`** : An object with the following properties:
|
||||||
|
- `append` (Boolean): Whether to append the fetched data to the existing data.
|
||||||
|
- `updateRouter` (Boolean): Whether to update the router with the current filter.
|
||||||
|
|
||||||
|
#### Returns
|
||||||
|
|
||||||
|
- **`Promise`** : A promise that resolves with the fetched data.
|
||||||
|
|
||||||
|
### `applyFilter`
|
||||||
|
|
||||||
|
Applies a filter to the data.
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
- **`filter`** : An object containing the filter criteria.
|
||||||
|
- **`params`** : Additional parameters for the filter.
|
||||||
|
- **`fetchOptions`** : Options for the fetch method.
|
||||||
|
|
||||||
|
#### Returns
|
||||||
|
|
||||||
|
- **`Promise`** : A promise that resolves with the filtered data.
|
||||||
|
|
||||||
|
### `addFilter`
|
||||||
|
|
||||||
|
Adds a filter to the existing filters.
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
- **`filter`** : An object containing the filter criteria.
|
||||||
|
- **`params`** : Additional parameters for the filter.
|
||||||
|
|
||||||
|
#### Returns
|
||||||
|
|
||||||
|
- **`Promise`** : A promise that resolves with the updated filter and parameters.
|
||||||
|
|
||||||
|
### `getCurrentFilter`
|
||||||
|
|
||||||
|
Gets the current filter applied to the data.
|
||||||
|
|
||||||
|
#### Returns
|
||||||
|
|
||||||
|
- **`Object`** : The current filter and parameters.
|
||||||
|
|
||||||
|
### `setCurrentFilter`
|
||||||
|
|
||||||
|
Sets the current filter for the data.
|
||||||
|
|
||||||
|
#### Returns
|
||||||
|
|
||||||
|
- **`Object`** : The current filter and parameters.
|
||||||
|
|
||||||
|
### `addFilterWhere`
|
||||||
|
|
||||||
|
Adds a `where` clause to the existing filters.
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
- **`where`** : An object containing the `where` clause.
|
||||||
|
|
||||||
|
#### Returns
|
||||||
|
|
||||||
|
- **`Promise`** : A promise that resolves when the filter is applied.
|
||||||
|
|
||||||
|
### `addOrder`
|
||||||
|
|
||||||
|
Adds an order to the existing orders.
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
- **`field`** : The field to order by.
|
||||||
|
- **`direction`** : The direction of the order (`ASC` or `DESC`).
|
||||||
|
|
||||||
|
#### Returns
|
||||||
|
|
||||||
|
- **`Promise`** : A promise that resolves with the updated order.
|
||||||
|
|
||||||
|
### `deleteOrder`
|
||||||
|
|
||||||
|
Deletes an order from the existing orders.
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
- **`field`** : The field to delete the order for.
|
||||||
|
|
||||||
|
#### Returns
|
||||||
|
|
||||||
|
- **`Promise`** : A promise that resolves when the order is deleted.
|
||||||
|
|
||||||
|
### `refresh`
|
||||||
|
|
||||||
|
Refreshes the data by re-fetching it from the server.
|
||||||
|
|
||||||
|
#### Returns
|
||||||
|
|
||||||
|
- **`Promise`** : A promise that resolves with the refreshed data.
|
||||||
|
|
||||||
|
### `destroy`
|
||||||
|
|
||||||
|
Destroys the data store for the given key.
|
||||||
|
|
||||||
|
### `loadMore`
|
||||||
|
|
||||||
|
Loads more data by incrementing the pagination.
|
||||||
|
|
||||||
|
#### Returns
|
||||||
|
|
||||||
|
- **`Promise`** : A promise that resolves with the additional data.
|
||||||
|
|
||||||
|
### `updateStateParams`
|
||||||
|
|
||||||
|
Updates the state parameters with the given data.
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
- **`data`** : The data to update the state parameters with.
|
||||||
|
|
||||||
|
### `deleteOption`
|
||||||
|
|
||||||
|
Deletes an option from the store.
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
- **`option`** : The option to delete.
|
||||||
|
|
||||||
|
### `reset`
|
||||||
|
|
||||||
|
Resets the store to its default state.
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
- **`opts`** : An array of options to reset.
|
||||||
|
|
||||||
|
### `resetPagination`
|
||||||
|
|
||||||
|
Resets the pagination for the store.
|
||||||
|
|
||||||
|
## Computed Properties
|
||||||
|
|
||||||
|
### `totalRows`
|
||||||
|
|
||||||
|
- **Description:** The total number of rows in the data.
|
||||||
|
- **Type:** `Number`
|
||||||
|
|
||||||
|
### `isLoading`
|
||||||
|
|
||||||
|
- **Description:** Whether the data is currently being loaded.
|
||||||
|
- **Type:** `Boolean`
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<script setup>
|
||||||
|
import { useArrayData } from 'src/composables/useArrayData';
|
||||||
|
|
||||||
|
const userOptions = {
|
||||||
|
url: '/api/data',
|
||||||
|
limit: 10,
|
||||||
|
};
|
||||||
|
|
||||||
|
const arrayData = useArrayData('myKey', userOptions);
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
|
@ -0,0 +1,13 @@
|
||||||
|
---
|
||||||
|
# https://vitepress.dev/reference/default-theme-home-page
|
||||||
|
layout: home
|
||||||
|
|
||||||
|
hero:
|
||||||
|
name: 'Lilium'
|
||||||
|
text: 'Lilium docs'
|
||||||
|
tagline: Powered by Verdnatura
|
||||||
|
actions:
|
||||||
|
- theme: brand
|
||||||
|
text: Docs
|
||||||
|
link: /components/vnInput
|
||||||
|
---
|
|
@ -18,7 +18,10 @@
|
||||||
"test:unit:ci": "vitest run",
|
"test:unit:ci": "vitest run",
|
||||||
"commitlint": "commitlint --edit",
|
"commitlint": "commitlint --edit",
|
||||||
"prepare": "npx husky install",
|
"prepare": "npx husky install",
|
||||||
"addReferenceTag": "node .husky/addReferenceTag.js"
|
"addReferenceTag": "node .husky/addReferenceTag.js",
|
||||||
|
"docs:dev": "vitepress dev docs",
|
||||||
|
"docs:build": "vitepress build docs",
|
||||||
|
"docs:preview": "vitepress preview docs"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@quasar/cli": "^2.4.1",
|
"@quasar/cli": "^2.4.1",
|
||||||
|
@ -54,6 +57,7 @@
|
||||||
"postcss": "^8.4.23",
|
"postcss": "^8.4.23",
|
||||||
"prettier": "^3.4.2",
|
"prettier": "^3.4.2",
|
||||||
"sass": "^1.83.4",
|
"sass": "^1.83.4",
|
||||||
|
"vitepress": "^1.6.3",
|
||||||
"vitest": "^0.34.0"
|
"vitest": "^0.34.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|
772
pnpm-lock.yaml
772
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,6 @@
|
||||||
|
export default [
|
||||||
|
{
|
||||||
|
path: '/api',
|
||||||
|
rule: { target: 'http://0.0.0.0:3000' },
|
||||||
|
},
|
||||||
|
];
|
|
@ -179,7 +179,6 @@ export default configure(function (/* ctx */) {
|
||||||
'render', // keep this as last one
|
'render', // keep this as last one
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
// https://v2.quasar.dev/quasar-cli/developing-pwa/configuring-pwa
|
// https://v2.quasar.dev/quasar-cli/developing-pwa/configuring-pwa
|
||||||
pwa: {
|
pwa: {
|
||||||
workboxMode: 'generateSW', // or 'injectManifest'
|
workboxMode: 'generateSW', // or 'injectManifest'
|
||||||
|
|
|
@ -349,4 +349,11 @@ es:
|
||||||
floramondo: Floramondo
|
floramondo: Floramondo
|
||||||
salesPersonFk: Comprador
|
salesPersonFk: Comprador
|
||||||
categoryFk: Categoría
|
categoryFk: Categoría
|
||||||
|
Plant: Planta natural
|
||||||
|
Flower: Flor fresca
|
||||||
|
Handmade: Hecho a mano
|
||||||
|
Artificial: Artificial
|
||||||
|
Green: Verdes frescos
|
||||||
|
Accessories: Complementos florales
|
||||||
|
Fruit: Fruta
|
||||||
</i18n>
|
</i18n>
|
||||||
|
|
|
@ -20,6 +20,7 @@ const appName = 'Lilium';
|
||||||
const pinnedModulesRef = ref();
|
const pinnedModulesRef = ref();
|
||||||
|
|
||||||
onMounted(() => stateStore.setMounted());
|
onMounted(() => stateStore.setMounted());
|
||||||
|
const refresh = () => window.location.reload();
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<QHeader color="white" elevated>
|
<QHeader color="white" elevated>
|
||||||
|
@ -64,6 +65,13 @@ onMounted(() => stateStore.setMounted());
|
||||||
<QSpace />
|
<QSpace />
|
||||||
<div class="q-pl-sm q-gutter-sm row items-center no-wrap">
|
<div class="q-pl-sm q-gutter-sm row items-center no-wrap">
|
||||||
<div id="actions-prepend"></div>
|
<div id="actions-prepend"></div>
|
||||||
|
<QIcon
|
||||||
|
name="refresh"
|
||||||
|
size="md"
|
||||||
|
color="red"
|
||||||
|
v-if="state.get('error')"
|
||||||
|
@click="refresh"
|
||||||
|
/>
|
||||||
<QBtn
|
<QBtn
|
||||||
:class="{ 'q-pa-none': quasar.platform.is.mobile }"
|
:class="{ 'q-pa-none': quasar.platform.is.mobile }"
|
||||||
id="pinnedModules"
|
id="pinnedModules"
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
export default function (initialFooter, data) {
|
||||||
|
const footer = data.reduce(
|
||||||
|
(acc, row) => {
|
||||||
|
Object.entries(initialFooter).forEach(([key, initialValue]) => {
|
||||||
|
acc[key] += row?.[key] !== undefined ? row[key] : initialValue;
|
||||||
|
});
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
{ ...initialFooter }
|
||||||
|
);
|
||||||
|
return footer;
|
||||||
|
}
|
|
@ -26,6 +26,7 @@ onMounted(() => {
|
||||||
round
|
round
|
||||||
dense
|
dense
|
||||||
icon="dock_to_left"
|
icon="dock_to_left"
|
||||||
|
data-cy="toggle-right-drawer"
|
||||||
>
|
>
|
||||||
<QTooltip bottom anchor="bottom right">
|
<QTooltip bottom anchor="bottom right">
|
||||||
{{ t('globals.collapseMenu') }}
|
{{ t('globals.collapseMenu') }}
|
||||||
|
|
|
@ -175,7 +175,11 @@ const handleUppercase = () => {
|
||||||
v-if="!$attrs.disabled && !($attrs.readonly) && $props.uppercase"
|
v-if="!$attrs.disabled && !($attrs.readonly) && $props.uppercase"
|
||||||
@click="handleUppercase"
|
@click="handleUppercase"
|
||||||
class="uppercase-icon"
|
class="uppercase-icon"
|
||||||
/>
|
>
|
||||||
|
<QTooltip>
|
||||||
|
{{ t('Convert to uppercase') }}
|
||||||
|
</QTooltip>
|
||||||
|
</QIcon>
|
||||||
|
|
||||||
<slot name="append" v-if="$slots.append && !$attrs.disabled" />
|
<slot name="append" v-if="$slots.append && !$attrs.disabled" />
|
||||||
<QIcon v-if="info" name="info">
|
<QIcon v-if="info" name="info">
|
||||||
|
@ -188,13 +192,26 @@ const handleUppercase = () => {
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.uppercase-icon {
|
||||||
|
transition: color 0.3s, transform 0.2s;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uppercase-icon:hover {
|
||||||
|
color: #ed9937;
|
||||||
|
transform: scale(1.2);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
<i18n>
|
<i18n>
|
||||||
en:
|
en:
|
||||||
inputMin: Must be more than {value}
|
inputMin: Must be more than {value}
|
||||||
maxLength: The value exceeds {value} characters
|
maxLength: The value exceeds {value} characters
|
||||||
inputMax: Must be less than {value}
|
inputMax: Must be less than {value}
|
||||||
|
|
||||||
es:
|
es:
|
||||||
inputMin: Debe ser mayor a {value}
|
inputMin: Debe ser mayor a {value}
|
||||||
maxLength: El valor excede los {value} carácteres
|
maxLength: El valor excede los {value} carácteres
|
||||||
inputMax: Debe ser menor a {value}
|
inputMax: Debe ser menor a {value}
|
||||||
|
Convert to uppercase: Convertir a mayúsculas
|
||||||
</i18n>
|
</i18n>
|
|
@ -98,8 +98,8 @@ function checkIsMain() {
|
||||||
/>
|
/>
|
||||||
<div :id="searchbarId"></div>
|
<div :id="searchbarId"></div>
|
||||||
</slot>
|
</slot>
|
||||||
<RightAdvancedMenu :is-main-section="isMainSection && rightFilter">
|
<RightAdvancedMenu :is-main-section="isMainSection">
|
||||||
<template #advanced-menu v-if="$slots[advancedMenuSlot]">
|
<template #advanced-menu v-if="$slots[advancedMenuSlot] || rightFilter">
|
||||||
<slot :name="advancedMenuSlot">
|
<slot :name="advancedMenuSlot">
|
||||||
<VnTableFilter
|
<VnTableFilter
|
||||||
v-if="rightFilter && columns"
|
v-if="rightFilter && columns"
|
||||||
|
|
|
@ -170,7 +170,7 @@ function emitStoreData() {
|
||||||
async function paginate() {
|
async function paginate() {
|
||||||
const { page, rowsPerPage, sortBy, descending } = pagination.value;
|
const { page, rowsPerPage, sortBy, descending } = pagination.value;
|
||||||
|
|
||||||
if (!props.url) return;
|
if (!arrayData.store.url) return;
|
||||||
|
|
||||||
isLoading.value = true;
|
isLoading.value = true;
|
||||||
await arrayData.loadMore();
|
await arrayData.loadMore();
|
||||||
|
|
|
@ -44,7 +44,7 @@ const transferEntry = async () => {
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<QItem v-ripple clickable @click="showEntryReport">
|
<QItem v-ripple clickable @click="showEntryReport">
|
||||||
<QItemSection>{{ $t('entryList.list.showEntryReport') }}</QItemSection>
|
<QItemSection>{{ $t('entry.descriptorMenu.showEntryReport') }}</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
<QItem v-ripple clickable @click="openDialog">
|
<QItem v-ripple clickable @click="openDialog">
|
||||||
<QItemSection>{{ t('transferEntry') }}</QItemSection>
|
<QItemSection>{{ t('transferEntry') }}</QItemSection>
|
||||||
|
|
|
@ -76,6 +76,8 @@ entry:
|
||||||
warehouseInFk: Warehouse in
|
warehouseInFk: Warehouse in
|
||||||
search: Search entries
|
search: Search entries
|
||||||
searchInfo: You can search by entry reference
|
searchInfo: You can search by entry reference
|
||||||
|
descriptorMenu:
|
||||||
|
showEntryReport: Show entry report
|
||||||
entryFilter:
|
entryFilter:
|
||||||
params:
|
params:
|
||||||
invoiceNumber: Invoice number
|
invoiceNumber: Invoice number
|
||||||
|
|
|
@ -75,6 +75,8 @@ entry:
|
||||||
warehouseInFk: Alm. entrada
|
warehouseInFk: Alm. entrada
|
||||||
daysOnward: Días adelante
|
daysOnward: Días adelante
|
||||||
daysAgo: Días atras
|
daysAgo: Días atras
|
||||||
|
descriptorMenu:
|
||||||
|
showEntryReport: Ver informe del pedido
|
||||||
search: Buscar entradas
|
search: Buscar entradas
|
||||||
searchInfo: Puedes buscar por referencia de entrada
|
searchInfo: Puedes buscar por referencia de entrada
|
||||||
entryFilter:
|
entryFilter:
|
||||||
|
|
|
@ -368,7 +368,7 @@ watchEffect(selectedRows);
|
||||||
<VnSelect
|
<VnSelect
|
||||||
url="InvoiceOutSerials"
|
url="InvoiceOutSerials"
|
||||||
v-model="data.serial"
|
v-model="data.serial"
|
||||||
:label="t('invoicein.serial')"
|
:label="t('invoiceOutModule.serial')"
|
||||||
:options="invoiceOutSerialsOptions"
|
:options="invoiceOutSerialsOptions"
|
||||||
option-label="description"
|
option-label="description"
|
||||||
option-value="code"
|
option-value="code"
|
||||||
|
|
|
@ -60,6 +60,7 @@ invoiceOutModule:
|
||||||
amount: Amount
|
amount: Amount
|
||||||
company: Company
|
company: Company
|
||||||
address: Address
|
address: Address
|
||||||
|
serial: Serial
|
||||||
invoiceOutList:
|
invoiceOutList:
|
||||||
tableVisibleColumns:
|
tableVisibleColumns:
|
||||||
id: ID
|
id: ID
|
||||||
|
|
|
@ -60,6 +60,7 @@ invoiceOutModule:
|
||||||
amount: Importe
|
amount: Importe
|
||||||
company: Empresa
|
company: Empresa
|
||||||
address: Consignatario
|
address: Consignatario
|
||||||
|
serial: Serie
|
||||||
invoiceOutList:
|
invoiceOutList:
|
||||||
tableVisibleColumns:
|
tableVisibleColumns:
|
||||||
id: ID
|
id: ID
|
||||||
|
|
|
@ -48,14 +48,14 @@ const itemPackingTypesOptions = ref([]);
|
||||||
>
|
>
|
||||||
<template #form="{ data }">
|
<template #form="{ data }">
|
||||||
<VnRow>
|
<VnRow>
|
||||||
<VnInput v-model="data.code" :label="t('shared.code')" />
|
<VnInput v-model="data.code" :label="t('itemType.shared.code')" />
|
||||||
<VnInput v-model="data.name" :label="t('shared.name')" />
|
<VnInput v-model="data.name" :label="t('itemType.shared.name')" />
|
||||||
</VnRow>
|
</VnRow>
|
||||||
<VnRow>
|
<VnRow>
|
||||||
<VnSelect
|
<VnSelect
|
||||||
url="Workers/search"
|
url="Workers/search"
|
||||||
v-model="data.workerFk"
|
v-model="data.workerFk"
|
||||||
:label="t('shared.worker')"
|
:label="t('itemType.shared.worker')"
|
||||||
sort-by="nickname ASC"
|
sort-by="nickname ASC"
|
||||||
:fields="['id', 'nickname']"
|
:fields="['id', 'nickname']"
|
||||||
option-label="nickname"
|
option-label="nickname"
|
||||||
|
@ -83,7 +83,7 @@ const itemPackingTypesOptions = ref([]);
|
||||||
>
|
>
|
||||||
<VnSelect
|
<VnSelect
|
||||||
v-model="data.categoryFk"
|
v-model="data.categoryFk"
|
||||||
:label="t('shared.category')"
|
:label="t('itemType.shared.category')"
|
||||||
:options="categoriesOptions"
|
:options="categoriesOptions"
|
||||||
option-value="id"
|
option-value="id"
|
||||||
option-label="name"
|
option-label="name"
|
||||||
|
@ -93,27 +93,30 @@ const itemPackingTypesOptions = ref([]);
|
||||||
<VnRow>
|
<VnRow>
|
||||||
<VnSelect
|
<VnSelect
|
||||||
v-model="data.temperatureFk"
|
v-model="data.temperatureFk"
|
||||||
:label="t('shared.temperature')"
|
:label="t('itemType.shared.temperature')"
|
||||||
:options="temperaturesOptions"
|
:options="temperaturesOptions"
|
||||||
option-value="code"
|
option-value="code"
|
||||||
option-label="name"
|
option-label="name"
|
||||||
hide-selected
|
hide-selected
|
||||||
/>
|
/>
|
||||||
<VnInput v-model="data.life" :label="t('shared.life')" />
|
<VnInput v-model="data.life" :label="t('itemType.summary.life')" />
|
||||||
</VnRow>
|
</VnRow>
|
||||||
<VnRow>
|
<VnRow>
|
||||||
<VnSelect
|
<VnSelect
|
||||||
v-model="data.itemPackingTypeFk"
|
v-model="data.itemPackingTypeFk"
|
||||||
:label="t('shared.itemPackingType')"
|
:label="t('itemType.shared.itemPackingType')"
|
||||||
:options="itemPackingTypesOptions"
|
:options="itemPackingTypesOptions"
|
||||||
option-value="code"
|
option-value="code"
|
||||||
option-label="description"
|
option-label="description"
|
||||||
hide-selected
|
hide-selected
|
||||||
/>
|
/>
|
||||||
<VnInput v-model="data.maxRefs" :label="t('shared.maxRefs')" />
|
<VnInput v-model="data.maxRefs" :label="t('itemType.shared.maxRefs')" />
|
||||||
</VnRow>
|
</VnRow>
|
||||||
<VnRow>
|
<VnRow>
|
||||||
<QCheckbox v-model="data.isFragile" :label="t('shared.fragile')" />
|
<QCheckbox
|
||||||
|
v-model="data.isFragile"
|
||||||
|
:label="t('itemType.shared.fragile')"
|
||||||
|
/>
|
||||||
</VnRow>
|
</VnRow>
|
||||||
</template>
|
</template>
|
||||||
</FormModel>
|
</FormModel>
|
||||||
|
|
|
@ -50,15 +50,15 @@ const setData = (entity) => (data.value = useCardDescription(entity.code, entity
|
||||||
@on-fetch="setData"
|
@on-fetch="setData"
|
||||||
>
|
>
|
||||||
<template #body="{ entity }">
|
<template #body="{ entity }">
|
||||||
<VnLv :label="t('shared.code')" :value="entity.code" />
|
<VnLv :label="t('itemType.shared.code')" :value="entity.code" />
|
||||||
<VnLv :label="t('shared.name')" :value="entity.name" />
|
<VnLv :label="t('itemType.shared.name')" :value="entity.name" />
|
||||||
<VnLv :label="t('shared.worker')">
|
<VnLv :label="t('itemType.shared.worker')">
|
||||||
<template #value>
|
<template #value>
|
||||||
<span class="link">{{ entity.worker?.firstName }}</span>
|
<span class="link">{{ entity.worker?.firstName }}</span>
|
||||||
<WorkerDescriptorProxy :id="entity.worker?.id" />
|
<WorkerDescriptorProxy :id="entity.worker?.id" />
|
||||||
</template>
|
</template>
|
||||||
</VnLv>
|
</VnLv>
|
||||||
<VnLv :label="t('shared.category')" :value="entity.category?.name" />
|
<VnLv :label="t('itemType.shared.category')" :value="entity.category?.name" />
|
||||||
</template>
|
</template>
|
||||||
</CardDescriptor>
|
</CardDescriptor>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -76,13 +76,6 @@ itemTags:
|
||||||
searchbar:
|
searchbar:
|
||||||
label: Search item
|
label: Search item
|
||||||
info: Search by item id
|
info: Search by item id
|
||||||
itemType:
|
|
||||||
shared:
|
|
||||||
code: Code
|
|
||||||
name: Name
|
|
||||||
worker: Worker
|
|
||||||
category: Category
|
|
||||||
temperature: Temperature
|
|
||||||
item:
|
item:
|
||||||
params:
|
params:
|
||||||
daysOnward: Days onward
|
daysOnward: Days onward
|
||||||
|
|
|
@ -80,6 +80,9 @@ itemType:
|
||||||
worker: Trabajador
|
worker: Trabajador
|
||||||
category: Reino
|
category: Reino
|
||||||
temperature: Temperatura
|
temperature: Temperatura
|
||||||
|
searchbar:
|
||||||
|
label: Buscar artículo
|
||||||
|
info: Buscar por id de artículo
|
||||||
params:
|
params:
|
||||||
state: asfsdf
|
state: asfsdf
|
||||||
item:
|
item:
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import RouteDescriptor from 'pages/Route/Card/RouteDescriptor.vue';
|
import RouteDescriptor from 'pages/Route/Card/RouteDescriptor.vue';
|
||||||
import VnCardBeta from 'src/components/common/VnCardBeta.vue';
|
import VnCardBeta from 'src/components/common/VnCardBeta.vue';
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<VnCardBeta data-key="Route" base-url="Routes" :descriptor="RouteDescriptor" />
|
<VnCardBeta
|
||||||
|
data-key="Route"
|
||||||
|
base-url="Routes"
|
||||||
|
custom-url="Routes/filter"
|
||||||
|
:descriptor="RouteDescriptor"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -0,0 +1,191 @@
|
||||||
|
<script setup>
|
||||||
|
import { computed, onBeforeMount, ref } from 'vue';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
import tableFooter from 'src/components/VnTable/filters/tableFooter';
|
||||||
|
import { dashIfEmpty, toCurrency, toDateHourMin } from 'src/filters';
|
||||||
|
import { useState } from 'src/composables/useState';
|
||||||
|
import { useStateStore } from 'src/stores/useStateStore';
|
||||||
|
|
||||||
|
import VnTable from 'src/components/VnTable/VnTable.vue';
|
||||||
|
|
||||||
|
import InvoiceInDescriptorProxy from 'src/pages/InvoiceIn/Card/InvoiceInDescriptorProxy.vue';
|
||||||
|
import SupplierBalanceFilter from './SupplierBalanceFilter.vue';
|
||||||
|
import { onMounted } from 'vue';
|
||||||
|
import FetchData from 'src/components/FetchData.vue';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const state = useState();
|
||||||
|
const stateStore = useStateStore();
|
||||||
|
const user = state.getUser();
|
||||||
|
|
||||||
|
const tableRef = ref();
|
||||||
|
const companyId = ref();
|
||||||
|
const companyUser = ref(user.value.companyFk);
|
||||||
|
const balances = ref([]);
|
||||||
|
const userParams = ref({
|
||||||
|
supplierId: route.params.id,
|
||||||
|
companyId: companyId.value ?? companyUser.value,
|
||||||
|
isBooked: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const columns = computed(() => [
|
||||||
|
{
|
||||||
|
align: 'left',
|
||||||
|
name: 'dated',
|
||||||
|
label: t('Creation date'),
|
||||||
|
format: ({ dated }) => toDateHourMin(dated),
|
||||||
|
cardVisible: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
align: 'left',
|
||||||
|
name: 'sref',
|
||||||
|
label: t('Reference'),
|
||||||
|
isTitle: true,
|
||||||
|
class: 'extend',
|
||||||
|
format: ({ sref }) => dashIfEmpty(sref),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
align: 'left',
|
||||||
|
name: 'bank',
|
||||||
|
label: t('Bank'),
|
||||||
|
cardVisible: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
align: 'left',
|
||||||
|
name: 'invoiceEuros',
|
||||||
|
label: t('Debit'),
|
||||||
|
format: ({ invoiceEuros }) => toCurrency(invoiceEuros),
|
||||||
|
isId: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
align: 'left',
|
||||||
|
name: 'paymentEuros',
|
||||||
|
label: t('Havings'),
|
||||||
|
format: ({ paymentEuros }) => toCurrency(paymentEuros),
|
||||||
|
cardVisible: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
align: 'left',
|
||||||
|
name: 'euroBalance',
|
||||||
|
label: t('Balance'),
|
||||||
|
format: ({ euroBalance }) => toCurrency(euroBalance),
|
||||||
|
cardVisible: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
align: 'left',
|
||||||
|
name: 'isBooked',
|
||||||
|
label: t('Conciliated'),
|
||||||
|
cardVisible: true,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
onBeforeMount(() => {
|
||||||
|
stateStore.rightDrawer = true;
|
||||||
|
companyId.value = companyUser.value;
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
Object.assign(userParams, {
|
||||||
|
supplierId: route.params.id,
|
||||||
|
companyId: companyId.value ?? companyUser.value,
|
||||||
|
isConciliated: false,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function setFooter(data) {
|
||||||
|
const initialFooter = {
|
||||||
|
invoiceEuros: 0,
|
||||||
|
paymentEuros: 0,
|
||||||
|
euroBalance: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
tableRef.value.footer = tableFooter(initialFooter, data);
|
||||||
|
}
|
||||||
|
async function onFetch(data) {
|
||||||
|
setFooter(data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
function round(value) {
|
||||||
|
return Math.round(value * 100) / 100;
|
||||||
|
}
|
||||||
|
const onFetchCurrencies = ([currency]) => {
|
||||||
|
userParams.value.currencyFk = currency?.id;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<QDrawer side="right" :width="265" v-model="stateStore.rightDrawer">
|
||||||
|
<SupplierBalanceFilter data-key="SupplierBalance" />
|
||||||
|
</QDrawer>
|
||||||
|
<FetchData
|
||||||
|
url="Currencies"
|
||||||
|
:filter="{ fields: ['id', 'code'], where: { code: 'EUR' } }"
|
||||||
|
sort-by="code"
|
||||||
|
@on-fetch="onFetchCurrencies"
|
||||||
|
auto-load
|
||||||
|
/>
|
||||||
|
<VnTable
|
||||||
|
v-if="userParams.currencyFk"
|
||||||
|
ref="tableRef"
|
||||||
|
data-key="SupplierBalance"
|
||||||
|
url="Suppliers/receipts"
|
||||||
|
search-url="balance"
|
||||||
|
:user-params="userParams"
|
||||||
|
:columns="columns"
|
||||||
|
:right-search="false"
|
||||||
|
:is-editable="false"
|
||||||
|
:column-search="false"
|
||||||
|
@on-fetch="onFetch"
|
||||||
|
:disable-option="{ card: true }"
|
||||||
|
:footer="true"
|
||||||
|
:order="['dated ASC']"
|
||||||
|
data-cy="supplierBalanceTable"
|
||||||
|
auto-load
|
||||||
|
:map-key="false"
|
||||||
|
>
|
||||||
|
<template #column-balance="{ rowIndex }">
|
||||||
|
{{ toCurrency(balances[rowIndex]?.balance) }}
|
||||||
|
</template>
|
||||||
|
<template #column-sref="{ row }">
|
||||||
|
<span class="link" v-if="row.statementType === 'invoiceIn'">
|
||||||
|
{{ dashIfEmpty(row.sref) }}
|
||||||
|
<InvoiceInDescriptorProxy :id="row.id" />
|
||||||
|
</span>
|
||||||
|
<span v-else> {{ dashIfEmpty(row.sref) }}</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #column-footer-invoiceEuros>
|
||||||
|
<span>
|
||||||
|
{{ toCurrency(round(tableRef.footer.invoiceEuros)) }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<template #column-footer-paymentEuros>
|
||||||
|
<span>
|
||||||
|
{{ toCurrency(round(tableRef.footer.paymentEuros)) }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<template #column-footer-euroBalance>
|
||||||
|
<span>
|
||||||
|
{{ toCurrency(round(tableRef.footer.euroBalance)) }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</VnTable>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<i18n>
|
||||||
|
es:
|
||||||
|
Company: Empresa
|
||||||
|
Total by company: Total por empresa
|
||||||
|
Date: Fecha
|
||||||
|
Creation date: Fecha de creación
|
||||||
|
Reference: Referencia
|
||||||
|
Bank: Caja
|
||||||
|
Debit: Debe
|
||||||
|
Havings: Haber
|
||||||
|
Balance: Balance
|
||||||
|
Conciliated: Conciliado
|
||||||
|
</i18n>
|
|
@ -0,0 +1,121 @@
|
||||||
|
<script setup>
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
|
||||||
|
import VnSelect from 'src/components/common/VnSelect.vue';
|
||||||
|
import VnInputDate from 'src/components/common/VnInputDate.vue';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
defineProps({
|
||||||
|
dataKey: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<VnFilterPanel
|
||||||
|
:data-key="dataKey"
|
||||||
|
:search-button="true"
|
||||||
|
:redirect="false"
|
||||||
|
:unremovable-params="['supplierId', 'companyId']"
|
||||||
|
>
|
||||||
|
<template #tags="{ tag, formatFn }">
|
||||||
|
<div class="q-gutter-x-xs">
|
||||||
|
<strong>{{ t(`params.${tag.label}`) }}: </strong>
|
||||||
|
<span>{{ formatFn(tag.value) }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #body="{ params, searchFn }">
|
||||||
|
<QItem>
|
||||||
|
<QItemSection>
|
||||||
|
<VnInputDate
|
||||||
|
:label="t('params.from')"
|
||||||
|
v-model="params.from"
|
||||||
|
@update:model-value="searchFn()"
|
||||||
|
is-outlined
|
||||||
|
/>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
<QItem>
|
||||||
|
<QItemSection>
|
||||||
|
<VnSelect
|
||||||
|
:label="t('params.bankFk')"
|
||||||
|
v-model="params.bankFk"
|
||||||
|
url="Accountings"
|
||||||
|
option-label="bank"
|
||||||
|
:include="{ relation: 'accountingType' }"
|
||||||
|
sort-by="id"
|
||||||
|
dense
|
||||||
|
outlined
|
||||||
|
rounded
|
||||||
|
>
|
||||||
|
<template #option="scope">
|
||||||
|
<QItem v-bind="scope.itemProps">
|
||||||
|
<QItemSection>
|
||||||
|
<QItemLabel>
|
||||||
|
{{ scope.opt.id }} {{ scope.opt.bank }}
|
||||||
|
</QItemLabel>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
</template>
|
||||||
|
</VnSelect>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
<QItem>
|
||||||
|
<QItemSection>
|
||||||
|
<VnSelect
|
||||||
|
:label="t('params.currencyFk')"
|
||||||
|
url="Currencies"
|
||||||
|
:filter="{ fields: ['id', 'name'] }"
|
||||||
|
order="code"
|
||||||
|
v-model="params.currencyFk"
|
||||||
|
option-value="id"
|
||||||
|
option-label="name"
|
||||||
|
hide-selected
|
||||||
|
dense
|
||||||
|
outlined
|
||||||
|
rounded
|
||||||
|
/>
|
||||||
|
</QItemSection>
|
||||||
|
</QItem>
|
||||||
|
<QItem>
|
||||||
|
<QItemSection>
|
||||||
|
<QCheckbox
|
||||||
|
v-model="params.isConciliated"
|
||||||
|
:label="t('params.isConciliated')"
|
||||||
|
/></QItemSection>
|
||||||
|
</QItem>
|
||||||
|
</template>
|
||||||
|
</VnFilterPanel>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<i18n>
|
||||||
|
en:
|
||||||
|
params:
|
||||||
|
search: General search
|
||||||
|
supplierId: Supplier
|
||||||
|
categoryId: Category
|
||||||
|
from: From
|
||||||
|
to: To
|
||||||
|
isConciliated: Is conciliated
|
||||||
|
currencyFk: Currency
|
||||||
|
bankFk: Bank
|
||||||
|
companyId: Comapany
|
||||||
|
isBooked: Is booked
|
||||||
|
es:
|
||||||
|
params:
|
||||||
|
supplierId: Proveedor
|
||||||
|
isConciliated: Conciliado
|
||||||
|
currencyFk: Moneda
|
||||||
|
New payment: Añadir pago
|
||||||
|
Date: Fecha
|
||||||
|
from: Desde
|
||||||
|
to: Hasta
|
||||||
|
companyId: Empresa
|
||||||
|
isBooked: Contabilizado
|
||||||
|
bankFk: Caja
|
||||||
|
Amount: Importe
|
||||||
|
Reference: Referencia
|
||||||
|
Cash: Efectivo
|
||||||
|
</i18n>
|
|
@ -185,33 +185,31 @@ const entriesTableRows = computed(() => {
|
||||||
return entries.value;
|
return entries.value;
|
||||||
});
|
});
|
||||||
|
|
||||||
const entriesTotalHb = computed(() =>
|
const entriesTotals = computed(() => {
|
||||||
entriesTableRows.value.reduce((acc, { hb }) => acc + hb, 0)
|
const totals = {
|
||||||
);
|
hb: 0,
|
||||||
|
freightValue: 0,
|
||||||
|
packageValue: 0,
|
||||||
|
cc: 0,
|
||||||
|
pallet: 0,
|
||||||
|
m3: 0,
|
||||||
|
};
|
||||||
|
|
||||||
const entriesTotalFreight = computed(() =>
|
entriesTableRows.value.forEach((row) => {
|
||||||
toCurrency(
|
for (const key in totals) {
|
||||||
entriesTableRows.value.reduce((acc, { freightValue }) => acc + freightValue, 0)
|
totals[key] += row[key] || 0;
|
||||||
)
|
}
|
||||||
);
|
});
|
||||||
|
|
||||||
const entriesTotalPackageValue = computed(() =>
|
return {
|
||||||
toCurrency(
|
hb: totals.hb.toFixed(2),
|
||||||
entriesTableRows.value.reduce((acc, { packageValue }) => acc + packageValue, 0)
|
freight: toCurrency(totals.freightValue),
|
||||||
)
|
packageValue: toCurrency(totals.packageValue),
|
||||||
);
|
cc: totals.cc.toFixed(2),
|
||||||
|
pallet: totals.pallet.toFixed(2),
|
||||||
const entriesTotalCc = computed(() =>
|
m3: totals.m3.toFixed(2),
|
||||||
entriesTableRows.value.reduce((acc, { cc }) => acc + cc, 0)
|
};
|
||||||
);
|
});
|
||||||
|
|
||||||
const entriesTotalPallet = computed(() =>
|
|
||||||
entriesTableRows.value.reduce((acc, { pallet }) => acc + pallet, 0)
|
|
||||||
);
|
|
||||||
|
|
||||||
const entriesTotalM3 = computed(() =>
|
|
||||||
entriesTableRows.value.reduce((acc, { m3 }) => acc + m3, 0)
|
|
||||||
);
|
|
||||||
|
|
||||||
const getTravelEntries = async (id) => {
|
const getTravelEntries = async (id) => {
|
||||||
const { data } = await axios.get(`Travels/${id}/getEntries`);
|
const { data } = await axios.get(`Travels/${id}/getEntries`);
|
||||||
|
@ -382,12 +380,12 @@ const getLink = (param) => `#/travel/${entityId.value}/${param}`;
|
||||||
<QTd></QTd>
|
<QTd></QTd>
|
||||||
<QTd></QTd>
|
<QTd></QTd>
|
||||||
<QTd></QTd>
|
<QTd></QTd>
|
||||||
<QTd class="text-bold">{{ entriesTotalHb }}</QTd>
|
<QTd class="text-bold">{{ entriesTotals.hb }}</QTd>
|
||||||
<QTd class="text-bold">{{ entriesTotalFreight }}</QTd>
|
<QTd class="text-bold">{{ entriesTotals.freight }}</QTd>
|
||||||
<QTd class="text-bold">{{ entriesTotalPackageValue }}</QTd>
|
<QTd class="text-bold">{{ entriesTotals.packageValue }}</QTd>
|
||||||
<QTd class="text-bold">{{ entriesTotalCc }}</QTd>
|
<QTd class="text-bold">{{ entriesTotals.cc }}</QTd>
|
||||||
<QTd class="text-bold">{{ entriesTotalPallet }}</QTd>
|
<QTd class="text-bold">{{ entriesTotals.pallet }}</QTd>
|
||||||
<QTd class="text-bold">{{ entriesTotalM3 }}</QTd>
|
<QTd class="text-bold">{{ entriesTotals.m3 }}</QTd>
|
||||||
</template>
|
</template>
|
||||||
</QTable>
|
</QTable>
|
||||||
</QCard>
|
</QCard>
|
||||||
|
|
|
@ -99,9 +99,15 @@ export default defineRouter(function (/* { store, ssrContext } */) {
|
||||||
|
|
||||||
title += builtTitle;
|
title += builtTitle;
|
||||||
}
|
}
|
||||||
|
|
||||||
document.title = title;
|
document.title = title;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Router.onError(({ message }) => {
|
||||||
|
const errorMessages = [
|
||||||
|
'Failed to fetch dynamically imported module',
|
||||||
|
'Importing a module script failed',
|
||||||
|
];
|
||||||
|
state.set('error', errorMessages.some(message.includes));
|
||||||
|
});
|
||||||
return Router;
|
return Router;
|
||||||
});
|
});
|
||||||
|
|
|
@ -21,6 +21,7 @@ export default {
|
||||||
'SupplierAccounts',
|
'SupplierAccounts',
|
||||||
'SupplierContacts',
|
'SupplierContacts',
|
||||||
'SupplierAddresses',
|
'SupplierAddresses',
|
||||||
|
'SupplierBalance',
|
||||||
'SupplierConsumption',
|
'SupplierConsumption',
|
||||||
'SupplierAgencyTerm',
|
'SupplierAgencyTerm',
|
||||||
'SupplierDms',
|
'SupplierDms',
|
||||||
|
@ -144,6 +145,16 @@ export default {
|
||||||
component: () =>
|
component: () =>
|
||||||
import('src/pages/Supplier/Card/SupplierAddressesCreate.vue'),
|
import('src/pages/Supplier/Card/SupplierAddressesCreate.vue'),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'balance',
|
||||||
|
name: 'SupplierBalance',
|
||||||
|
meta: {
|
||||||
|
title: 'balance',
|
||||||
|
icon: 'balance',
|
||||||
|
},
|
||||||
|
component: () =>
|
||||||
|
import('src/pages/Supplier/Card/SupplierBalance.vue'),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'consumption',
|
path: 'consumption',
|
||||||
name: 'SupplierConsumption',
|
name: 'SupplierConsumption',
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
describe('Supplier Balance', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.viewport(1920, 1080);
|
||||||
|
cy.login('developer');
|
||||||
|
cy.visit(`/#/supplier/1/balance`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should load layout', () => {
|
||||||
|
cy.get('.q-page').should('be.visible');
|
||||||
|
});
|
||||||
|
});
|
|
@ -3,9 +3,7 @@ describe('Client balance', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
cy.viewport(1280, 720);
|
cy.viewport(1280, 720);
|
||||||
cy.login('developer');
|
cy.login('developer');
|
||||||
cy.visit('#/customer/1101/balance', {
|
cy.visit('#/customer/1101/balance');
|
||||||
timeout: 5000,
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
it('Should load layout', () => {
|
it('Should load layout', () => {
|
||||||
cy.get('.q-page').should('be.visible');
|
cy.get('.q-page').should('be.visible');
|
||||||
|
|
|
@ -9,7 +9,7 @@ describe('InvoiceInList', () => {
|
||||||
cy.viewport(1920, 1080);
|
cy.viewport(1920, 1080);
|
||||||
cy.login('developer');
|
cy.login('developer');
|
||||||
cy.visit(`/#/invoice-in/list`);
|
cy.visit(`/#/invoice-in/list`);
|
||||||
cy.get('#searchbar input').type('{enter}');
|
cy.get('#searchbar input').should('be.visible').type('{enter}');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should redirect on clicking a invoice', () => {
|
it('should redirect on clicking a invoice', () => {
|
||||||
|
@ -22,7 +22,7 @@ describe('InvoiceInList', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
// https://redmine.verdnatura.es/issues/8420
|
// https://redmine.verdnatura.es/issues/8420
|
||||||
it.skip('should open the details', () => {
|
it('should open the details', () => {
|
||||||
cy.get(firstDetailBtn).click();
|
cy.get(firstDetailBtn).click();
|
||||||
cy.get(summaryHeaders).eq(1).contains('Basic data');
|
cy.get(summaryHeaders).eq(1).contains('Basic data');
|
||||||
cy.get(summaryHeaders).eq(4).contains('Vat');
|
cy.get(summaryHeaders).eq(4).contains('Vat');
|
||||||
|
|
|
@ -1,13 +1,6 @@
|
||||||
/// <reference types="cypress" />
|
/// <reference types="cypress" />
|
||||||
describe('InvoiceOut list', () => {
|
describe('InvoiceOut list', () => {
|
||||||
const invoice = {
|
const serial = 'Española rapida';
|
||||||
Ticket: { val: '8' },
|
|
||||||
Serial: { val: 'Española rapida', type: 'select' },
|
|
||||||
};
|
|
||||||
const invoiceError = {
|
|
||||||
Ticket: { val: '1' },
|
|
||||||
Serial: { val: 'Española rapida', type: 'select' },
|
|
||||||
};
|
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
cy.viewport(1920, 1080);
|
cy.viewport(1920, 1080);
|
||||||
|
@ -32,14 +25,16 @@ describe('InvoiceOut list', () => {
|
||||||
|
|
||||||
it('should give an error when manual invoicing a ticket that is already invoiced', () => {
|
it('should give an error when manual invoicing a ticket that is already invoiced', () => {
|
||||||
cy.dataCy('vnTableCreateBtn').click();
|
cy.dataCy('vnTableCreateBtn').click();
|
||||||
cy.fillInForm(invoiceError);
|
cy.dataCy('InvoiceOutCreateTicketinput').type(1);
|
||||||
|
cy.selectOption('[data-cy="InvoiceOutCreateSerialSelect"]', serial);
|
||||||
cy.dataCy('FormModelPopup_save').click();
|
cy.dataCy('FormModelPopup_save').click();
|
||||||
cy.checkNotification('This ticket is already invoiced');
|
cy.checkNotification('This ticket is already invoiced');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create a manual invoice and enter to its summary', () => {
|
it('should create a manual invoice and enter to its summary', () => {
|
||||||
cy.dataCy('vnTableCreateBtn').click();
|
cy.dataCy('vnTableCreateBtn').click();
|
||||||
cy.fillInForm(invoice);
|
cy.dataCy('InvoiceOutCreateTicketinput').type(8);
|
||||||
|
cy.selectOption('[data-cy="InvoiceOutCreateSerialSelect"]', serial);
|
||||||
cy.dataCy('FormModelPopup_save').click();
|
cy.dataCy('FormModelPopup_save').click();
|
||||||
cy.checkNotification('Data created');
|
cy.checkNotification('Data created');
|
||||||
});
|
});
|
||||||
|
|
|
@ -10,14 +10,14 @@ describe('VnLog', () => {
|
||||||
cy.openRightMenu();
|
cy.openRightMenu();
|
||||||
});
|
});
|
||||||
|
|
||||||
it.skip('should filter by insert actions', () => {
|
it('should filter by insert actions', () => {
|
||||||
cy.checkOption(':nth-child(7) > .q-checkbox');
|
cy.checkOption(':nth-child(7) > .q-checkbox');
|
||||||
cy.get('.q-page').click();
|
cy.get('.q-page').click();
|
||||||
cy.validateContent(chips[0], 'Document');
|
cy.validateContent(chips[0], 'Document');
|
||||||
cy.validateContent(chips[1], 'Beginning');
|
cy.validateContent(chips[1], 'Beginning');
|
||||||
});
|
});
|
||||||
|
|
||||||
it.skip('should filter by entity', () => {
|
it('should filter by entity', () => {
|
||||||
cy.selectOption('.q-drawer--right .q-item > .q-select', 'Claim');
|
cy.selectOption('.q-drawer--right .q-item > .q-select', 'Claim');
|
||||||
cy.get('.q-page').click();
|
cy.get('.q-page').click();
|
||||||
cy.validateContent(chips[0], 'Claim');
|
cy.validateContent(chips[0], 'Claim');
|
||||||
|
|
|
@ -71,7 +71,7 @@ Cypress.Commands.add('getValue', (selector) => {
|
||||||
return cy
|
return cy
|
||||||
.get(
|
.get(
|
||||||
selector +
|
selector +
|
||||||
'> .q-field > .q-field__inner > .q-field__control > .q-field__control-container > .q-field__native > input'
|
'> .q-field > .q-field__inner > .q-field__control > .q-field__control-container > .q-field__native > input',
|
||||||
)
|
)
|
||||||
.invoke('val');
|
.invoke('val');
|
||||||
}
|
}
|
||||||
|
@ -264,7 +264,7 @@ Cypress.Commands.add('openListSummary', (row) => {
|
||||||
|
|
||||||
Cypress.Commands.add('openRightMenu', (element) => {
|
Cypress.Commands.add('openRightMenu', (element) => {
|
||||||
if (element) cy.waitForElement(element);
|
if (element) cy.waitForElement(element);
|
||||||
cy.get('#actions-append').click();
|
cy.get('[data-cy="toggle-right-drawer"]').click();
|
||||||
});
|
});
|
||||||
|
|
||||||
Cypress.Commands.add('openLeftMenu', (element) => {
|
Cypress.Commands.add('openLeftMenu', (element) => {
|
||||||
|
@ -330,7 +330,7 @@ Cypress.Commands.add('clickButtonsDescriptor', (id) => {
|
||||||
|
|
||||||
Cypress.Commands.add('openUserPanel', () => {
|
Cypress.Commands.add('openUserPanel', () => {
|
||||||
cy.get(
|
cy.get(
|
||||||
'.column > .q-avatar > .q-avatar__content > .q-img > .q-img__container > .q-img__image'
|
'.column > .q-avatar > .q-avatar__content > .q-img > .q-img__container > .q-img__image',
|
||||||
).click();
|
).click();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -356,7 +356,7 @@ Cypress.Commands.add('checkValueForm', (id, search) => {
|
||||||
|
|
||||||
Cypress.Commands.add('checkValueSelectForm', (id, search) => {
|
Cypress.Commands.add('checkValueSelectForm', (id, search) => {
|
||||||
cy.get(
|
cy.get(
|
||||||
`.grid-create > :nth-child(${id}) > .q-field > .q-field__inner > .q-field__control > .q-field__control-container > .q-field__native > .q-field__input`
|
`.grid-create > :nth-child(${id}) > .q-field > .q-field__inner > .q-field__control > .q-field__control-container > .q-field__native > .q-field__input`,
|
||||||
).should('have.value', search);
|
).should('have.value', search);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue