From be1993cf8b04f89bd0e2fc185054f13d07a469c0 Mon Sep 17 00:00:00 2001 From: alexandre Date: Thu, 2 Mar 2023 11:33:55 +0100 Subject: [PATCH 01/95] refs #5206 version with top-searcher and two fields for reference and id --- front/core/styles/variables.scss | 1 + front/salix/components/layout/style.scss | 6 +- .../front/extra-community/locale/es.yml | 4 +- modules/travel/front/index/index.html | 27 +- modules/travel/front/locale/es.yml | 10 +- modules/travel/front/main/index.html | 3 +- modules/travel/front/search-panel/index.html | 299 +++++++++++------- modules/travel/front/search-panel/index.js | 42 ++- modules/travel/front/search-panel/style.scss | 42 +++ modules/travel/front/summary/locale/es.yml | 6 +- 10 files changed, 279 insertions(+), 161 deletions(-) create mode 100644 modules/travel/front/search-panel/style.scss diff --git a/front/core/styles/variables.scss b/front/core/styles/variables.scss index bcc9fab66..c280838ca 100644 --- a/front/core/styles/variables.scss +++ b/front/core/styles/variables.scss @@ -2,6 +2,7 @@ $font-size: 11pt; $menu-width: 256px; +$right-menu-width: 318px; $topbar-height: 56px; $mobile-width: 800px; $float-spacing: 20px; diff --git a/front/salix/components/layout/style.scss b/front/salix/components/layout/style.scss index 612366228..6697bb1b0 100644 --- a/front/salix/components/layout/style.scss +++ b/front/salix/components/layout/style.scss @@ -88,13 +88,13 @@ vn-layout { } &.right-menu { & > vn-topbar > .end { - width: 80px + $menu-width; + width: 80px + $right-menu-width; } & > .main-view { - padding-right: $menu-width; + padding-right: $right-menu-width; } [fixed-bottom-right] { - right: $menu-width; + right: $right-menu-width; } } & > .main-view { diff --git a/modules/travel/front/extra-community/locale/es.yml b/modules/travel/front/extra-community/locale/es.yml index dc231226f..ed6179c91 100644 --- a/modules/travel/front/extra-community/locale/es.yml +++ b/modules/travel/front/extra-community/locale/es.yml @@ -6,6 +6,6 @@ Phy. KG: KG físico Vol. KG: KG Vol. Search by travel id or reference: Buscar por id de travel o referencia Search by extra community travel: Buscar por envío extra comunitario -Continent Out: Continente salida +Continent Out: Cont. salida W. Shipped: F. envío -W. Landed: F. llegada \ No newline at end of file +W. Landed: F. llegada diff --git a/modules/travel/front/index/index.html b/modules/travel/front/index/index.html index 27a700083..14faef3ee 100644 --- a/modules/travel/front/index/index.html +++ b/modules/travel/front/index/index.html @@ -2,6 +2,9 @@ + + @@ -9,7 +12,6 @@ - Id Reference Agency Warehouse Out @@ -22,10 +24,9 @@ - - {{::travel.id}} {{::travel.ref}} {{::travel.agencyModeName}} {{::travel.warehouseOutName}} @@ -49,7 +50,7 @@ vn-tooltip="Clone" icon="icon-clone"> - @@ -78,7 +79,7 @@ fixed-bottom-right> - Filter by selection - Exclude selection - Remove filter - Remove all filters - Copy value - \ No newline at end of file + diff --git a/modules/travel/front/locale/es.yml b/modules/travel/front/locale/es.yml index 7231d37cd..043702b99 100644 --- a/modules/travel/front/locale/es.yml +++ b/modules/travel/front/locale/es.yml @@ -1,7 +1,7 @@ #Ordenar alfabeticamente Reference: Referencia -Warehouse Out: Almacén salida -Warehouse In: Almacén llegada +Warehouse Out: Alm salida +Warehouse In: Alm llegada Shipped from: Salida desde Shipped to: Salida hasta Landed from: Llegada desde @@ -10,12 +10,12 @@ Shipped: F. salida Landed: F. llegada Delivered: Enviado Received: Recibido -Travel id: Id envío -Search travels by id: Buscar envíos por identificador +Travel id: Id +Search travels by id: Buscar envíos por identificador o referencia New travel: Nuevo envío travel: envío # Sections Travels: Envíos Log: Historial -Thermographs: Termógrafos \ No newline at end of file +Thermographs: Termógrafos diff --git a/modules/travel/front/main/index.html b/modules/travel/front/main/index.html index feb1e8b01..acf1a1612 100644 --- a/modules/travel/front/main/index.html +++ b/modules/travel/front/main/index.html @@ -7,7 +7,6 @@ - \ No newline at end of file + diff --git a/modules/travel/front/search-panel/index.html b/modules/travel/front/search-panel/index.html index 2e9c796c3..26f6b96c6 100644 --- a/modules/travel/front/search-panel/index.html +++ b/modules/travel/front/search-panel/index.html @@ -1,109 +1,190 @@ -
-
- - - - - - - - - - - - - - - - -
- - - - - - Or - - - - - -
- - - - - - - - - - - - - - - - - - - -
-
\ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + Or +
+ + + + +
+
+ + + + + + + + + + + + +
+ + {{$ctrl.$t('Reference')}}: {{$ctrl.filter.ref}} + + + {{$ctrl.$t('Total entries')}}: {{$ctrl.filter.totalEntries}} + + + {{$ctrl.$t('Travel id')}}: {{$ctrl.filter.id}} + + + {{$ctrl.$t('Agency')}}: {{agency.selection.name}} + + + {{$ctrl.$t('Continent Out')}}: {{continent.selection.name}} + + + {{$ctrl.$t('Shipped from')}}: {{$ctrl.filter.shippedFrom | date:'dd/MM/yyyy'}} + + + {{$ctrl.$t('Shipped to')}}: {{$ctrl.filter.shippedTo | date:'dd/MM/yyyy'}} + + + {{$ctrl.$t('Days onward')}}: {{$ctrl.filter.scopeDays}} + + + {{$ctrl.$t('Landed from')}}: {{$ctrl.filter.landedFrom | date:'dd/MM/yyyy'}} + + + {{$ctrl.$t('Landed to')}}: {{$ctrl.filter.landedTo | date:'dd/MM/yyyy'}} + + + {{$ctrl.$t('Warehouse Out')}}: {{warehouseOut.selection.name}} + + + {{$ctrl.$t('Warehouse In')}}: {{warehouseIn.selection.name}} + +
+
diff --git a/modules/travel/front/search-panel/index.js b/modules/travel/front/search-panel/index.js index 877d4f9d3..69d8dafcd 100644 --- a/modules/travel/front/search-panel/index.js +++ b/modules/travel/front/search-panel/index.js @@ -1,43 +1,37 @@ import ngModule from '../module'; import SearchPanel from 'core/components/searchbar/search-panel'; +import './style.scss'; class Controller extends SearchPanel { constructor($, $element) { super($, $element); - this.filter = this.$.filter; } - get shippedFrom() { - return this._shippedFrom; - } - - set shippedFrom(value) { - this._shippedFrom = value; + changeShipped() { this.filter.scopeDays = null; + this.addFilters(); } - get shippedTo() { - return this._shippedTo; - } - - set shippedTo(value) { - this._shippedTo = value; - this.filter.scopeDays = null; - } - - get scopeDays() { - return this._scopeDays; - } - - set scopeDays(value) { - this._scopeDays = value; - + changeScopeDays() { this.filter.shippedFrom = null; this.filter.shippedTo = null; + this.addFilters(); + } + + addFilters() { + this.model.addFilter({}, this.filter); + } + + removeParamFilter(param) { + this.filter[param] = null; + this.addFilters(); } } ngModule.vnComponent('vnTravelSearchPanel', { template: require('./index.html'), - controller: Controller + controller: Controller, + bindings: { + model: '<' + } }); diff --git a/modules/travel/front/search-panel/style.scss b/modules/travel/front/search-panel/style.scss new file mode 100644 index 000000000..4d08c1402 --- /dev/null +++ b/modules/travel/front/search-panel/style.scss @@ -0,0 +1,42 @@ +@import "variables"; + +vn-travel-search-panel vn-side-menu { + .menu { + min-width: $right-menu-width; + } + & > div { + .input { + padding-left: $spacing-md; + padding-right: $spacing-md; + border-color: $color-spacer; + border-bottom: $border-thin; + } + .horizontal { + padding-left: $spacing-md; + padding-right: $spacing-md; + grid-auto-flow: column; + grid-column-gap: $spacing-sm; + align-items: center; + } + .chips { + display: flex; + flex-wrap: wrap; + padding: $spacing-md; + overflow: hidden; + max-width: 100%; + border-color: $color-spacer; + } + + .or { + align-self: center; + font-weight: bold; + font-size: 26px; + color: $color-font-secondary; + } + + .scope-days{ + display: flex; + align-items: center; + } + } +} diff --git a/modules/travel/front/summary/locale/es.yml b/modules/travel/front/summary/locale/es.yml index aa002fad0..aa6adc938 100644 --- a/modules/travel/front/summary/locale/es.yml +++ b/modules/travel/front/summary/locale/es.yml @@ -1,9 +1,9 @@ Reference: Referencia -Warehouse In: Almacén entrada -Warehouse Out: Almacén salida +Warehouse In: Alm. entrada +Warehouse Out: Alm. salida Shipped: F. envío Landed: F. entrega -Total entries: Entradas totales +Total entries: Ent. totales Delivered: Enviada Received: Recibida Agency: Agencia From dbe42e3bf4490ac60a8d4dc37ea982fb4bd5bc7c Mon Sep 17 00:00:00 2001 From: alexandre Date: Thu, 2 Mar 2023 13:55:47 +0100 Subject: [PATCH 02/95] refs #5206 version with plane added, needs to implement general search --- front/core/locale/es.yml | 10 +++--- modules/travel/front/index/index.html | 27 +++++++++++--- modules/travel/front/index/index.js | 1 + modules/travel/front/index/style.scss | 11 ++++++ modules/travel/front/main/index.html | 13 ------- modules/travel/front/main/index.js | 22 ------------ modules/travel/front/search-panel/index.html | 37 ++++++-------------- modules/travel/front/search-panel/index.js | 31 ++++++++++++++++ 8 files changed, 82 insertions(+), 70 deletions(-) create mode 100644 modules/travel/front/index/style.scss diff --git a/front/core/locale/es.yml b/front/core/locale/es.yml index d849fcdd2..f654c61cf 100644 --- a/front/core/locale/es.yml +++ b/front/core/locale/es.yml @@ -26,7 +26,7 @@ Value should have at most %s characters: El valor debe tener un máximo de %s ca Enter a new search: Introduce una nueva búsqueda No results: Sin resultados Ups! It seems there was an error: ¡Vaya! Parece que ha habido un error -General search: Busqueda general +General search: Búsqueda general January: Enero February: Febrero March: Marzo @@ -42,9 +42,9 @@ December: Diciembre Monday: Lunes Tuesday: Martes Wednesday: Miércoles -Thursday: Jueves -Friday: Viernes -Saturday: Sábado +Thursday: Jueves +Friday: Viernes +Saturday: Sábado Sunday: Domingo Has delivery: Hay reparto Loading: Cargando @@ -63,4 +63,4 @@ Loading...: Cargando... No results found: Sin resultados No data: Sin datos Undo changes: Deshacer cambios -Load more results: Cargar más resultados \ No newline at end of file +Load more results: Cargar más resultados diff --git a/modules/travel/front/index/index.html b/modules/travel/front/index/index.html index 14faef3ee..06acd92a1 100644 --- a/modules/travel/front/index/index.html +++ b/modules/travel/front/index/index.html @@ -5,6 +5,13 @@ + + @@ -16,10 +23,10 @@ Agency Warehouse Out Shipped - Delivered + Warehouse In Landed - Received + @@ -35,14 +42,26 @@ {{::travel.shipped | date:'dd/MM/yyyy'}} - + + + + {{::travel.warehouseInName}} {{::travel.landed | date:'dd/MM/yyyy'}} - + + + + - - - diff --git a/modules/travel/front/main/index.js b/modules/travel/front/main/index.js index fbaf78c16..6a153f21a 100644 --- a/modules/travel/front/main/index.js +++ b/modules/travel/front/main/index.js @@ -4,28 +4,6 @@ import ModuleMain from 'salix/components/module-main'; export default class Travel extends ModuleMain { constructor() { super(); - - this.filterParams = { - scopeDays: 1 - }; - } - - fetchParams($params) { - if (!Object.entries($params).length) - $params.scopeDays = 1; - - if (typeof $params.scopeDays === 'number') { - const shippedFrom = Date.vnNew(); - shippedFrom.setHours(0, 0, 0, 0); - - const shippedTo = new Date(shippedFrom.getTime()); - shippedTo.setDate(shippedTo.getDate() + $params.scopeDays); - shippedTo.setHours(23, 59, 59, 999); - - Object.assign($params, {shippedFrom, shippedTo}); - } - - return $params; } } diff --git a/modules/travel/front/search-panel/index.html b/modules/travel/front/search-panel/index.html index 26f6b96c6..d39f32a7d 100644 --- a/modules/travel/front/search-panel/index.html +++ b/modules/travel/front/search-panel/index.html @@ -1,23 +1,18 @@ + label="General search" + info="Search travels by id" + ng-model="$ctrl.search" + ng-keydown="$ctrl.onKeyPress($event, 'search')"> - - + ng-model="$ctrl.totalEntries" + ng-keydown="$ctrl.onKeyPress($event, 'totalEntries')"> @@ -61,12 +56,9 @@ label="Days onward" ng-model="$ctrl.filter.scopeDays" on-change="$ctrl.changeScopeDays()" - display-controls="true"> + display-controls="true" + info="Cannot choose a range of dates and days onward at the same time"> - - @@ -103,11 +95,11 @@
- {{$ctrl.$t('Reference')}}: {{$ctrl.filter.ref}} + Id/{{$ctrl.$t('Reference')}}: {{$ctrl.filter.search}} {{$ctrl.$t('Total entries')}}: {{$ctrl.filter.totalEntries}} - - {{$ctrl.$t('Travel id')}}: {{$ctrl.filter.id}} - Date: Thu, 2 Mar 2023 15:10:17 +0100 Subject: [PATCH 03/95] refs #5206 implemented general search, missing tests --- modules/travel/front/index/index.html | 3 +- modules/travel/front/main/index.js | 3 -- modules/travel/front/search-panel/index.js | 39 ++++++++-------------- 3 files changed, 15 insertions(+), 30 deletions(-) diff --git a/modules/travel/front/index/index.html b/modules/travel/front/index/index.html index 06acd92a1..df7fd5611 100644 --- a/modules/travel/front/index/index.html +++ b/modules/travel/front/index/index.html @@ -9,8 +9,7 @@ vn-id="model" url="Travels/filter" limit="20" - order="shipped DESC, landed DESC" - auto-load="true"> + order="shipped DESC, landed DESC"> { + if (param) + this.checkJustOneResult(); + }); } removeParamFilter(param) { @@ -51,12 +36,16 @@ class Controller extends SearchPanel { } onKeyPress($event, param) { - console.log('event'); if ($event.key === 'Enter') { this.filter[param] = this[param]; - this.addFilters(); + this.addFilters(param === 'search'); } } + + checkJustOneResult() { + if (this.model._orgData.length === 1) + this.$state.go('travel.card.summary', {id: this.model._orgData[0].id}); + } } ngModule.vnComponent('vnTravelSearchPanel', { From f2bd0253e28222d2ab5f90931742a6f1a9c12af1 Mon Sep 17 00:00:00 2001 From: alexandre Date: Mon, 6 Mar 2023 09:27:53 +0100 Subject: [PATCH 04/95] refs #5092 added unbilled tickets section --- db/changes/231001/.gitkeep | 0 db/changes/231001/00-unbilledTickets.sql | 3 + .../09-invoice-in/05_unbilled_tickets.spec.js | 29 +++++ loopback/locale/en.json | 8 +- loopback/locale/es.json | 3 +- modules/client/front/locale/es.yml | 3 +- .../invoice-in/specs/unbilledTickets.spec.js | 47 ++++++++ .../methods/invoice-in/unbilledTickets.js | 112 ++++++++++++++++++ modules/invoiceIn/back/models/invoice-in.js | 1 + modules/invoiceIn/front/index.js | 1 + modules/invoiceIn/front/routes.json | 17 ++- .../front/unbilled-tickets/index.html | 104 ++++++++++++++++ .../invoiceIn/front/unbilled-tickets/index.js | 66 +++++++++++ .../front/unbilled-tickets/locale/es.yml | 1 + .../front/unbilled-tickets/style.scss | 7 ++ 15 files changed, 392 insertions(+), 10 deletions(-) delete mode 100644 db/changes/231001/.gitkeep create mode 100644 db/changes/231001/00-unbilledTickets.sql create mode 100644 e2e/paths/09-invoice-in/05_unbilled_tickets.spec.js create mode 100644 modules/invoiceIn/back/methods/invoice-in/specs/unbilledTickets.spec.js create mode 100644 modules/invoiceIn/back/methods/invoice-in/unbilledTickets.js create mode 100644 modules/invoiceIn/front/unbilled-tickets/index.html create mode 100644 modules/invoiceIn/front/unbilled-tickets/index.js create mode 100644 modules/invoiceIn/front/unbilled-tickets/locale/es.yml create mode 100644 modules/invoiceIn/front/unbilled-tickets/style.scss diff --git a/db/changes/231001/.gitkeep b/db/changes/231001/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/db/changes/231001/00-unbilledTickets.sql b/db/changes/231001/00-unbilledTickets.sql new file mode 100644 index 000000000..d0c3fbbcb --- /dev/null +++ b/db/changes/231001/00-unbilledTickets.sql @@ -0,0 +1,3 @@ +INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) + VALUES + ('InvoiceIn', 'unbilledTickets', 'READ', 'ALLOW', 'ROLE', 'administrative'); diff --git a/e2e/paths/09-invoice-in/05_unbilled_tickets.spec.js b/e2e/paths/09-invoice-in/05_unbilled_tickets.spec.js new file mode 100644 index 000000000..dd75d0b49 --- /dev/null +++ b/e2e/paths/09-invoice-in/05_unbilled_tickets.spec.js @@ -0,0 +1,29 @@ +import getBrowser from '../../helpers/puppeteer'; + +describe('InvoiceIn unbilled tickets path', () => { + let browser; + let page; + const httpRequests = []; + + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + page.on('request', req => { + if (req.url().includes(`InvoiceIns/unbilledTickets`)) + httpRequests.push(req.url()); + }); + await page.loginAndModule('administrative', 'invoiceIn'); + await page.accessToSection('invoiceIn.unbilled-tickets'); + }); + + afterAll(async() => { + await browser.close(); + }); + + it('should show unbilled tickets in a date range', async() => { + const request = httpRequests.find(req => + req.includes(`from`) && req.includes(`to`)); + + expect(request).toBeDefined(); + }); +}); diff --git a/loopback/locale/en.json b/loopback/locale/en.json index eeb25f75d..dbe25dea3 100644 --- a/loopback/locale/en.json +++ b/loopback/locale/en.json @@ -147,8 +147,10 @@ "Receipt's bank was not found": "Receipt's bank was not found", "This receipt was not compensated": "This receipt was not compensated", "Client's email was not found": "Client's email was not found", - "Tickets with associated refunds": "Tickets with associated refunds can't be deleted. This ticket is associated with refund Nº {{id}}", + "Tickets with associated refunds": "Tickets with associated refunds can't be deleted. This ticket is associated with refund Nº {{id}}", "It is not possible to modify tracked sales": "It is not possible to modify tracked sales", "It is not possible to modify sales that their articles are from Floramondo": "It is not possible to modify sales that their articles are from Floramondo", - "It is not possible to modify cloned sales": "It is not possible to modify cloned sales" -} + "It is not possible to modify cloned sales": "It is not possible to modify cloned sales", + "Valid priorities: 1,2,3": "Valid priorities: 1,2,3", + "Tickets with associated refunds can't be deleted. This ticket is associated with refund Nº 2": "Tickets with associated refunds can't be deleted. This ticket is associated with refund Nº 2" +} \ No newline at end of file diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 507cc9003..563c24c05 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -266,5 +266,6 @@ "There is no assigned email for this client": "No hay correo asignado para este cliente", "This locker has already been assigned": "Esta taquilla ya ha sido asignada", "Tickets with associated refunds": "No se pueden borrar tickets con abonos asociados. Este ticket está asociado al abono Nº {{id}}", - "Not exist this branch": "La rama no existe" + "Not exist this branch": "La rama no existe", + "Insert a date range": "Inserte un rango de fechas" } diff --git a/modules/client/front/locale/es.yml b/modules/client/front/locale/es.yml index de4b91e0b..fe87b2362 100644 --- a/modules/client/front/locale/es.yml +++ b/modules/client/front/locale/es.yml @@ -63,4 +63,5 @@ Consumption: Consumo Compensation Account: Cuenta para compensar Amount to return: Cantidad a devolver Delivered amount: Cantidad entregada -Unpaid: Impagado \ No newline at end of file +Unpaid: Impagado +Unbilled tickets: Tickets sin facturar diff --git a/modules/invoiceIn/back/methods/invoice-in/specs/unbilledTickets.spec.js b/modules/invoiceIn/back/methods/invoice-in/specs/unbilledTickets.spec.js new file mode 100644 index 000000000..07e320a9f --- /dev/null +++ b/modules/invoiceIn/back/methods/invoice-in/specs/unbilledTickets.spec.js @@ -0,0 +1,47 @@ +const models = require('vn-loopback/server/server').models; + +describe('invoiceIn unbilledTickets()', () => { + it('should return all unbilled tickets in a date range', async() => { + const tx = await models.InvoiceIn.beginTransaction({}); + const options = {transaction: tx}; + const ctx = { + args: { + from: new Date().setMonth(new Date().getMonth() - 12), + to: new Date(), + filter: {} + } + }; + + try { + const result = await models.InvoiceIn.unbilledTickets(ctx, options); + + expect(result.length).toBeGreaterThan(0); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); + + it('should throw an error if a date range is not in args', async() => { + let error; + const tx = await models.InvoiceIn.beginTransaction({}); + const options = {transaction: tx}; + const ctx = { + args: { + filter: {} + } + }; + + try { + await models.InvoiceIn.unbilledTickets(ctx, options); + await tx.rollback(); + } catch (e) { + error = e; + await tx.rollback(); + } + + expect(error.message).toEqual(`Insert a date range`); + }); +}); diff --git a/modules/invoiceIn/back/methods/invoice-in/unbilledTickets.js b/modules/invoiceIn/back/methods/invoice-in/unbilledTickets.js new file mode 100644 index 000000000..3c33c8337 --- /dev/null +++ b/modules/invoiceIn/back/methods/invoice-in/unbilledTickets.js @@ -0,0 +1,112 @@ +const UserError = require('vn-loopback/util/user-error'); +const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; + +module.exports = Self => { + Self.remoteMethodCtx('unbilledTickets', { + description: 'Find all unbilled tickets', + accessType: 'READ', + accepts: [ + { + arg: 'from', + type: 'date', + description: 'From date' + }, + { + arg: 'to', + type: 'date', + description: 'To date' + }, + { + arg: 'filter', + type: 'object', + description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string' + }, + ], + returns: { + type: ['object'], + root: true + }, + http: { + path: `/unbilledTickets`, + verb: 'GET' + } + }); + + Self.unbilledTickets = async(ctx, options) => { + const conn = Self.dataSource.connector; + const args = ctx.args; + + if (!args.from || !args.to) + throw new UserError(`Insert a date range`); + + const myOptions = {}; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + const stmts = []; + let stmt; + stmts.push(`DROP TEMPORARY TABLE IF EXISTS tmp.ticket`); + + stmts.push(new ParameterizedSQL( + `CREATE TEMPORARY TABLE tmp.ticket + (KEY (ticketFk)) + ENGINE = MEMORY + SELECT id ticketFk + FROM ticket t + WHERE shipped BETWEEN ? AND ? + AND refFk IS NULL`, [args.from, args.to])); + stmts.push(`CALL vn.ticket_getTax(NULL)`); + stmts.push(`DROP TEMPORARY TABLE IF EXISTS tmp.filter`); + stmts.push(new ParameterizedSQL( + `CREATE TEMPORARY TABLE tmp.filter + ENGINE = MEMORY + SELECT + co.code company, + cou.country, + c.id clientId, + c.socialName clientSocialName, + SUM(s.quantity * s.price * ( 100 - s.discount ) / 100) amount, + negativeBase.taxableBase, + negativeBase.ticketFk, + c.isActive, + c.hasToInvoice, + c.isTaxDataChecked, + w.id comercialId, + CONCAT(w.firstName, ' ', w.lastName) comercialName + FROM vn.ticket t + JOIN vn.company co ON co.id = t.companyFk + JOIN vn.sale s ON s.ticketFk = t.id + JOIN vn.client c ON c.id = t.clientFk + JOIN vn.country cou ON cou.id = c.countryFk + LEFT JOIN vn.worker w ON w.id = c.salesPersonFk + LEFT JOIN ( + SELECT ticketFk, taxableBase + FROM tmp.ticketAmount + GROUP BY ticketFk + HAVING taxableBase < 0 + ) negativeBase ON negativeBase.ticketFk = t.id + WHERE t.shipped BETWEEN ? AND ? + AND t.refFk IS NULL + AND c.typeFk IN ('normal','trust') + GROUP BY t.clientFk + HAVING amount <> 0`, [args.from, args.to])); + + stmt = new ParameterizedSQL(` + SELECT f.* + FROM tmp.filter f`); + + stmt.merge(conn.makeWhere(args.filter.where)); + stmt.merge(conn.makeOrderBy(args.filter.order)); + + const ticketsIndex = stmts.push(stmt) - 1; + + stmts.push(`DROP TEMPORARY TABLE tmp.filter, tmp.ticket, tmp.ticketTax, tmp.ticketAmount`); + + const sql = ParameterizedSQL.join(stmts, ';'); + const result = await conn.executeStmt(sql, myOptions); + + return ticketsIndex === 0 ? result : result[ticketsIndex]; + }; +}; + diff --git a/modules/invoiceIn/back/models/invoice-in.js b/modules/invoiceIn/back/models/invoice-in.js index 95ccc7b20..05909680c 100644 --- a/modules/invoiceIn/back/models/invoice-in.js +++ b/modules/invoiceIn/back/models/invoice-in.js @@ -6,4 +6,5 @@ module.exports = Self => { require('../methods/invoice-in/getTotals')(Self); require('../methods/invoice-in/invoiceInPdf')(Self); require('../methods/invoice-in/invoiceInEmail')(Self); + require('../methods/invoice-in/unbilledTickets')(Self); }; diff --git a/modules/invoiceIn/front/index.js b/modules/invoiceIn/front/index.js index 7b6d6a77c..00a8d2c58 100644 --- a/modules/invoiceIn/front/index.js +++ b/modules/invoiceIn/front/index.js @@ -13,3 +13,4 @@ import './dueDay'; import './intrastat'; import './create'; import './log'; +import './unbilled-tickets'; diff --git a/modules/invoiceIn/front/routes.json b/modules/invoiceIn/front/routes.json index 4867b7db9..1fe1b3255 100644 --- a/modules/invoiceIn/front/routes.json +++ b/modules/invoiceIn/front/routes.json @@ -9,10 +9,8 @@ ], "menus": { "main": [ - { - "state": "invoiceIn.index", - "icon": "icon-invoice-in" - } + { "state": "invoiceIn.index", "icon": "icon-invoice-in"}, + { "state": "invoiceIn.unbilled-tickets", "icon": "icon-ticket"} ], "card": [ { @@ -54,6 +52,15 @@ "administrative" ] }, + { + "url": "/unbilled-tickets", + "state": "invoiceIn.unbilled-tickets", + "component": "vn-unbilled-tickets", + "description": "Unbilled tickets", + "acl": [ + "administrative" + ] + }, { "url": "/:id", "state": "invoiceIn.card", @@ -133,4 +140,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/modules/invoiceIn/front/unbilled-tickets/index.html b/modules/invoiceIn/front/unbilled-tickets/index.html new file mode 100644 index 000000000..57cfa5138 --- /dev/null +++ b/modules/invoiceIn/front/unbilled-tickets/index.html @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Company + + Country + + Id Client + + Client + + Amount + + Base + + Id Ticket + + Active + + Has To Invoice + + Verified data + + Id Comercial + + Comercial +
{{ticket.company | dashIfEmpty}}{{ticket.country | dashIfEmpty}}{{ticket.clientId | dashIfEmpty}}{{ticket.clientSocialName | dashIfEmpty}}{{ticket.amount | currency: 'EUR':2 | dashIfEmpty}}{{ticket.taxableBase | dashIfEmpty}}{{ticket.ticketFk | dashIfEmpty}} + + + + + + + + + {{ticket.comercialId | dashIfEmpty}}{{ticket.comercialName | dashIfEmpty}}
+
+
+
diff --git a/modules/invoiceIn/front/unbilled-tickets/index.js b/modules/invoiceIn/front/unbilled-tickets/index.js new file mode 100644 index 000000000..f71fd35b3 --- /dev/null +++ b/modules/invoiceIn/front/unbilled-tickets/index.js @@ -0,0 +1,66 @@ +import ngModule from '../module'; +import Section from 'salix/components/section'; +import './style.scss'; + +export default class Controller extends Section { + constructor($element, $) { + super($element, $); + const now = new Date(); + const firstDayOfMonth = new Date(now.getFullYear(), now.getMonth(), 1); + const lastDayOfMonth = new Date(now.getFullYear(), now.getMonth() + 1, 0); + this.params = { + from: firstDayOfMonth, + to: lastDayOfMonth + }; + this.$checkAll = false; + + this.smartTableOptions = { + activeButtons: { + search: true, + }, columns: [ + { + field: 'isActive', + searchable: false + }, + { + field: 'hasToInvoice', + searchable: false + }, + { + field: 'isTaxDataChecked', + searchable: false + }, + ] + }; + } + + exprBuilder(param, value) { + switch (param) { + case 'company': + return {'company': value}; + case 'country': + return {'country': value}; + case 'clientId': + return {'clientId': value}; + case 'clientSocialName': + return {'clientSocialName': value}; + case 'amount': + return {'amount': value}; + case 'taxableBase': + return {'taxableBase': value}; + case 'ticketFk': + return {'ticketFk': value}; + case 'comercialId': + return {'comercialId': value}; + case 'comercialName': + return {'comercialName': value}; + } + } +} + +Controller.$inject = ['$element', '$scope']; + +ngModule.vnComponent('vnUnbilledTickets', { + template: require('./index.html'), + controller: Controller +}); diff --git a/modules/invoiceIn/front/unbilled-tickets/locale/es.yml b/modules/invoiceIn/front/unbilled-tickets/locale/es.yml new file mode 100644 index 000000000..9c6c3d735 --- /dev/null +++ b/modules/invoiceIn/front/unbilled-tickets/locale/es.yml @@ -0,0 +1 @@ +Has To Invoice: Facturar diff --git a/modules/invoiceIn/front/unbilled-tickets/style.scss b/modules/invoiceIn/front/unbilled-tickets/style.scss new file mode 100644 index 000000000..ad74a0071 --- /dev/null +++ b/modules/invoiceIn/front/unbilled-tickets/style.scss @@ -0,0 +1,7 @@ +@import "./variables"; + +vn-unbilled-tickets { + vn-date-picker{ + padding-right: 5%; + } +} From 4e800a7a454022a58714da645a56e4fbf95283d9 Mon Sep 17 00:00:00 2001 From: alexandre Date: Mon, 6 Mar 2023 09:30:14 +0100 Subject: [PATCH 05/95] . --- loopback/locale/en.json | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/loopback/locale/en.json b/loopback/locale/en.json index dbe25dea3..32b5e0168 100644 --- a/loopback/locale/en.json +++ b/loopback/locale/en.json @@ -150,7 +150,5 @@ "Tickets with associated refunds": "Tickets with associated refunds can't be deleted. This ticket is associated with refund Nº {{id}}", "It is not possible to modify tracked sales": "It is not possible to modify tracked sales", "It is not possible to modify sales that their articles are from Floramondo": "It is not possible to modify sales that their articles are from Floramondo", - "It is not possible to modify cloned sales": "It is not possible to modify cloned sales", - "Valid priorities: 1,2,3": "Valid priorities: 1,2,3", - "Tickets with associated refunds can't be deleted. This ticket is associated with refund Nº 2": "Tickets with associated refunds can't be deleted. This ticket is associated with refund Nº 2" -} \ No newline at end of file + "It is not possible to modify cloned sales": "It is not possible to modify cloned sales" +} From 874fd0656c58730df7b5bef998cfe0a99972fd0c Mon Sep 17 00:00:00 2001 From: alexandre Date: Fri, 10 Mar 2023 10:05:16 +0100 Subject: [PATCH 06/95] refs #5206 url gets params --- modules/travel/front/index/index.html | 2 + modules/travel/front/search-panel/index.html | 145 ++++++++----------- modules/travel/front/search-panel/index.js | 58 +++++--- modules/travel/front/search-panel/style.scss | 5 - 4 files changed, 95 insertions(+), 115 deletions(-) diff --git a/modules/travel/front/index/index.html b/modules/travel/front/index/index.html index df7fd5611..a6952321f 100644 --- a/modules/travel/front/index/index.html +++ b/modules/travel/front/index/index.html @@ -26,6 +26,7 @@ Warehouse In Landed + Total entries @@ -61,6 +62,7 @@ ng-class="{active: travel.isReceived}"> + {{::travel.totalEntries}} - - - - + on-change="$ctrl.applyFilters()"> - - - - - - - - - - - Or -
- - -
-
- - - - - + on-change="$ctrl.applyFilters()"> + on-change="$ctrl.applyFilters()"> + + + + + + + + + + + + + + + +
Id/{{$ctrl.$t('Reference')}}: {{$ctrl.filter.search}} - - {{$ctrl.$t('Total entries')}}: {{$ctrl.filter.totalEntries}} - {{$ctrl.$t('Agency')}}: {{agency.selection.name}} - {{$ctrl.$t('Continent Out')}}: {{continent.selection.name}} + {{$ctrl.$t('Warehouse Out')}}: {{warehouseOut.selection.name}} - {{$ctrl.$t('Shipped from')}}: {{$ctrl.filter.shippedFrom | date:'dd/MM/yyyy'}} - - - {{$ctrl.$t('Shipped to')}}: {{$ctrl.filter.shippedTo | date:'dd/MM/yyyy'}} + {{$ctrl.$t('Warehouse In')}}: {{warehouseIn.selection.name}} {{$ctrl.$t('Landed to')}}: {{$ctrl.filter.landedTo | date:'dd/MM/yyyy'}} - {{$ctrl.$t('Warehouse Out')}}: {{warehouseOut.selection.name}} + {{$ctrl.$t('Continent Out')}}: {{continent.selection.name}} - {{$ctrl.$t('Warehouse In')}}: {{warehouseIn.selection.name}} + {{$ctrl.$t('Total entries')}}: {{$ctrl.filter.totalEntries}}
diff --git a/modules/travel/front/search-panel/index.js b/modules/travel/front/search-panel/index.js index 8269a7d51..9cf417da1 100644 --- a/modules/travel/front/search-panel/index.js +++ b/modules/travel/front/search-panel/index.js @@ -5,47 +5,59 @@ import './style.scss'; class Controller extends SearchPanel { constructor($, $element) { super($, $element); - this.filter = { - scopeDays: 1, - }; + this.initFilter(); + this.fetchData(); } - changeShipped() { - this.filter.scopeDays = null; - this.addFilters(); + $onChanges() { + if (this.model) + this.applyFilters(); } - changeScopeDays() { - this.filter.shippedFrom = null; - this.filter.shippedTo = null; - this.addFilters(); + fetchData() { + this.$http.get('AgencyModes').then(res => { + this.agencyModes = res.data; + }); + this.$http.get('Warehouses').then(res => { + this.warehouses = res.data; + }); + this.$http.get('Continents').then(res => { + this.continents = res.data; + }); } - addFilters(param) { - this.model.addFilter({}, this.filter) + initFilter() { + this.filter = {}; + if (this.$params.q) { + this.filter = JSON.parse(this.$params.q); + this.search = this.filter.search; + this.totalEntries = this.filter.totalEntries; + } + if (!this.filter.scopeDays) this.filter.scopeDays = 7; + } + + applyFilters(param) { + this.model.applyFilter({}, this.filter) .then(() => { - if (param) - this.checkJustOneResult(); + if (param && this.model._orgData.length === 1) + this.$state.go('travel.card.summary', {id: this.model._orgData[0].id}); + else + this.$state.go(this.$state.current.name, {q: JSON.stringify(this.filter)}, {location: 'replace'}); }); } removeParamFilter(param) { - if (this[param]) this[param] = null; - this.filter[param] = null; - this.addFilters(); + if (this[param]) delete this[param]; + delete this.filter[param]; + this.applyFilters(); } onKeyPress($event, param) { if ($event.key === 'Enter') { this.filter[param] = this[param]; - this.addFilters(param === 'search'); + this.applyFilters(param === 'search'); } } - - checkJustOneResult() { - if (this.model._orgData.length === 1) - this.$state.go('travel.card.summary', {id: this.model._orgData[0].id}); - } } ngModule.vnComponent('vnTravelSearchPanel', { diff --git a/modules/travel/front/search-panel/style.scss b/modules/travel/front/search-panel/style.scss index 4d08c1402..94fe7b239 100644 --- a/modules/travel/front/search-panel/style.scss +++ b/modules/travel/front/search-panel/style.scss @@ -33,10 +33,5 @@ vn-travel-search-panel vn-side-menu { font-size: 26px; color: $color-font-secondary; } - - .scope-days{ - display: flex; - align-items: center; - } } } From c4d6a19666f5ebdfe8af2390ca4574d777fc606e Mon Sep 17 00:00:00 2001 From: alexandre Date: Fri, 10 Mar 2023 12:49:20 +0100 Subject: [PATCH 07/95] refs #5092 download as csv button --- db/changes/231001/00-unbilledTickets.sql | 3 +- .../methods/invoice-in/unbilledTicketsCsv.js | 53 +++++++++++++++++++ modules/invoiceIn/back/models/invoice-in.js | 1 + .../front/unbilled-tickets/index.html | 28 ++++++---- .../invoiceIn/front/unbilled-tickets/index.js | 24 ++++++++- .../front/unbilled-tickets/locale/es.yml | 13 +++++ .../front/unbilled-tickets/style.scss | 3 ++ 7 files changed, 111 insertions(+), 14 deletions(-) create mode 100644 modules/invoiceIn/back/methods/invoice-in/unbilledTicketsCsv.js diff --git a/db/changes/231001/00-unbilledTickets.sql b/db/changes/231001/00-unbilledTickets.sql index d0c3fbbcb..3d2bc562b 100644 --- a/db/changes/231001/00-unbilledTickets.sql +++ b/db/changes/231001/00-unbilledTickets.sql @@ -1,3 +1,4 @@ INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES - ('InvoiceIn', 'unbilledTickets', 'READ', 'ALLOW', 'ROLE', 'administrative'); + ('InvoiceIn', 'unbilledTickets', 'READ', 'ALLOW', 'ROLE', 'administrative'), + ('InvoiceIn', 'unbilledTicketsCsv', 'READ', 'ALLOW', 'ROLE', 'administrative'); diff --git a/modules/invoiceIn/back/methods/invoice-in/unbilledTicketsCsv.js b/modules/invoiceIn/back/methods/invoice-in/unbilledTicketsCsv.js new file mode 100644 index 000000000..bd6bb8d36 --- /dev/null +++ b/modules/invoiceIn/back/methods/invoice-in/unbilledTicketsCsv.js @@ -0,0 +1,53 @@ +const {toCSV} = require('vn-loopback/util/csv'); + +module.exports = Self => { + Self.remoteMethodCtx('unbilledTicketsCsv', { + description: 'Returns the unbilled tickets as .csv', + accessType: 'READ', + accepts: [{ + arg: 'unbilledTickets', + type: ['object'], + required: true + }, + { + arg: 'from', + type: 'date', + description: 'From date' + }, + { + arg: 'to', + type: 'date', + description: 'To date' + }], + returns: [ + { + arg: 'body', + type: 'file', + root: true + }, { + arg: 'Content-Type', + type: 'String', + http: {target: 'header'} + }, { + arg: 'Content-Disposition', + type: 'String', + http: {target: 'header'} + } + ], + http: { + path: '/unbilledTicketsCsv', + verb: 'GET' + } + }); + + Self.unbilledTicketsCsv = async ctx => { + const args = ctx.args; + const content = toCSV(args.unbilledTickets); + + return [ + content, + 'text/csv', + `attachment; filename="unbilled-tickets-${new Date(args.from).toLocaleDateString()}-${new Date(args.to).toLocaleDateString()}.csv"` + ]; + }; +}; diff --git a/modules/invoiceIn/back/models/invoice-in.js b/modules/invoiceIn/back/models/invoice-in.js index 05909680c..bdd9e1b11 100644 --- a/modules/invoiceIn/back/models/invoice-in.js +++ b/modules/invoiceIn/back/models/invoice-in.js @@ -7,4 +7,5 @@ module.exports = Self => { require('../methods/invoice-in/invoiceInPdf')(Self); require('../methods/invoice-in/invoiceInEmail')(Self); require('../methods/invoice-in/unbilledTickets')(Self); + require('../methods/invoice-in/unbilledTicketsCsv')(Self); }; diff --git a/modules/invoiceIn/front/unbilled-tickets/index.html b/modules/invoiceIn/front/unbilled-tickets/index.html index 57cfa5138..eb669a015 100644 --- a/modules/invoiceIn/front/unbilled-tickets/index.html +++ b/modules/invoiceIn/front/unbilled-tickets/index.html @@ -13,17 +13,23 @@ expr-builder="$ctrl.exprBuilder(param, value)"> - - - + vn-one + label="From" + ng-model="$ctrl.params.from" + on-change="model.refresh()"> + + + + + diff --git a/modules/invoiceIn/front/unbilled-tickets/index.js b/modules/invoiceIn/front/unbilled-tickets/index.js index f71fd35b3..4d99257a7 100644 --- a/modules/invoiceIn/front/unbilled-tickets/index.js +++ b/modules/invoiceIn/front/unbilled-tickets/index.js @@ -3,8 +3,10 @@ import Section from 'salix/components/section'; import './style.scss'; export default class Controller extends Section { - constructor($element, $) { + constructor($element, $, vnReport) { super($element, $); + + this.vnReport = vnReport; const now = new Date(); const firstDayOfMonth = new Date(now.getFullYear(), now.getMonth(), 1); const lastDayOfMonth = new Date(now.getFullYear(), now.getMonth() + 1, 0); @@ -56,9 +58,27 @@ export default class Controller extends Section { return {'comercialName': value}; } } + + downloadCSV() { + const data = []; + this.$.model._orgData.forEach(element => { + data.push(Object.keys(element).map(key => { + return {newName: this.$t(key), value: element[key]}; + }).filter(item => item !== null) + .reduce((result, item) => { + result[item.newName] = item.value; + return result; + }, {})); + }); + this.vnReport.show('InvoiceIns/unbilledTicketsCsv', { + unbilledTickets: data, + from: this.params.from, + to: this.params.to + }); + } } -Controller.$inject = ['$element', '$scope']; +Controller.$inject = ['$element', '$scope', 'vnReport']; ngModule.vnComponent('vnUnbilledTickets', { template: require('./index.html'), diff --git a/modules/invoiceIn/front/unbilled-tickets/locale/es.yml b/modules/invoiceIn/front/unbilled-tickets/locale/es.yml index 9c6c3d735..9095eee22 100644 --- a/modules/invoiceIn/front/unbilled-tickets/locale/es.yml +++ b/modules/invoiceIn/front/unbilled-tickets/locale/es.yml @@ -1 +1,14 @@ Has To Invoice: Facturar +Download as CSV: Descargar como CSV +company: Compañía +country: País +clientId: Id Cliente +clientSocialName: Cliente +amount: Importe +taxableBase: Base +ticketFk: Id Ticket +isActive: Activo +hasToInvoice: Facturar +isTaxDataChecked: Datos comprobados +comercialId: Id Comercial +comercialName: Comercial diff --git a/modules/invoiceIn/front/unbilled-tickets/style.scss b/modules/invoiceIn/front/unbilled-tickets/style.scss index ad74a0071..555b25fa9 100644 --- a/modules/invoiceIn/front/unbilled-tickets/style.scss +++ b/modules/invoiceIn/front/unbilled-tickets/style.scss @@ -4,4 +4,7 @@ vn-unbilled-tickets { vn-date-picker{ padding-right: 5%; } + slot-actions{ + align-items: center; + } } From 8a4d9bd2bf88743e44f1d9bac6d9506034be3bf9 Mon Sep 17 00:00:00 2001 From: pablone Date: Fri, 10 Mar 2023 12:52:51 +0100 Subject: [PATCH 08/95] refs #5211 --- modules/item/back/models/item-shelving.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/item/back/models/item-shelving.json b/modules/item/back/models/item-shelving.json index 0890350da..339b9ab6e 100644 --- a/modules/item/back/models/item-shelving.json +++ b/modules/item/back/models/item-shelving.json @@ -20,6 +20,9 @@ }, "created": { "type": "date" + }, + "isChecked": { + "type": "boolean" } }, "relations": { From 0248c3c9e0eda364db04d4b20537b4b868faa798 Mon Sep 17 00:00:00 2001 From: alexandre Date: Mon, 13 Mar 2023 07:34:49 +0100 Subject: [PATCH 09/95] refs #5056 models and tables added --- db/changes/231001/.gitkeep | 0 db/changes/231001/00-wagon.sql | 67 +++++++++++++++++++ modules/wagon/back/model-config.json | 23 +++++++ .../wagon/back/models/collectionWagon.json | 34 ++++++++++ .../back/models/collectionWagonTicket.json | 43 ++++++++++++ modules/wagon/back/models/wagon.json | 31 +++++++++ modules/wagon/back/models/wagonConfig.json | 30 +++++++++ modules/wagon/back/models/wagonType.json | 18 +++++ modules/wagon/back/models/wagonTypeColor.json | 21 ++++++ modules/wagon/back/models/wagonTypeTray.json | 36 ++++++++++ 10 files changed, 303 insertions(+) delete mode 100644 db/changes/231001/.gitkeep create mode 100644 db/changes/231001/00-wagon.sql create mode 100644 modules/wagon/back/model-config.json create mode 100644 modules/wagon/back/models/collectionWagon.json create mode 100644 modules/wagon/back/models/collectionWagonTicket.json create mode 100644 modules/wagon/back/models/wagon.json create mode 100644 modules/wagon/back/models/wagonConfig.json create mode 100644 modules/wagon/back/models/wagonType.json create mode 100644 modules/wagon/back/models/wagonTypeColor.json create mode 100644 modules/wagon/back/models/wagonTypeTray.json diff --git a/db/changes/231001/.gitkeep b/db/changes/231001/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/db/changes/231001/00-wagon.sql b/db/changes/231001/00-wagon.sql new file mode 100644 index 000000000..cd945cc46 --- /dev/null +++ b/db/changes/231001/00-wagon.sql @@ -0,0 +1,67 @@ +CREATE TABLE `vn`.`wagonType` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(30) NOT NULL UNIQUE, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb3; + +CREATE TABLE `vn`.`wagonTypeColor` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(30) NOT NULL UNIQUE, + `rgb` varchar(30) NOT NULL UNIQUE, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb3; + +CREATE TABLE `vn`.`wagonTypeTray` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `typeFk` int(11) unsigned, + `height` int(11) unsigned, + `colorFk` int(11) unsigned, + PRIMARY KEY (`id`), + UNIQUE KEY (`typeFk`,`height`), + CONSTRAINT `wagonTypeTray_type` FOREIGN KEY (`typeFk`) REFERENCES `wagonType` (`id`) ON UPDATE CASCADE, + CONSTRAINT `wagonTypeTray_color` FOREIGN KEY (`colorFk`) REFERENCES `wagonTypeColor` (`id`) ON UPDATE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb3; + +CREATE TABLE `vn`.`wagonConfig` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `width` int(11) unsigned DEFAULT 1350, + `height` int(11) unsigned DEFAULT 1900, + `trayStep` int(11) unsigned DEFAULT 50, + `minTrayHeight` int(11) unsigned DEFAULT 200, + `maxTrays` int(11) unsigned DEFAULT 6, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb3; + +CREATE TABLE `vn`.`collectionWagon` ( + `collectionFk` int(11) NOT NULL, + `wagonFk` int(11) NOT NULL, + `position` int(11) unsigned, + PRIMARY KEY (`collectionFk`,`position`), + UNIQUE KEY `collectionWagon_unique` (`collectionFk`,`wagonFk`), + CONSTRAINT `collectionWagon_collection` FOREIGN KEY (`collectionFk`) REFERENCES `collection` (`id`) ON UPDATE CASCADE, + CONSTRAINT `collectionWagon_wagon` FOREIGN KEY (`wagonFk`) REFERENCES `wagon` (`id`) ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; + +CREATE TABLE `vn`.`collectionWagonTicket` ( + `ticketFk` int(11) NOT NULL, + `wagonFk` int(11) NOT NULL, + `trayFk` int(11) unsigned NOT NULL, + `side` SET('L', 'R') NULL, + PRIMARY KEY (`ticketFk`), + CONSTRAINT `collectionWagonTicket_ticket` FOREIGN KEY (`ticketFk`) REFERENCES `ticket` (`id`) ON UPDATE CASCADE, + CONSTRAINT `collectionWagonTicket_wagon` FOREIGN KEY (`wagonFk`) REFERENCES `wagon` (`id`) ON UPDATE CASCADE, + CONSTRAINT `collectionWagonTicket_tray` FOREIGN KEY (`trayFk`) REFERENCES `wagonTypeTray` (`id`) ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; + +ALTER TABLE `vn`.`wagon` ADD `typeFk` int(11) unsigned DEFAULT NULL; +ALTER TABLE `vn`.`wagon` ADD CONSTRAINT `wagon_type` FOREIGN KEY (`typeFk`) REFERENCES `wagonType` (`id`) ON UPDATE CASCADE; + +INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) + VALUES + ('WagonType', '*', '*', 'ALLOW', 'ROLE', 'employee'), + ('WagonTypeColor', '*', '*', 'ALLOW', 'ROLE', 'employee'), + ('WagonTypeTray', '*', '*', 'ALLOW', 'ROLE', 'employee'), + ('WagonConfig', '*', '*', 'ALLOW', 'ROLE', 'employee'), + ('CollectionWagon', '*', '*', 'ALLOW', 'ROLE', 'employee'), + ('CollectionWagonTicket', '*', '*', 'ALLOW', 'ROLE', 'employee'), + ('Wagon', '*', '*', 'ALLOW', 'ROLE', 'employee'); diff --git a/modules/wagon/back/model-config.json b/modules/wagon/back/model-config.json new file mode 100644 index 000000000..279d55e5c --- /dev/null +++ b/modules/wagon/back/model-config.json @@ -0,0 +1,23 @@ +{ + "Wagon": { + "dataSource": "vn" + }, + "WagonType": { + "dataSource": "vn" + }, + "WagonTypeColor": { + "dataSource": "vn" + }, + "WagonTypeTray": { + "dataSource": "vn" + }, + "WagonConfig": { + "dataSource": "vn" + }, + "CollectionWagon": { + "dataSource": "vn" + }, + "CollectionWagonTicket": { + "dataSource": "vn" + } +} diff --git a/modules/wagon/back/models/collectionWagon.json b/modules/wagon/back/models/collectionWagon.json new file mode 100644 index 000000000..f3f237428 --- /dev/null +++ b/modules/wagon/back/models/collectionWagon.json @@ -0,0 +1,34 @@ +{ + "name": "CollectionWagon", + "base": "VnModel", + "options": { + "mysql": { + "table": "collectionWagon" + } + }, + "properties": { + "collectionFk": { + "id": true, + "type": "number" + }, + "wagonFk": { + "type": "number", + "required": true + }, + "position": { + "type": "number" + } + }, + "relations": { + "collection": { + "type": "belongsTo", + "model": "Collection", + "foreignKey": "collectionFk" + }, + "wagon": { + "type": "belongsTo", + "model": "Wagon", + "foreignKey": "wagonFk" + } + } +} diff --git a/modules/wagon/back/models/collectionWagonTicket.json b/modules/wagon/back/models/collectionWagonTicket.json new file mode 100644 index 000000000..04527205c --- /dev/null +++ b/modules/wagon/back/models/collectionWagonTicket.json @@ -0,0 +1,43 @@ +{ + "name": "CollectionWagonTicket", + "base": "VnModel", + "options": { + "mysql": { + "table": "collectionWagonTicket" + } + }, + "properties": { + "ticketFk": { + "id": true, + "type": "number" + }, + "wagonFk": { + "type": "number", + "required": true + }, + "trayFk": { + "type": "number", + "required": true + }, + "side": { + "type": "string" + } + }, + "relations": { + "ticket": { + "type": "belongsTo", + "model": "Ticket", + "foreignKey": "ticketFk" + }, + "wagon": { + "type": "belongsTo", + "model": "Wagon", + "foreignKey": "wagonFk" + }, + "tray": { + "type": "belongsTo", + "model": "WagonTypeTray", + "foreignKey": "trayFk" + } + } +} diff --git a/modules/wagon/back/models/wagon.json b/modules/wagon/back/models/wagon.json new file mode 100644 index 000000000..81b9f23e6 --- /dev/null +++ b/modules/wagon/back/models/wagon.json @@ -0,0 +1,31 @@ +{ + "name": "Wagon", + "base": "VnModel", + "options": { + "mysql": { + "table": "wagon" + } + }, + "properties": { + "id": { + "id": true, + "type": "number" + }, + "volume": { + "type": "number" + }, + "plate": { + "type": "string" + }, + "typeFk": { + "type": "number" + } + }, + "relations": { + "type": { + "type": "belongsTo", + "model": "WagonType", + "foreignKey": "typeFk" + } + } +} diff --git a/modules/wagon/back/models/wagonConfig.json b/modules/wagon/back/models/wagonConfig.json new file mode 100644 index 000000000..ee33f312e --- /dev/null +++ b/modules/wagon/back/models/wagonConfig.json @@ -0,0 +1,30 @@ +{ + "name": "WagonConfig", + "base": "VnModel", + "options": { + "mysql": { + "table": "wagonConfig" + } + }, + "properties": { + "id": { + "id": true, + "type": "number" + }, + "width": { + "type": "number" + }, + "height": { + "type": "string" + }, + "trayStep": { + "type": "number" + }, + "minTrayHeight": { + "type": "number" + }, + "maxTrays": { + "type": "number" + } + } +} diff --git a/modules/wagon/back/models/wagonType.json b/modules/wagon/back/models/wagonType.json new file mode 100644 index 000000000..feb8d046c --- /dev/null +++ b/modules/wagon/back/models/wagonType.json @@ -0,0 +1,18 @@ +{ + "name": "WagonType", + "base": "VnModel", + "options": { + "mysql": { + "table": "wagonType" + } + }, + "properties": { + "id": { + "id": true, + "type": "number" + }, + "name": { + "type": "string" + } + } +} diff --git a/modules/wagon/back/models/wagonTypeColor.json b/modules/wagon/back/models/wagonTypeColor.json new file mode 100644 index 000000000..573fd60f5 --- /dev/null +++ b/modules/wagon/back/models/wagonTypeColor.json @@ -0,0 +1,21 @@ +{ + "name": "WagonTypeColor", + "base": "VnModel", + "options": { + "mysql": { + "table": "wagonTypeColor" + } + }, + "properties": { + "id": { + "id": true, + "type": "number" + }, + "name": { + "type": "string" + }, + "rgb": { + "type": "string" + } + } +} diff --git a/modules/wagon/back/models/wagonTypeTray.json b/modules/wagon/back/models/wagonTypeTray.json new file mode 100644 index 000000000..b61510bcf --- /dev/null +++ b/modules/wagon/back/models/wagonTypeTray.json @@ -0,0 +1,36 @@ +{ + "name": "WagonTypeTray", + "base": "VnModel", + "options": { + "mysql": { + "table": "wagonTypeTray" + } + }, + "properties": { + "id": { + "id": true, + "type": "number" + }, + "typeFk": { + "type": "number" + }, + "height": { + "type": "number" + }, + "colorFk": { + "type": "number" + } + }, + "relations": { + "type": { + "type": "belongsTo", + "model": "WagonType", + "foreignKey": "typeFk" + }, + "color": { + "type": "belongsTo", + "model": "WagonTypeColor", + "foreignKey": "colorFk" + } + } +} From 38bf49c0b60cfb6d3eb637775b234ca4bb8a5e0b Mon Sep 17 00:00:00 2001 From: vicent Date: Wed, 15 Mar 2023 08:40:53 +0100 Subject: [PATCH 10/95] refs #5410 fix: se mantenien los checkbox marcados al paginar --- modules/client/front/defaulter/index.html | 32 ++++++++++++----------- modules/client/front/defaulter/index.js | 14 ++++++++++ 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/modules/client/front/defaulter/index.html b/modules/client/front/defaulter/index.html index 22b78594a..8f22629a9 100644 --- a/modules/client/front/defaulter/index.html +++ b/modules/client/front/defaulter/index.html @@ -5,6 +5,7 @@ limit="20" order="amount DESC" data="defaulters" + on-data-change="$ctrl.reCheck()" auto-load="true"> @@ -17,22 +18,22 @@ -
Total
-
-
@@ -56,25 +57,25 @@ - - - - @@ -150,7 +152,7 @@ - + @@ -160,7 +162,7 @@ id !== clientId) : [...this.checkedDefaulers, clientId]; + } + + reCheck() { + if (!this.$.model.data || !this.checkedDefaulers.length) return; + + this.$.model.data.forEach(defaulter => { + defaulter.checked = this.checkedDefaulers.includes(defaulter.clientFk); + }); + } + getBalanceDueTotal() { this.$http.get('Defaulters/filter') .then(res => { From 6a2542758b70bb33495c40a376b194e8e1411214 Mon Sep 17 00:00:00 2001 From: alexandre Date: Wed, 15 Mar 2023 10:29:44 +0100 Subject: [PATCH 11/95] refs #5056 added fixtures --- modules/item/front/diary/index.html | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/modules/item/front/diary/index.html b/modules/item/front/diary/index.html index 0f00f5854..e29e76afa 100644 --- a/modules/item/front/diary/index.html +++ b/modules/item/front/diary/index.html @@ -16,15 +16,15 @@ - - + + @@ -44,7 +44,7 @@ - {{::sale.shipped | date:'dd/MM/yyyy' }} @@ -99,13 +99,13 @@ - - - From 53bca1e8a302d1939f39d2b80a93644a431954b7 Mon Sep 17 00:00:00 2001 From: alexandre Date: Wed, 15 Mar 2023 11:36:10 +0100 Subject: [PATCH 12/95] refs #5056 added fixtures --- db/dump/fixtures.sql | 11 +++++++++++ modules/item/front/diary/index.html | 28 ++++++++++++++-------------- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 80983a318..488285b6b 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -2821,4 +2821,15 @@ INSERT INTO `vn`.`deviceProductionUser` (`deviceProductionFk`, `userFk`, `create (1, 1, util.VN_NOW()), (3, 3, util.VN_NOW()); +INSERT INTO `vn`.`wagonConfig` (`id`, `width`, `height`, `trayStep`, `minTrayHeight`, `maxTrays`) + VALUES + (1, 1350, 1900, 50, 200, 6); + + +INSERT INTO `vn`.`wagonTypeColor` (`id`, `name`, `rgb`) + VALUES + (1, 'red', '#ff0000'), + (2, 'green', '#00ff00'), + (3, 'blue', '#0000ff'); + diff --git a/modules/item/front/diary/index.html b/modules/item/front/diary/index.html index e29e76afa..0f00f5854 100644 --- a/modules/item/front/diary/index.html +++ b/modules/item/front/diary/index.html @@ -16,15 +16,15 @@ - - + + @@ -44,7 +44,7 @@ - {{::sale.shipped | date:'dd/MM/yyyy' }} @@ -99,13 +99,13 @@ - - - From f706b66efcb270f37f17cffcfa4f046eb234702c Mon Sep 17 00:00:00 2001 From: alexandre Date: Wed, 15 Mar 2023 11:57:09 +0100 Subject: [PATCH 13/95] refs #5056 added divisible in wagonType --- db/changes/231001/00-wagon.sql | 4 ++-- db/dump/fixtures.sql | 4 ++-- ...ollectionWagonTicket.json => collection-wagon-ticket.json} | 0 .../models/{collectionWagon.json => collection-wagon.json} | 0 .../wagon/back/models/{wagonConfig.json => wagon-config.json} | 3 --- .../models/{wagonTypeColor.json => wagon-type-color.json} | 0 .../back/models/{wagonTypeTray.json => wagon-type-tray.json} | 0 modules/wagon/back/models/{wagonType.json => wagon-type.json} | 3 +++ 8 files changed, 7 insertions(+), 7 deletions(-) rename modules/wagon/back/models/{collectionWagonTicket.json => collection-wagon-ticket.json} (100%) rename modules/wagon/back/models/{collectionWagon.json => collection-wagon.json} (100%) rename modules/wagon/back/models/{wagonConfig.json => wagon-config.json} (88%) rename modules/wagon/back/models/{wagonTypeColor.json => wagon-type-color.json} (100%) rename modules/wagon/back/models/{wagonTypeTray.json => wagon-type-tray.json} (100%) rename modules/wagon/back/models/{wagonType.json => wagon-type.json} (82%) diff --git a/db/changes/231001/00-wagon.sql b/db/changes/231001/00-wagon.sql index cd945cc46..5249c1faf 100644 --- a/db/changes/231001/00-wagon.sql +++ b/db/changes/231001/00-wagon.sql @@ -1,6 +1,7 @@ CREATE TABLE `vn`.`wagonType` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(30) NOT NULL UNIQUE, + `divisible` tinyint(1) NOT NULL DEFAULT 0, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb3; @@ -26,8 +27,7 @@ CREATE TABLE `vn`.`wagonConfig` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `width` int(11) unsigned DEFAULT 1350, `height` int(11) unsigned DEFAULT 1900, - `trayStep` int(11) unsigned DEFAULT 50, - `minTrayHeight` int(11) unsigned DEFAULT 200, + `minTrayHeight` int(11) unsigned DEFAULT 50, `maxTrays` int(11) unsigned DEFAULT 6, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb3; diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 488285b6b..302d16d76 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -2821,9 +2821,9 @@ INSERT INTO `vn`.`deviceProductionUser` (`deviceProductionFk`, `userFk`, `create (1, 1, util.VN_NOW()), (3, 3, util.VN_NOW()); -INSERT INTO `vn`.`wagonConfig` (`id`, `width`, `height`, `trayStep`, `minTrayHeight`, `maxTrays`) +INSERT INTO `vn`.`wagonConfig` (`id`, `width`, `height`, `minTrayHeight`, `maxTrays`) VALUES - (1, 1350, 1900, 50, 200, 6); + (1, 1350, 1900, 50, 6); INSERT INTO `vn`.`wagonTypeColor` (`id`, `name`, `rgb`) diff --git a/modules/wagon/back/models/collectionWagonTicket.json b/modules/wagon/back/models/collection-wagon-ticket.json similarity index 100% rename from modules/wagon/back/models/collectionWagonTicket.json rename to modules/wagon/back/models/collection-wagon-ticket.json diff --git a/modules/wagon/back/models/collectionWagon.json b/modules/wagon/back/models/collection-wagon.json similarity index 100% rename from modules/wagon/back/models/collectionWagon.json rename to modules/wagon/back/models/collection-wagon.json diff --git a/modules/wagon/back/models/wagonConfig.json b/modules/wagon/back/models/wagon-config.json similarity index 88% rename from modules/wagon/back/models/wagonConfig.json rename to modules/wagon/back/models/wagon-config.json index ee33f312e..8bad354f7 100644 --- a/modules/wagon/back/models/wagonConfig.json +++ b/modules/wagon/back/models/wagon-config.json @@ -17,9 +17,6 @@ "height": { "type": "string" }, - "trayStep": { - "type": "number" - }, "minTrayHeight": { "type": "number" }, diff --git a/modules/wagon/back/models/wagonTypeColor.json b/modules/wagon/back/models/wagon-type-color.json similarity index 100% rename from modules/wagon/back/models/wagonTypeColor.json rename to modules/wagon/back/models/wagon-type-color.json diff --git a/modules/wagon/back/models/wagonTypeTray.json b/modules/wagon/back/models/wagon-type-tray.json similarity index 100% rename from modules/wagon/back/models/wagonTypeTray.json rename to modules/wagon/back/models/wagon-type-tray.json diff --git a/modules/wagon/back/models/wagonType.json b/modules/wagon/back/models/wagon-type.json similarity index 82% rename from modules/wagon/back/models/wagonType.json rename to modules/wagon/back/models/wagon-type.json index feb8d046c..f57bf957d 100644 --- a/modules/wagon/back/models/wagonType.json +++ b/modules/wagon/back/models/wagon-type.json @@ -13,6 +13,9 @@ }, "name": { "type": "string" + }, + "divisible": { + "type": "boolean" } } } From 6609cce06521d4843f4d586a0d89dfafa737b23f Mon Sep 17 00:00:00 2001 From: alexandre Date: Wed, 15 Mar 2023 12:14:58 +0100 Subject: [PATCH 14/95] refs #5056 minHeightBetweenTrays --- db/changes/231001/00-wagon.sql | 3 ++- db/dump/fixtures.sql | 5 +++-- modules/wagon/back/models/wagon-config.json | 5 ++++- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/db/changes/231001/00-wagon.sql b/db/changes/231001/00-wagon.sql index 5249c1faf..c7725ab4f 100644 --- a/db/changes/231001/00-wagon.sql +++ b/db/changes/231001/00-wagon.sql @@ -27,7 +27,8 @@ CREATE TABLE `vn`.`wagonConfig` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `width` int(11) unsigned DEFAULT 1350, `height` int(11) unsigned DEFAULT 1900, - `minTrayHeight` int(11) unsigned DEFAULT 50, + `maxWagonHeight` int(11) unsigned DEFAULT 200, + `minHeightBetweenTrays` int(11) unsigned DEFAULT 50, `maxTrays` int(11) unsigned DEFAULT 6, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb3; diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 302d16d76..45f90359e 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -2821,9 +2821,10 @@ INSERT INTO `vn`.`deviceProductionUser` (`deviceProductionFk`, `userFk`, `create (1, 1, util.VN_NOW()), (3, 3, util.VN_NOW()); -INSERT INTO `vn`.`wagonConfig` (`id`, `width`, `height`, `minTrayHeight`, `maxTrays`) +INSERT INTO `vn`.`wagonConfig` (`id`, `width`, `height`, `maxWagonHeight`, `minHeightBetweenTrays`, `maxTrays`) VALUES - (1, 1350, 1900, 50, 6); + (1, 1350, 1900, 200, 50, 6); + INSERT INTO `vn`.`wagonTypeColor` (`id`, `name`, `rgb`) diff --git a/modules/wagon/back/models/wagon-config.json b/modules/wagon/back/models/wagon-config.json index 8bad354f7..3d96e2864 100644 --- a/modules/wagon/back/models/wagon-config.json +++ b/modules/wagon/back/models/wagon-config.json @@ -17,7 +17,10 @@ "height": { "type": "string" }, - "minTrayHeight": { + "maxWagonHeight": { + "type": "number" + }, + "minHeightBetweenTrays": { "type": "number" }, "maxTrays": { From c46e15c8e463368135adff134285f2a287935e34 Mon Sep 17 00:00:00 2001 From: alexandre Date: Thu, 16 Mar 2023 09:35:00 +0100 Subject: [PATCH 15/95] refs #5092 changed section name --- db/changes/231201/.gitkeep | 0 .../00-unbilledClients.sql} | 4 +-- ...ts.spec.js => 05_unbilled_clients.spec.js} | 8 +++--- modules/client/front/locale/es.yml | 1 - ...ickets.spec.js => unbilledClients.spec.js} | 8 +++--- ...{unbilledTickets.js => unbilledClients.js} | 12 ++++---- ...ledTicketsCsv.js => unbilledClientsCsv.js} | 14 +++++----- modules/invoiceIn/back/models/invoice-in.js | 4 +-- modules/invoiceIn/front/index.js | 2 +- modules/invoiceIn/front/locale/es.yml | 1 + modules/invoiceIn/front/routes.json | 10 +++---- .../index.html | 28 +++++++++---------- .../index.js | 6 ++-- .../locale/es.yml | 0 .../style.scss | 2 +- 15 files changed, 50 insertions(+), 50 deletions(-) delete mode 100644 db/changes/231201/.gitkeep rename db/changes/{231001/00-unbilledTickets.sql => 231201/00-unbilledClients.sql} (56%) rename e2e/paths/09-invoice-in/{05_unbilled_tickets.spec.js => 05_unbilled_clients.spec.js} (71%) rename modules/invoiceIn/back/methods/invoice-in/specs/{unbilledTickets.spec.js => unbilledClients.spec.js} (82%) rename modules/invoiceIn/back/methods/invoice-in/{unbilledTickets.js => unbilledClients.js} (92%) rename modules/invoiceIn/back/methods/invoice-in/{unbilledTicketsCsv.js => unbilledClientsCsv.js} (75%) rename modules/invoiceIn/front/{unbilled-tickets => unbilled-clients}/index.html (80%) rename modules/invoiceIn/front/{unbilled-tickets => unbilled-clients}/index.js (94%) rename modules/invoiceIn/front/{unbilled-tickets => unbilled-clients}/locale/es.yml (100%) rename modules/invoiceIn/front/{unbilled-tickets => unbilled-clients}/style.scss (85%) diff --git a/db/changes/231201/.gitkeep b/db/changes/231201/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/db/changes/231001/00-unbilledTickets.sql b/db/changes/231201/00-unbilledClients.sql similarity index 56% rename from db/changes/231001/00-unbilledTickets.sql rename to db/changes/231201/00-unbilledClients.sql index 3d2bc562b..16127dd18 100644 --- a/db/changes/231001/00-unbilledTickets.sql +++ b/db/changes/231201/00-unbilledClients.sql @@ -1,4 +1,4 @@ INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES - ('InvoiceIn', 'unbilledTickets', 'READ', 'ALLOW', 'ROLE', 'administrative'), - ('InvoiceIn', 'unbilledTicketsCsv', 'READ', 'ALLOW', 'ROLE', 'administrative'); + ('InvoiceIn', 'unbilledClients', 'READ', 'ALLOW', 'ROLE', 'administrative'), + ('InvoiceIn', 'unbilledClientsCsv', 'READ', 'ALLOW', 'ROLE', 'administrative'); diff --git a/e2e/paths/09-invoice-in/05_unbilled_tickets.spec.js b/e2e/paths/09-invoice-in/05_unbilled_clients.spec.js similarity index 71% rename from e2e/paths/09-invoice-in/05_unbilled_tickets.spec.js rename to e2e/paths/09-invoice-in/05_unbilled_clients.spec.js index dd75d0b49..629f24404 100644 --- a/e2e/paths/09-invoice-in/05_unbilled_tickets.spec.js +++ b/e2e/paths/09-invoice-in/05_unbilled_clients.spec.js @@ -1,6 +1,6 @@ import getBrowser from '../../helpers/puppeteer'; -describe('InvoiceIn unbilled tickets path', () => { +describe('InvoiceIn unbilled clients path', () => { let browser; let page; const httpRequests = []; @@ -9,18 +9,18 @@ describe('InvoiceIn unbilled tickets path', () => { browser = await getBrowser(); page = browser.page; page.on('request', req => { - if (req.url().includes(`InvoiceIns/unbilledTickets`)) + if (req.url().includes(`InvoiceIns/unbilledClients`)) httpRequests.push(req.url()); }); await page.loginAndModule('administrative', 'invoiceIn'); - await page.accessToSection('invoiceIn.unbilled-tickets'); + await page.accessToSection('invoiceIn.unbilled-clients'); }); afterAll(async() => { await browser.close(); }); - it('should show unbilled tickets in a date range', async() => { + it('should show unbilled clients in a date range', async() => { const request = httpRequests.find(req => req.includes(`from`) && req.includes(`to`)); diff --git a/modules/client/front/locale/es.yml b/modules/client/front/locale/es.yml index fe87b2362..adbca8dbf 100644 --- a/modules/client/front/locale/es.yml +++ b/modules/client/front/locale/es.yml @@ -64,4 +64,3 @@ Compensation Account: Cuenta para compensar Amount to return: Cantidad a devolver Delivered amount: Cantidad entregada Unpaid: Impagado -Unbilled tickets: Tickets sin facturar diff --git a/modules/invoiceIn/back/methods/invoice-in/specs/unbilledTickets.spec.js b/modules/invoiceIn/back/methods/invoice-in/specs/unbilledClients.spec.js similarity index 82% rename from modules/invoiceIn/back/methods/invoice-in/specs/unbilledTickets.spec.js rename to modules/invoiceIn/back/methods/invoice-in/specs/unbilledClients.spec.js index 07e320a9f..fcb3173ab 100644 --- a/modules/invoiceIn/back/methods/invoice-in/specs/unbilledTickets.spec.js +++ b/modules/invoiceIn/back/methods/invoice-in/specs/unbilledClients.spec.js @@ -1,7 +1,7 @@ const models = require('vn-loopback/server/server').models; -describe('invoiceIn unbilledTickets()', () => { - it('should return all unbilled tickets in a date range', async() => { +describe('invoiceIn unbilledClients()', () => { + it('should return all unbilled clients in a date range', async() => { const tx = await models.InvoiceIn.beginTransaction({}); const options = {transaction: tx}; const ctx = { @@ -13,7 +13,7 @@ describe('invoiceIn unbilledTickets()', () => { }; try { - const result = await models.InvoiceIn.unbilledTickets(ctx, options); + const result = await models.InvoiceIn.unbilledClients(ctx, options); expect(result.length).toBeGreaterThan(0); @@ -35,7 +35,7 @@ describe('invoiceIn unbilledTickets()', () => { }; try { - await models.InvoiceIn.unbilledTickets(ctx, options); + await models.InvoiceIn.unbilledClients(ctx, options); await tx.rollback(); } catch (e) { error = e; diff --git a/modules/invoiceIn/back/methods/invoice-in/unbilledTickets.js b/modules/invoiceIn/back/methods/invoice-in/unbilledClients.js similarity index 92% rename from modules/invoiceIn/back/methods/invoice-in/unbilledTickets.js rename to modules/invoiceIn/back/methods/invoice-in/unbilledClients.js index 3c33c8337..ad39bc547 100644 --- a/modules/invoiceIn/back/methods/invoice-in/unbilledTickets.js +++ b/modules/invoiceIn/back/methods/invoice-in/unbilledClients.js @@ -2,8 +2,8 @@ const UserError = require('vn-loopback/util/user-error'); const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; module.exports = Self => { - Self.remoteMethodCtx('unbilledTickets', { - description: 'Find all unbilled tickets', + Self.remoteMethodCtx('unbilledClients', { + description: 'Find all unbilled clients', accessType: 'READ', accepts: [ { @@ -27,12 +27,12 @@ module.exports = Self => { root: true }, http: { - path: `/unbilledTickets`, + path: `/unbilledClients`, verb: 'GET' } }); - Self.unbilledTickets = async(ctx, options) => { + Self.unbilledClients = async(ctx, options) => { const conn = Self.dataSource.connector; const args = ctx.args; @@ -99,14 +99,14 @@ module.exports = Self => { stmt.merge(conn.makeWhere(args.filter.where)); stmt.merge(conn.makeOrderBy(args.filter.order)); - const ticketsIndex = stmts.push(stmt) - 1; + const clientsIndex = stmts.push(stmt) - 1; stmts.push(`DROP TEMPORARY TABLE tmp.filter, tmp.ticket, tmp.ticketTax, tmp.ticketAmount`); const sql = ParameterizedSQL.join(stmts, ';'); const result = await conn.executeStmt(sql, myOptions); - return ticketsIndex === 0 ? result : result[ticketsIndex]; + return clientsIndex === 0 ? result : result[clientsIndex]; }; }; diff --git a/modules/invoiceIn/back/methods/invoice-in/unbilledTicketsCsv.js b/modules/invoiceIn/back/methods/invoice-in/unbilledClientsCsv.js similarity index 75% rename from modules/invoiceIn/back/methods/invoice-in/unbilledTicketsCsv.js rename to modules/invoiceIn/back/methods/invoice-in/unbilledClientsCsv.js index bd6bb8d36..f9b30d83b 100644 --- a/modules/invoiceIn/back/methods/invoice-in/unbilledTicketsCsv.js +++ b/modules/invoiceIn/back/methods/invoice-in/unbilledClientsCsv.js @@ -1,11 +1,11 @@ const {toCSV} = require('vn-loopback/util/csv'); module.exports = Self => { - Self.remoteMethodCtx('unbilledTicketsCsv', { - description: 'Returns the unbilled tickets as .csv', + Self.remoteMethodCtx('unbilledClientsCsv', { + description: 'Returns the unbilled clients as .csv', accessType: 'READ', accepts: [{ - arg: 'unbilledTickets', + arg: 'unbilledClients', type: ['object'], required: true }, @@ -35,19 +35,19 @@ module.exports = Self => { } ], http: { - path: '/unbilledTicketsCsv', + path: '/unbilledClientsCsv', verb: 'GET' } }); - Self.unbilledTicketsCsv = async ctx => { + Self.unbilledClientsCsv = async ctx => { const args = ctx.args; - const content = toCSV(args.unbilledTickets); + const content = toCSV(args.unbilledClients); return [ content, 'text/csv', - `attachment; filename="unbilled-tickets-${new Date(args.from).toLocaleDateString()}-${new Date(args.to).toLocaleDateString()}.csv"` + `attachment; filename="unbilled-clients-${new Date(args.from).toLocaleDateString()}-${new Date(args.to).toLocaleDateString()}.csv"` ]; }; }; diff --git a/modules/invoiceIn/back/models/invoice-in.js b/modules/invoiceIn/back/models/invoice-in.js index bdd9e1b11..ebb2981e1 100644 --- a/modules/invoiceIn/back/models/invoice-in.js +++ b/modules/invoiceIn/back/models/invoice-in.js @@ -6,6 +6,6 @@ module.exports = Self => { require('../methods/invoice-in/getTotals')(Self); require('../methods/invoice-in/invoiceInPdf')(Self); require('../methods/invoice-in/invoiceInEmail')(Self); - require('../methods/invoice-in/unbilledTickets')(Self); - require('../methods/invoice-in/unbilledTicketsCsv')(Self); + require('../methods/invoice-in/unbilledClients')(Self); + require('../methods/invoice-in/unbilledClientsCsv')(Self); }; diff --git a/modules/invoiceIn/front/index.js b/modules/invoiceIn/front/index.js index 00a8d2c58..7576848bf 100644 --- a/modules/invoiceIn/front/index.js +++ b/modules/invoiceIn/front/index.js @@ -13,4 +13,4 @@ import './dueDay'; import './intrastat'; import './create'; import './log'; -import './unbilled-tickets'; +import './unbilled-clients'; diff --git a/modules/invoiceIn/front/locale/es.yml b/modules/invoiceIn/front/locale/es.yml index 35b43f9f6..2b444f75b 100644 --- a/modules/invoiceIn/front/locale/es.yml +++ b/modules/invoiceIn/front/locale/es.yml @@ -22,3 +22,4 @@ Total stems: Total tallos Show agricultural receipt as PDF: Ver recibo agrícola como PDF Send agricultural receipt as PDF: Enviar recibo agrícola como PDF New InvoiceIn: Nueva Factura +Unbilled clients: Clientes sin facturar diff --git a/modules/invoiceIn/front/routes.json b/modules/invoiceIn/front/routes.json index 1fe1b3255..567323571 100644 --- a/modules/invoiceIn/front/routes.json +++ b/modules/invoiceIn/front/routes.json @@ -10,7 +10,7 @@ "menus": { "main": [ { "state": "invoiceIn.index", "icon": "icon-invoice-in"}, - { "state": "invoiceIn.unbilled-tickets", "icon": "icon-ticket"} + { "state": "invoiceIn.unbilled-clients", "icon": "person"} ], "card": [ { @@ -53,10 +53,10 @@ ] }, { - "url": "/unbilled-tickets", - "state": "invoiceIn.unbilled-tickets", - "component": "vn-unbilled-tickets", - "description": "Unbilled tickets", + "url": "/unbilled-clients", + "state": "invoiceIn.unbilled-clients", + "component": "vn-unbilled-clients", + "description": "Unbilled clients", "acl": [ "administrative" ] diff --git a/modules/invoiceIn/front/unbilled-tickets/index.html b/modules/invoiceIn/front/unbilled-clients/index.html similarity index 80% rename from modules/invoiceIn/front/unbilled-tickets/index.html rename to modules/invoiceIn/front/unbilled-clients/index.html index eb669a015..514f1e8ff 100644 --- a/modules/invoiceIn/front/unbilled-tickets/index.html +++ b/modules/invoiceIn/front/unbilled-clients/index.html @@ -1,6 +1,6 @@ @@ -74,34 +74,34 @@ - - - - - - - - + + + + + + + + - - + +
- Comercial Balance D. Author Last observation L. O. Date @@ -88,8 +89,9 @@
-
{{ticket.company | dashIfEmpty}}{{ticket.country | dashIfEmpty}}{{ticket.clientId | dashIfEmpty}}{{ticket.clientSocialName | dashIfEmpty}}{{ticket.amount | currency: 'EUR':2 | dashIfEmpty}}{{ticket.taxableBase | dashIfEmpty}}{{ticket.ticketFk | dashIfEmpty}}
{{client.company | dashIfEmpty}}{{client.country | dashIfEmpty}}{{client.clientId | dashIfEmpty}}{{client.clientSocialName | dashIfEmpty}}{{client.amount | currency: 'EUR':2 | dashIfEmpty}}{{client.taxableBase | dashIfEmpty}}{{client.ticketFk | dashIfEmpty}} + ng-model="client.isActive"> + ng-model="client.hasToInvoice"> + ng-model="client.isTaxDataChecked"> {{ticket.comercialId | dashIfEmpty}}{{ticket.comercialName | dashIfEmpty}}{{client.comercialId | dashIfEmpty}}{{client.comercialName | dashIfEmpty}}
diff --git a/modules/invoiceIn/front/unbilled-tickets/index.js b/modules/invoiceIn/front/unbilled-clients/index.js similarity index 94% rename from modules/invoiceIn/front/unbilled-tickets/index.js rename to modules/invoiceIn/front/unbilled-clients/index.js index 4d99257a7..a53872f8b 100644 --- a/modules/invoiceIn/front/unbilled-tickets/index.js +++ b/modules/invoiceIn/front/unbilled-clients/index.js @@ -70,8 +70,8 @@ export default class Controller extends Section { return result; }, {})); }); - this.vnReport.show('InvoiceIns/unbilledTicketsCsv', { - unbilledTickets: data, + this.vnReport.show('InvoiceIns/unbilledClientsCsv', { + unbilledClients: data, from: this.params.from, to: this.params.to }); @@ -80,7 +80,7 @@ export default class Controller extends Section { Controller.$inject = ['$element', '$scope', 'vnReport']; -ngModule.vnComponent('vnUnbilledTickets', { +ngModule.vnComponent('vnUnbilledClients', { template: require('./index.html'), controller: Controller }); diff --git a/modules/invoiceIn/front/unbilled-tickets/locale/es.yml b/modules/invoiceIn/front/unbilled-clients/locale/es.yml similarity index 100% rename from modules/invoiceIn/front/unbilled-tickets/locale/es.yml rename to modules/invoiceIn/front/unbilled-clients/locale/es.yml diff --git a/modules/invoiceIn/front/unbilled-tickets/style.scss b/modules/invoiceIn/front/unbilled-clients/style.scss similarity index 85% rename from modules/invoiceIn/front/unbilled-tickets/style.scss rename to modules/invoiceIn/front/unbilled-clients/style.scss index 555b25fa9..dbed8b967 100644 --- a/modules/invoiceIn/front/unbilled-tickets/style.scss +++ b/modules/invoiceIn/front/unbilled-clients/style.scss @@ -1,6 +1,6 @@ @import "./variables"; -vn-unbilled-tickets { +vn-unbilled-clients { vn-date-picker{ padding-right: 5%; } From 3f356335db93ac0945f034294bfdf03fbdac145d Mon Sep 17 00:00:00 2001 From: alexandre Date: Thu, 16 Mar 2023 09:47:58 +0100 Subject: [PATCH 16/95] refs #5092 added popovers --- .../front/unbilled-clients/index.html | 49 ++++++++++++++----- .../invoiceIn/front/unbilled-clients/index.js | 2 - 2 files changed, 36 insertions(+), 15 deletions(-) diff --git a/modules/invoiceIn/front/unbilled-clients/index.html b/modules/invoiceIn/front/unbilled-clients/index.html index 514f1e8ff..c4c561191 100644 --- a/modules/invoiceIn/front/unbilled-clients/index.html +++ b/modules/invoiceIn/front/unbilled-clients/index.html @@ -56,18 +56,15 @@ Id Ticket - + Active - + Has To Invoice - + Verified data - - Id Comercial - Comercial @@ -77,34 +74,60 @@ {{client.company | dashIfEmpty}} {{client.country | dashIfEmpty}} - {{client.clientId | dashIfEmpty}} + + + {{::client.clientId | dashIfEmpty}} + + {{client.clientSocialName | dashIfEmpty}} {{client.amount | currency: 'EUR':2 | dashIfEmpty}} {{client.taxableBase | dashIfEmpty}} - {{client.ticketFk | dashIfEmpty}} - + + + {{::client.ticketFk | dashIfEmpty}} + + + - + - + - {{client.comercialId | dashIfEmpty}} - {{client.comercialName | dashIfEmpty}} + + + {{::client.comercialName | dashIfEmpty}} + +
+ + + + + + diff --git a/modules/invoiceIn/front/unbilled-clients/index.js b/modules/invoiceIn/front/unbilled-clients/index.js index a53872f8b..b1f55abac 100644 --- a/modules/invoiceIn/front/unbilled-clients/index.js +++ b/modules/invoiceIn/front/unbilled-clients/index.js @@ -52,8 +52,6 @@ export default class Controller extends Section { return {'taxableBase': value}; case 'ticketFk': return {'ticketFk': value}; - case 'comercialId': - return {'comercialId': value}; case 'comercialName': return {'comercialName': value}; } From 1cd768f7b87e74387b9fa7da9c86cf983d24359f Mon Sep 17 00:00:00 2001 From: alexandre Date: Thu, 16 Mar 2023 10:39:02 +0100 Subject: [PATCH 17/95] refs #5056 moved sql --- db/changes/231201/.gitkeep | 0 db/changes/{231001 => 231201}/00-wagon.sql | 0 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 db/changes/231201/.gitkeep rename db/changes/{231001 => 231201}/00-wagon.sql (100%) diff --git a/db/changes/231201/.gitkeep b/db/changes/231201/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/db/changes/231001/00-wagon.sql b/db/changes/231201/00-wagon.sql similarity index 100% rename from db/changes/231001/00-wagon.sql rename to db/changes/231201/00-wagon.sql From bc47fc35d6c650ae3fec65a6b9b1e33b64296ffa Mon Sep 17 00:00:00 2001 From: vicent Date: Thu, 16 Mar 2023 13:55:21 +0100 Subject: [PATCH 18/95] =?UTF-8?q?refs=20#5410=20feat:=20a=C3=B1adido=20fil?= =?UTF-8?q?tro=20a=20las=20columnas=20created=20y=20defaulterSinced?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/client/front/defaulter/index.js | 21 ++++++++++++++++++-- modules/client/front/defaulter/index.spec.js | 18 +++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/modules/client/front/defaulter/index.js b/modules/client/front/defaulter/index.js index 868e1b03f..48552f731 100644 --- a/modules/client/front/defaulter/index.js +++ b/modules/client/front/defaulter/index.js @@ -46,11 +46,11 @@ export default class Controller extends Section { }, { field: 'created', - searchable: false + datepicker: true }, { field: 'defaulterSinced', - searchable: false + datepicker: true } ] }; @@ -136,8 +136,25 @@ export default class Controller extends Section { case 'workerFk': case 'salesPersonFk': return {[`d.${param}`]: value}; + case 'created': + return {'d.created': { + between: this.dateRange(value)} + }; + case 'defaulterSinced': + return {'d.defaulterSinced': { + between: this.dateRange(value)} + }; } } + + dateRange(value) { + const minHour = new Date(value); + minHour.setHours(0, 0, 0, 0); + const maxHour = new Date(value); + maxHour.setHours(23, 59, 59, 59); + + return [minHour, maxHour]; + } } ngModule.vnComponent('vnClientDefaulter', { diff --git a/modules/client/front/defaulter/index.spec.js b/modules/client/front/defaulter/index.spec.js index f92378d08..6b80a7c36 100644 --- a/modules/client/front/defaulter/index.spec.js +++ b/modules/client/front/defaulter/index.spec.js @@ -117,5 +117,23 @@ describe('client defaulter', () => { expect(controller.balanceDueTotal).toEqual(875); }); }); + + describe('dateRange()', () => { + it('should return two dates with the hours at the start and end of the given date', () => { + const now = Date.vnNew(); + + const today = now.getDate(); + + const dateRange = controller.dateRange(now); + const start = dateRange[0].toString(); + const end = dateRange[1].toString(); + + expect(start).toContain(today); + expect(start).toContain('00:00:00'); + + expect(end).toContain(today); + expect(end).toContain('23:59:59'); + }); + }); }); }); From 98916bf5e13ab0e2f622fc932bbe2f81bf574df8 Mon Sep 17 00:00:00 2001 From: vicent Date: Thu, 16 Mar 2023 13:57:22 +0100 Subject: [PATCH 19/95] refs #5410 add changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dde790aaa..708fd7bd9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [2312.01] - 2023-04-06 ### Added -- +- (Clientes -> Morosos) Ahora se puede filtrar por las columnas "Desde" y "Fecha Ú. O." ### Changed - From 9565bb33f2c30635d4dd7e3660e5e35c31b442c0 Mon Sep 17 00:00:00 2001 From: carlossa Date: Thu, 16 Mar 2023 14:12:54 +0100 Subject: [PATCH 20/95] refs #5425 modificacion de los campos --- e2e/helpers/selectors.js | 2 +- modules/entry/front/latest-buys/index.html | 2 +- modules/item/front/basic-data/index.html | 2 +- modules/item/front/index/index.html | 2 +- modules/item/front/locale/es.yml | 4 ++-- modules/item/front/summary/index.html | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index f20d75310..d4c68ff00 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -410,7 +410,7 @@ export default { advancedSearchButton: 'vn-item-search-panel button[type=submit]', advancedSmartTableButton: 'vn-item-index vn-button[icon="search"]', advancedSmartTableGrouping: 'vn-item-index vn-textfield[name=grouping]', - weightByPieceCheckbox: '.vn-popover.shown vn-horizontal:nth-child(3) > vn-check[label="Weight/Piece"]', + weightByPieceCheckbox: '.vn-popover.shown vn-horizontal:nth-child(3) > vn-check[label="Weight per unit"]', saveFieldsButton: '.vn-popover.shown vn-button[label="Save"] > button' }, itemFixedPrice: { diff --git a/modules/entry/front/latest-buys/index.html b/modules/entry/front/latest-buys/index.html index 727b19220..0fe2de94d 100644 --- a/modules/entry/front/latest-buys/index.html +++ b/modules/entry/front/latest-buys/index.html @@ -63,7 +63,7 @@ Origin - Weight/Piece + Weight per unit Active diff --git a/modules/item/front/basic-data/index.html b/modules/item/front/basic-data/index.html index 974aa37d8..5e6752aea 100644 --- a/modules/item/front/basic-data/index.html +++ b/modules/item/front/basic-data/index.html @@ -124,7 +124,7 @@ diff --git a/modules/item/front/index/index.html b/modules/item/front/index/index.html index 6f5cce7c0..47e71c2df 100644 --- a/modules/item/front/index/index.html +++ b/modules/item/front/index/index.html @@ -46,7 +46,7 @@ Buyer - Weight/Piece + Weight per unit Multiplier diff --git a/modules/item/front/locale/es.yml b/modules/item/front/locale/es.yml index 0fc014742..115a69528 100644 --- a/modules/item/front/locale/es.yml +++ b/modules/item/front/locale/es.yml @@ -40,11 +40,11 @@ Create: Crear Client card: Ficha del cliente Shipped: F. envío stems: Tallos -Weight/Piece: Peso/tallo +Weight per unit: Peso por unidad (gramos) Search items by id, name or barcode: Buscar articulos por identificador, nombre o codigo de barras SalesPerson: Comercial Concept: Concepto -Units/Box: Unidades/Caja +Units/Box: Unidades/caja # Sections Items: Artículos diff --git a/modules/item/front/summary/index.html b/modules/item/front/summary/index.html index 46a2baef4..cdcc2ae49 100644 --- a/modules/item/front/summary/index.html +++ b/modules/item/front/summary/index.html @@ -110,7 +110,7 @@ - Date: Fri, 17 Mar 2023 09:32:20 +0100 Subject: [PATCH 21/95] =?UTF-8?q?refs=20#5425=20modificaci=C3=B3n=20usuari?= =?UTF-8?q?o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- e2e/helpers/selectors.js | 2 +- modules/entry/front/latest-buys/index.html | 2 +- modules/item/front/basic-data/index.html | 2 +- modules/item/front/index/index.html | 2 +- modules/item/front/locale/es.yml | 2 +- modules/item/front/summary/index.html | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index d4c68ff00..f20d75310 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -410,7 +410,7 @@ export default { advancedSearchButton: 'vn-item-search-panel button[type=submit]', advancedSmartTableButton: 'vn-item-index vn-button[icon="search"]', advancedSmartTableGrouping: 'vn-item-index vn-textfield[name=grouping]', - weightByPieceCheckbox: '.vn-popover.shown vn-horizontal:nth-child(3) > vn-check[label="Weight per unit"]', + weightByPieceCheckbox: '.vn-popover.shown vn-horizontal:nth-child(3) > vn-check[label="Weight/Piece"]', saveFieldsButton: '.vn-popover.shown vn-button[label="Save"] > button' }, itemFixedPrice: { diff --git a/modules/entry/front/latest-buys/index.html b/modules/entry/front/latest-buys/index.html index 0fe2de94d..727b19220 100644 --- a/modules/entry/front/latest-buys/index.html +++ b/modules/entry/front/latest-buys/index.html @@ -63,7 +63,7 @@ Origin - Weight per unit + Weight/Piece Active diff --git a/modules/item/front/basic-data/index.html b/modules/item/front/basic-data/index.html index 5e6752aea..974aa37d8 100644 --- a/modules/item/front/basic-data/index.html +++ b/modules/item/front/basic-data/index.html @@ -124,7 +124,7 @@ diff --git a/modules/item/front/index/index.html b/modules/item/front/index/index.html index 47e71c2df..6f5cce7c0 100644 --- a/modules/item/front/index/index.html +++ b/modules/item/front/index/index.html @@ -46,7 +46,7 @@ Buyer - Weight per unit + Weight/Piece Multiplier diff --git a/modules/item/front/locale/es.yml b/modules/item/front/locale/es.yml index 115a69528..37f774e4e 100644 --- a/modules/item/front/locale/es.yml +++ b/modules/item/front/locale/es.yml @@ -40,7 +40,7 @@ Create: Crear Client card: Ficha del cliente Shipped: F. envío stems: Tallos -Weight per unit: Peso por unidad (gramos) +Weight/Piece: Peso (gramos)/tallo Search items by id, name or barcode: Buscar articulos por identificador, nombre o codigo de barras SalesPerson: Comercial Concept: Concepto diff --git a/modules/item/front/summary/index.html b/modules/item/front/summary/index.html index cdcc2ae49..46a2baef4 100644 --- a/modules/item/front/summary/index.html +++ b/modules/item/front/summary/index.html @@ -110,7 +110,7 @@ - Date: Mon, 20 Mar 2023 10:15:18 +0100 Subject: [PATCH 22/95] refs #5092 showing clients with multiple negative bases --- modules/invoiceIn/back/methods/invoice-in/unbilledClients.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/invoiceIn/back/methods/invoice-in/unbilledClients.js b/modules/invoiceIn/back/methods/invoice-in/unbilledClients.js index ad39bc547..790185d25 100644 --- a/modules/invoiceIn/back/methods/invoice-in/unbilledClients.js +++ b/modules/invoiceIn/back/methods/invoice-in/unbilledClients.js @@ -89,8 +89,8 @@ module.exports = Self => { WHERE t.shipped BETWEEN ? AND ? AND t.refFk IS NULL AND c.typeFk IN ('normal','trust') - GROUP BY t.clientFk - HAVING amount <> 0`, [args.from, args.to])); + GROUP BY t.clientFk, negativeBase.taxableBase + HAVING amount < 0`, [args.from, args.to])); stmt = new ParameterizedSQL(` SELECT f.* From a670795f9d93d2074c636015f4902b8051baeb36 Mon Sep 17 00:00:00 2001 From: carlossa Date: Mon, 20 Mar 2023 13:22:21 +0100 Subject: [PATCH 23/95] refs #5432 mod ng-show, add tooltip and disabled --- modules/ticket/front/sale/index.html | 6 ++++-- modules/ticket/front/sale/locale/es.yml | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/ticket/front/sale/index.html b/modules/ticket/front/sale/index.html index 8764417a8..6f0361c35 100644 --- a/modules/ticket/front/sale/index.html +++ b/modules/ticket/front/sale/index.html @@ -28,8 +28,10 @@ + disabled="!$ctrl.hasSelectedSales()" + vn-tooltip="Select lines to see the options" + ng-click="moreOptions.show($event)"> + Date: Mon, 20 Mar 2023 13:41:32 +0100 Subject: [PATCH 24/95] refs #5432 quitar comentario --- modules/ticket/front/sale/index.html | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/ticket/front/sale/index.html b/modules/ticket/front/sale/index.html index 6f0361c35..6fc986e8f 100644 --- a/modules/ticket/front/sale/index.html +++ b/modules/ticket/front/sale/index.html @@ -31,7 +31,6 @@ disabled="!$ctrl.hasSelectedSales()" vn-tooltip="Select lines to see the options" ng-click="moreOptions.show($event)"> - Date: Mon, 20 Mar 2023 15:11:55 +0100 Subject: [PATCH 25/95] refs #5439 campos fecha y salesperson --- back/methods/user-config/getUserConfig.js | 4 +++- modules/item/front/request-search-panel/index.html | 14 ++++++++++++++ .../monitor/front/index/search-panel/index.html | 12 ++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/back/methods/user-config/getUserConfig.js b/back/methods/user-config/getUserConfig.js index 4de8049e7..1ea723f52 100644 --- a/back/methods/user-config/getUserConfig.js +++ b/back/methods/user-config/getUserConfig.js @@ -33,7 +33,9 @@ module.exports = function(Self) { let newConfig = { warehouseFk: warehouse.id, companyFk: company.id, - userFk: ctx.req.accessToken.userId + userFk: ctx.req.accessToken.userId, + buyed: ticketResquest.buyed, + salesPersonCode: salesPersonNickname }; userConfig = await models.UserConfig.create(newConfig, myOptions); diff --git a/modules/item/front/request-search-panel/index.html b/modules/item/front/request-search-panel/index.html index 8c9d04b64..1572c6213 100644 --- a/modules/item/front/request-search-panel/index.html +++ b/modules/item/front/request-search-panel/index.html @@ -38,6 +38,20 @@ url="Warehouses"> + + + + + +
+ + + + Date: Tue, 21 Mar 2023 08:44:28 +0100 Subject: [PATCH 26/95] refs #5439 filtro comercial --- back/methods/user-config/getUserConfig.js | 2 -- .../front/request-search-panel/index.html | 21 ++++++++++++------- .../front/index/search-panel/index.html | 21 ++++++++++++------- 3 files changed, 28 insertions(+), 16 deletions(-) diff --git a/back/methods/user-config/getUserConfig.js b/back/methods/user-config/getUserConfig.js index 1ea723f52..c8aef963d 100644 --- a/back/methods/user-config/getUserConfig.js +++ b/back/methods/user-config/getUserConfig.js @@ -34,8 +34,6 @@ module.exports = function(Self) { warehouseFk: warehouse.id, companyFk: company.id, userFk: ctx.req.accessToken.userId, - buyed: ticketResquest.buyed, - salesPersonCode: salesPersonNickname }; userConfig = await models.UserConfig.create(newConfig, myOptions); diff --git a/modules/item/front/request-search-panel/index.html b/modules/item/front/request-search-panel/index.html index 1572c6213..f26c05a0b 100644 --- a/modules/item/front/request-search-panel/index.html +++ b/modules/item/front/request-search-panel/index.html @@ -39,17 +39,24 @@ - + ng-model="filter.salesPersonFk" + url="Workers/activeWithInheritedRole" + search-function="{firstName: $search}" + value-field="id" + where="{role: 'logistic'}" + label="Comercial"> + {{firstName}} {{name}} + ng-model="filter.saleFk" + url="Sales/created" + search-function="{id: $search}" + value-field="created" + label="Fecha"> + {{created}}
diff --git a/modules/monitor/front/index/search-panel/index.html b/modules/monitor/front/index/search-panel/index.html index 5d4f97140..e2dbc2e87 100644 --- a/modules/monitor/front/index/search-panel/index.html +++ b/modules/monitor/front/index/search-panel/index.html @@ -93,16 +93,23 @@ + url="Workers/activeWithInheritedRole" + search-function="{firstName: $search}" + value-field="id" + where="{role: 'logistic'}" + label="Comercial"> + {{firstName}} {{name}} - + vn-one + ng-model="filter.saleFk" + url="Sales/created" + search-function="{id: $search}" + value-field="created" + label="Fecha"> + {{created}} + Date: Tue, 21 Mar 2023 10:44:00 +0100 Subject: [PATCH 27/95] refs #5056 wagonType backs and test --- db/changes/231201/00-wagon.sql | 10 ++- db/dump/fixtures.sql | 7 +- .../back/methods/wagonType/createWagonType.js | 57 +++++++++++++++++ .../back/methods/wagonType/deleteWagonType.js | 43 +++++++++++++ .../back/methods/wagonType/editWagonType.js | 64 +++++++++++++++++++ .../wagonType/specs/crudWagonType.spec.js | 63 ++++++++++++++++++ modules/wagon/back/models/wagon-type.js | 5 ++ modules/wagon/back/models/wagon.json | 3 + 8 files changed, 246 insertions(+), 6 deletions(-) create mode 100644 modules/wagon/back/methods/wagonType/createWagonType.js create mode 100644 modules/wagon/back/methods/wagonType/deleteWagonType.js create mode 100644 modules/wagon/back/methods/wagonType/editWagonType.js create mode 100644 modules/wagon/back/methods/wagonType/specs/crudWagonType.spec.js create mode 100644 modules/wagon/back/models/wagon-type.js diff --git a/db/changes/231201/00-wagon.sql b/db/changes/231201/00-wagon.sql index c7725ab4f..2924fdc99 100644 --- a/db/changes/231201/00-wagon.sql +++ b/db/changes/231201/00-wagon.sql @@ -15,7 +15,7 @@ CREATE TABLE `vn`.`wagonTypeColor` ( CREATE TABLE `vn`.`wagonTypeTray` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `typeFk` int(11) unsigned, - `height` int(11) unsigned, + `height` int(11) unsigned NOT NULL, `colorFk` int(11) unsigned, PRIMARY KEY (`id`), UNIQUE KEY (`typeFk`,`height`), @@ -54,7 +54,8 @@ CREATE TABLE `vn`.`collectionWagonTicket` ( CONSTRAINT `collectionWagonTicket_tray` FOREIGN KEY (`trayFk`) REFERENCES `wagonTypeTray` (`id`) ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; -ALTER TABLE `vn`.`wagon` ADD `typeFk` int(11) unsigned DEFAULT NULL; +ALTER TABLE `vn`.`wagon` ADD `typeFk` int(11) unsigned NOT NULL; +ALTER TABLE `vn`.`wagon` ADD `label` int(11) unsigned NOT NULL; ALTER TABLE `vn`.`wagon` ADD CONSTRAINT `wagon_type` FOREIGN KEY (`typeFk`) REFERENCES `wagonType` (`id`) ON UPDATE CASCADE; INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) @@ -65,4 +66,7 @@ INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `pri ('WagonConfig', '*', '*', 'ALLOW', 'ROLE', 'employee'), ('CollectionWagon', '*', '*', 'ALLOW', 'ROLE', 'employee'), ('CollectionWagonTicket', '*', '*', 'ALLOW', 'ROLE', 'employee'), - ('Wagon', '*', '*', 'ALLOW', 'ROLE', 'employee'); + ('Wagon', '*', '*', 'ALLOW', 'ROLE', 'employee'), + ('WagonType', 'createWagonType', '*', 'ALLOW', 'ROLE', 'employee'), + ('WagonType', 'deleteWagonType', '*', 'ALLOW', 'ROLE', 'employee'), + ('WagonType', 'editWagonType', '*', 'ALLOW', 'ROLE', 'employee'); diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 571769e8c..1c8134ca3 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -2838,8 +2838,9 @@ INSERT INTO `vn`.`wagonConfig` (`id`, `width`, `height`, `maxWagonHeight`, `minH INSERT INTO `vn`.`wagonTypeColor` (`id`, `name`, `rgb`) VALUES - (1, 'red', '#ff0000'), - (2, 'green', '#00ff00'), - (3, 'blue', '#0000ff'); + (1, 'white', '#ffffff'), + (2, 'red', '#ff0000'), + (3, 'green', '#00ff00'), + (4, 'blue', '#0000ff'); diff --git a/modules/wagon/back/methods/wagonType/createWagonType.js b/modules/wagon/back/methods/wagonType/createWagonType.js new file mode 100644 index 000000000..fed915b28 --- /dev/null +++ b/modules/wagon/back/methods/wagonType/createWagonType.js @@ -0,0 +1,57 @@ +module.exports = Self => { + Self.remoteMethodCtx('createWagonType', { + description: 'Creates a new wagon type', + accessType: 'WRITE', + accepts: [ + { + arg: 'name', + type: 'String', + required: true + }, + { + arg: 'divisible', + type: 'boolean', + required: true + }, { + arg: 'trays', + type: 'any', + required: true + } + ], + http: { + path: `/createWagonType`, + verb: 'PATCH' + } + }); + + Self.createWagonType = async(ctx, options) => { + const args = ctx.args; + const models = Self.app.models; + const myOptions = {}; + let tx; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + if (!myOptions.transaction) { + tx = await Self.beginTransaction({}); + myOptions.transaction = tx; + } + + try { + const newWagonType = await models.WagonType.create({name: args.name, divisible: args.divisible}, myOptions); + args.trays.forEach(async tray => { + await models.WagonTypeTray.create({ + typeFk: newWagonType.id, + height: tray.position, + colorFk: tray.color.id + }, myOptions); + }); + + if (tx) await tx.commit(); + } catch (e) { + if (tx) await tx.rollback(); + throw e; + } + }; +}; diff --git a/modules/wagon/back/methods/wagonType/deleteWagonType.js b/modules/wagon/back/methods/wagonType/deleteWagonType.js new file mode 100644 index 000000000..46b65e32f --- /dev/null +++ b/modules/wagon/back/methods/wagonType/deleteWagonType.js @@ -0,0 +1,43 @@ +module.exports = Self => { + Self.remoteMethodCtx('deleteWagonType', { + description: 'Deletes a wagon type', + accessType: 'WRITE', + accepts: [ + { + arg: 'id', + type: 'Number', + required: true + } + ], + http: { + path: `/deleteWagonType`, + verb: 'DELETE' + } + }); + + Self.deleteWagonType = async(ctx, options) => { + const args = ctx.args; + const models = Self.app.models; + const myOptions = {}; + let tx; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + if (!myOptions.transaction) { + tx = await Self.beginTransaction({}); + myOptions.transaction = tx; + } + + try { + await models.Wagon.destroyAll({typeFk: args.id}, myOptions); + await models.WagonTypeTray.destroyAll({typeFk: args.id}, myOptions); + await models.WagonType.destroyAll({id: args.id}, myOptions); + + if (tx) await tx.commit(); + } catch (e) { + if (tx) await tx.rollback(); + throw e; + } + }; +}; diff --git a/modules/wagon/back/methods/wagonType/editWagonType.js b/modules/wagon/back/methods/wagonType/editWagonType.js new file mode 100644 index 000000000..bd5ad1f16 --- /dev/null +++ b/modules/wagon/back/methods/wagonType/editWagonType.js @@ -0,0 +1,64 @@ +module.exports = Self => { + Self.remoteMethodCtx('editWagonType', { + description: 'Edits a new wagon type', + accessType: 'WRITE', + accepts: [ + { + arg: 'id', + type: 'String', + required: true + }, + { + arg: 'name', + type: 'String', + required: true + }, + { + arg: 'divisible', + type: 'boolean', + required: true + }, { + arg: 'trays', + type: 'any', + required: true + } + ], + http: { + path: `/editWagonType`, + verb: 'PATCH' + } + }); + + Self.editWagonType = async(ctx, options) => { + const args = ctx.args; + const models = Self.app.models; + const myOptions = {}; + let tx; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + if (!myOptions.transaction) { + tx = await Self.beginTransaction({}); + myOptions.transaction = tx; + } + + try { + const wagonType = await models.WagonType.findById(args.id, null, myOptions); + wagonType.updateAttributes({name: args.name, divisible: args.divisible}, myOptions); + models.WagonTypeTray.destroyAll({typeFk: args.id}, myOptions); + args.trays.forEach(async tray => { + await models.WagonTypeTray.create({ + typeFk: args.id, + height: tray.position, + colorFk: tray.color.id + }, myOptions); + }); + + if (tx) await tx.commit(); + } catch (e) { + if (tx) await tx.rollback(); + throw e; + } + }; +}; diff --git a/modules/wagon/back/methods/wagonType/specs/crudWagonType.spec.js b/modules/wagon/back/methods/wagonType/specs/crudWagonType.spec.js new file mode 100644 index 000000000..92ac61060 --- /dev/null +++ b/modules/wagon/back/methods/wagonType/specs/crudWagonType.spec.js @@ -0,0 +1,63 @@ +const models = require('vn-loopback/server/server').models; + +describe('WagonType crudWagonType()', () => { + const ctx = { + args: { + name: 'Mock wagon type', + divisible: true, + trays: [{position: 0, color: {id: 1}}, + {position: 50, color: {id: 2}}, + {position: 100, color: {id: 3}}] + } + }; + + it(`should create, edit and delete a new wagon type and its trays`, async() => { + const tx = await models.WagonType.beginTransaction({}); + + try { + const options = {transaction: tx}; + + // create + await models.WagonType.createWagonType(ctx, options); + + const newWagonType = await models.WagonType.findOne({where: {name: ctx.args.name}}, options); + const newWagonTrays = await models.WagonTypeTray.find({where: {typeFk: newWagonType.id}}, options); + + expect(newWagonType).not.toEqual(null); + expect(newWagonType.name).toEqual(ctx.args.name); + expect(newWagonType.divisible).toEqual(ctx.args.divisible); + expect(newWagonTrays.length).toEqual(ctx.args.trays.length); + + ctx.args = { + id: newWagonType.id, + name: 'Edited wagon type', + divisible: false, + trays: [{position: 0, color: {id: 1}}] + }; + + // edit + await models.WagonType.editWagonType(ctx, options); + + const editedWagonType = await models.WagonType.findById(newWagonType.id, null, options); + const editedWagonTrays = await models.WagonTypeTray.find({where: {typeFk: newWagonType.id}}, options); + + expect(editedWagonType.name).toEqual(ctx.args.name); + expect(editedWagonType.divisible).toEqual(ctx.args.divisible); + expect(editedWagonTrays.length).toEqual(ctx.args.trays.length); + + // delete + await models.WagonType.deleteWagonType(ctx, options); + + const deletedWagonType = await models.WagonType.findById(newWagonType.id, null, options); + const deletedWagonTrays = await models.WagonTypeTray.find({where: {typeFk: newWagonType.id}}, options); + + expect(deletedWagonType).toEqual(null); + expect(deletedWagonTrays).toEqual([]); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); +}); diff --git a/modules/wagon/back/models/wagon-type.js b/modules/wagon/back/models/wagon-type.js new file mode 100644 index 000000000..bebf7a9d9 --- /dev/null +++ b/modules/wagon/back/models/wagon-type.js @@ -0,0 +1,5 @@ +module.exports = Self => { + require('../methods/wagonType/createWagonType')(Self); + require('../methods/wagonType/editWagonType')(Self); + require('../methods/wagonType/deleteWagonType')(Self); +}; diff --git a/modules/wagon/back/models/wagon.json b/modules/wagon/back/models/wagon.json index 81b9f23e6..61ee61e61 100644 --- a/modules/wagon/back/models/wagon.json +++ b/modules/wagon/back/models/wagon.json @@ -11,6 +11,9 @@ "id": true, "type": "number" }, + "label": { + "type": "number" + }, "volume": { "type": "number" }, From 41c79263c43c170cc31cbb68d7027598bcdaf0b1 Mon Sep 17 00:00:00 2001 From: vicent Date: Tue, 21 Mar 2023 14:53:36 +0100 Subject: [PATCH 28/95] =?UTF-8?q?refs=20#5410=20feat:=20envia=20email=20cu?= =?UTF-8?q?ando=20se=20a=C3=B1ade=20una=20nota?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/client/front/defaulter/index.js | 24 +++++++++++++++++++- modules/client/front/defaulter/locale/es.yml | 6 ++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/modules/client/front/defaulter/index.js b/modules/client/front/defaulter/index.js index 48552f731..d8bf12bff 100644 --- a/modules/client/front/defaulter/index.js +++ b/modules/client/front/defaulter/index.js @@ -123,11 +123,33 @@ export default class Controller extends Section { } this.$http.post(`ClientObservations`, params) .then(() => { - this.vnApp.showMessage(this.$t('Observation saved!')); + this.vnApp.showSuccess(this.$t('Observation saved!')); + this.sendMail(); this.$state.reload(); }); } + sendMail() { + const params = []; + for (let defaulter of this.checked) { + const body = this.$t('Added observation', { + salesPersonName: defaulter.salesPersonName, + text: this.defaulter.observation + }); + + params.push({ + subject: this.$t('Comment added to client', {clientFk: defaulter.clientFk}), + body: body, + receiver: `${defaulter.salesPersonName}@verdnatura.es`, + replyTo: `${window.localStorage.lastUser}@verdnatura.es` + }); + } + + this.$http.post(`Mails`, params) .then(() => { + this.vnApp.showMessage(this.$t('Email sended!')); + }); + } + exprBuilder(param, value) { switch (param) { case 'creditInsurance': diff --git a/modules/client/front/defaulter/locale/es.yml b/modules/client/front/defaulter/locale/es.yml index c3e1d4e19..a301a50e0 100644 --- a/modules/client/front/defaulter/locale/es.yml +++ b/modules/client/front/defaulter/locale/es.yml @@ -6,4 +6,8 @@ Last observation: Última observación L. O. Date: Fecha Ú. O. Last observation date: Fecha última observación Search client: Buscar clientes -Worker who made the last observation: Trabajador que ha realizado la última observación \ No newline at end of file +Worker who made the last observation: Trabajador que ha realizado la última observación +Added observation: '{{salesPersonName}} añadió esta observacion: {{text}}' +Comment added to client: Observación añadida al cliente {{clientFk}} +Email sended!: Email enviado! +Observation saved!: Observación añadida! From 700151b500853f9d4065fb089c4f9221163dbad2 Mon Sep 17 00:00:00 2001 From: alexandre Date: Wed, 22 Mar 2023 08:18:56 +0100 Subject: [PATCH 29/95] refs #5092 amount <> 0 --- modules/invoiceIn/back/methods/invoice-in/unbilledClients.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/invoiceIn/back/methods/invoice-in/unbilledClients.js b/modules/invoiceIn/back/methods/invoice-in/unbilledClients.js index 790185d25..216af4d48 100644 --- a/modules/invoiceIn/back/methods/invoice-in/unbilledClients.js +++ b/modules/invoiceIn/back/methods/invoice-in/unbilledClients.js @@ -90,7 +90,7 @@ module.exports = Self => { AND t.refFk IS NULL AND c.typeFk IN ('normal','trust') GROUP BY t.clientFk, negativeBase.taxableBase - HAVING amount < 0`, [args.from, args.to])); + HAVING amount <> 0`, [args.from, args.to])); stmt = new ParameterizedSQL(` SELECT f.* From 1b1bca28bd429e246ff0af0cfc0488606baa6999 Mon Sep 17 00:00:00 2001 From: vicent Date: Wed, 22 Mar 2023 10:13:59 +0100 Subject: [PATCH 30/95] refs #5410 add frontTest --- CHANGELOG.md | 4 +- db/changes/231201/00-mailACL.sql | 2 + modules/client/front/defaulter/index.spec.js | 43 +++++++++++++++++++- 3 files changed, 46 insertions(+), 3 deletions(-) create mode 100644 db/changes/231201/00-mailACL.sql diff --git a/CHANGELOG.md b/CHANGELOG.md index 708fd7bd9..65ed1f645 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,13 +8,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [2312.01] - 2023-04-06 ### Added -- (Clientes -> Morosos) Ahora se puede filtrar por las columnas "Desde" y "Fecha Ú. O." +- (Clientes -> Morosos) Ahora se puede filtrar por las columnas "Desde" y "Fecha Ú. O.". También se envia un email al comercial cuando se añade una nota. ### Changed - ### Fixed -- +- (Clientes -> Morosos) Ahora se mantienen los elementos seleccionados al hacer sroll. ## [2310.01] - 2023-03-23 diff --git a/db/changes/231201/00-mailACL.sql b/db/changes/231201/00-mailACL.sql new file mode 100644 index 000000000..ac687818d --- /dev/null +++ b/db/changes/231201/00-mailACL.sql @@ -0,0 +1,2 @@ +INSERT INTO `salix`.`ACL` ( model, property, accessType, permission, principalType, principalId) +VALUES('Mail', '*', '*', 'ALLOW', 'ROLE', 'employee'); diff --git a/modules/client/front/defaulter/index.spec.js b/modules/client/front/defaulter/index.spec.js index 6b80a7c36..30c40132d 100644 --- a/modules/client/front/defaulter/index.spec.js +++ b/modules/client/front/defaulter/index.spec.js @@ -80,15 +80,17 @@ describe('client defaulter', () => { controller.defaulter = {observation: 'My new observation'}; const params = [{text: controller.defaulter.observation, clientFk: data[1].clientFk}]; + const mailParams = [{subject: 'Comment added to client', body: 'Added observation', receiver: 'undefined@verdnatura.es', replyTo: 'undefined@verdnatura.es'}]; jest.spyOn(controller.vnApp, 'showMessage'); $httpBackend.expect('GET', `Defaulters/filter`).respond(200); $httpBackend.expect('POST', `ClientObservations`, params).respond(200, params); + $httpBackend.expect('POST', `Mails`, mailParams).respond(200); controller.onResponse(); $httpBackend.flush(); - expect(controller.vnApp.showMessage).toHaveBeenCalledWith('Observation saved!'); + expect(controller.vnApp.showMessage).toHaveBeenCalledWith('Email sended!'); }); }); @@ -135,5 +137,44 @@ describe('client defaulter', () => { expect(end).toContain('23:59:59'); }); }); + + describe('reCheck()', () => { + it(`should recheck buys`, () => { + controller.$.model.data = [ + {checked: false, clientFk: 1}, + {checked: false, clientFk: 2}, + {checked: false, clientFk: 3}, + {checked: false, clientFk: 4}, + ]; + controller.checkedDefaulers = [1, 2]; + + controller.reCheck(); + + expect(controller.$.model.data[0].checked).toEqual(true); + expect(controller.$.model.data[1].checked).toEqual(true); + expect(controller.$.model.data[2].checked).toEqual(false); + expect(controller.$.model.data[3].checked).toEqual(false); + }); + }); + + describe('saveChecked()', () => { + it(`should check buy`, () => { + const buyCheck = 3; + controller.checkedDefaulers = [1, 2]; + + controller.saveChecked(buyCheck); + + expect(controller.checkedDefaulers[2]).toEqual(buyCheck); + }); + + it(`should uncheck buy`, () => { + const buyUncheck = 3; + controller.checkedDefaulers = [1, 2, 3]; + + controller.saveChecked(buyUncheck); + + expect(controller.checkedDefaulers[2]).toEqual(undefined); + }); + }); }); }); From fde854f5c2e078f4a277ad0ea649f6f01a744604 Mon Sep 17 00:00:00 2001 From: carlossa Date: Wed, 22 Mar 2023 10:21:15 +0100 Subject: [PATCH 31/95] refs #5250 campo de notes --- db/changes/231201/00-workerNotes.sql | 10 +++++ e2e/helpers/selectors.js | 6 +++ e2e/paths/03-worker/08_add_notes.spec.js | 42 +++++++++++++++++++ modules/worker/front/index.js | 3 ++ modules/worker/front/locale/es.yml | 2 + modules/worker/front/note/create/index.html | 30 +++++++++++++ modules/worker/front/note/create/index.js | 21 ++++++++++ .../worker/front/note/create/index.spec.js | 22 ++++++++++ .../worker/front/note/create/locale/es.yml | 2 + modules/worker/front/note/index/index.html | 31 ++++++++++++++ modules/worker/front/note/index/index.js | 22 ++++++++++ modules/worker/front/note/index/style.scss | 5 +++ modules/worker/front/routes.json | 19 +++++++++ 13 files changed, 215 insertions(+) create mode 100644 db/changes/231201/00-workerNotes.sql create mode 100644 e2e/paths/03-worker/08_add_notes.spec.js create mode 100644 modules/worker/front/note/create/index.html create mode 100644 modules/worker/front/note/create/index.js create mode 100644 modules/worker/front/note/create/index.spec.js create mode 100644 modules/worker/front/note/create/locale/es.yml create mode 100644 modules/worker/front/note/index/index.html create mode 100644 modules/worker/front/note/index/index.js create mode 100644 modules/worker/front/note/index/style.scss diff --git a/db/changes/231201/00-workerNotes.sql b/db/changes/231201/00-workerNotes.sql new file mode 100644 index 000000000..602ea3296 --- /dev/null +++ b/db/changes/231201/00-workerNotes.sql @@ -0,0 +1,10 @@ +CREATE TABLE `vn`.`workerObservation` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `workerFk` int(10) unsigned DEFAULT NULL, + `userFk` int(10) unsigned DEFAULT NULL, + `text` text COLLATE utf8mb3_unicode_ci NOT NULL, + `created` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`id`), + CONSTRAINT `workerFk_workerObservation_FK` FOREIGN KEY (`workerFk`) REFERENCES `vn`.`worker` (`id`) ON UPDATE CASCADE, + CONSTRAINT `userFk_workerObservation_FK` FOREIGN KEY (`userFk`) REFERENCES `account`.`user`(`id`) ON UPDATE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci COMMENT='Todas las observaciones referentes a un trabajador'; \ No newline at end of file diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index f20d75310..ad5ff2692 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -988,6 +988,12 @@ export default { locker: 'vn-worker-basic-data vn-input-number[ng-model="$ctrl.worker.locker"]', saveButton: 'vn-worker-basic-data button[type=submit]' }, + workerNotes: { + addNoteFloatButton: 'vn-float-button', + note: 'vn-textarea[ng-model="$ctrl.note.text"]', + saveButton: 'button[type=submit]', + firstNoteText: 'vn-worker-note .text' + }, workerPbx: { extension: 'vn-worker-pbx vn-textfield[ng-model="$ctrl.worker.sip.extension"]', saveButton: 'vn-worker-pbx button[type=submit]' diff --git a/e2e/paths/03-worker/08_add_notes.spec.js b/e2e/paths/03-worker/08_add_notes.spec.js new file mode 100644 index 000000000..eb2e4c041 --- /dev/null +++ b/e2e/paths/03-worker/08_add_notes.spec.js @@ -0,0 +1,42 @@ +import selectors from '../../helpers/selectors'; +import getBrowser from '../../helpers/puppeteer'; + +describe('Worker Add notes path', () => { + let browser; + let page; + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('employee', 'worker'); + await page.accessToSearchResult('Bruce Banner'); + await page.accessToSection('worker.card.note.index'); + }); + + afterAll(async() => { + await browser.close(); + }); + + it(`should reach the notes index`, async() => { + await page.waitForState('worker.card.note.index'); + }); + + it(`should click on the add note button`, async() => { + await page.waitToClick(selectors.workerNotes.addNoteFloatButton); + await page.waitForState('worker.card.note.create'); + }); + + it(`should create a note`, async() => { + await page.waitForSelector(selectors.workerNotes.note); + await page.type(`${selectors.workerNotes.note} textarea`, 'Meeting with Black Widow 21st 9am'); + await page.waitToClick(selectors.workerNotes.saveButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); + + it('should confirm the note was created', async() => { + const result = await page.waitToGetProperty(selectors.workerNotes.firstNoteText, 'innerText'); + + expect(result).toEqual('Meeting with Black Widow 21st 9am'); + }); +}); diff --git a/modules/worker/front/index.js b/modules/worker/front/index.js index 657f6a8c6..8fad2c0df 100644 --- a/modules/worker/front/index.js +++ b/modules/worker/front/index.js @@ -18,3 +18,6 @@ import './log'; import './dms/index'; import './dms/create'; import './dms/edit'; +import './note/index'; +import './note/create'; + diff --git a/modules/worker/front/locale/es.yml b/modules/worker/front/locale/es.yml index b5bcfefa4..a25377122 100644 --- a/modules/worker/front/locale/es.yml +++ b/modules/worker/front/locale/es.yml @@ -31,3 +31,5 @@ Deallocate PDA: Desasignar PDA PDA deallocated: PDA desasignada PDA allocated: PDA asignada New PDA: Nueva PDA +Notes: Notas +New note: Nueva nota diff --git a/modules/worker/front/note/create/index.html b/modules/worker/front/note/create/index.html new file mode 100644 index 000000000..d09fc2da5 --- /dev/null +++ b/modules/worker/front/note/create/index.html @@ -0,0 +1,30 @@ + + +
+ + + + + + + + + + + + +
\ No newline at end of file diff --git a/modules/worker/front/note/create/index.js b/modules/worker/front/note/create/index.js new file mode 100644 index 000000000..81ee247db --- /dev/null +++ b/modules/worker/front/note/create/index.js @@ -0,0 +1,21 @@ +import ngModule from '../../module'; +import Section from 'salix/components/section'; + +export default class Controller extends Section { + constructor($element, $) { + super($element, $); + this.note = { + workerFk: parseInt(this.$params.id), + text: null + }; + } + + cancel() { + this.$state.go('worker.card.note.index', {id: this.$params.id}); + } +} + +ngModule.vnComponent('vnNoteWorkerCreate', { + template: require('./index.html'), + controller: Controller +}); diff --git a/modules/worker/front/note/create/index.spec.js b/modules/worker/front/note/create/index.spec.js new file mode 100644 index 000000000..d900c8ee0 --- /dev/null +++ b/modules/worker/front/note/create/index.spec.js @@ -0,0 +1,22 @@ +import './index'; + +describe('Worker', () => { + describe('Component vnNoteWorkerCreate', () => { + let $state; + let controller; + + beforeEach(ngModule('worker')); + + beforeEach(inject(($componentController, _$state_) => { + $state = _$state_; + $state.params.id = '1234'; + const $element = angular.element(''); + controller = $componentController('vnNoteWorkerCreate', {$element, $state}); + })); + + it('should define workerFk using $state.params.id', () => { + expect(controller.note.workerFk).toBe(1234); + expect(controller.note.worker).toBe(undefined); + }); + }); +}); diff --git a/modules/worker/front/note/create/locale/es.yml b/modules/worker/front/note/create/locale/es.yml new file mode 100644 index 000000000..bfe773f48 --- /dev/null +++ b/modules/worker/front/note/create/locale/es.yml @@ -0,0 +1,2 @@ +New note: Nueva nota +Note: Nota \ No newline at end of file diff --git a/modules/worker/front/note/index/index.html b/modules/worker/front/note/index/index.html new file mode 100644 index 000000000..4b72d60ab --- /dev/null +++ b/modules/worker/front/note/index/index.html @@ -0,0 +1,31 @@ + + + + +
+ + {{::note.worker.user.nickname}} + {{::note.created | date:'dd/MM/yyyy HH:mm'}} + + + {{::note.text}} + +
+
+
+ + + diff --git a/modules/worker/front/note/index/index.js b/modules/worker/front/note/index/index.js new file mode 100644 index 000000000..d20971413 --- /dev/null +++ b/modules/worker/front/note/index/index.js @@ -0,0 +1,22 @@ +import ngModule from '../../module'; +import Section from 'salix/components/section'; +import './style.scss'; + +export default class Controller extends Section { + constructor($element, $) { + super($element, $); + this.filter = { + order: 'created DESC', + }; + } +} + +Controller.$inject = ['$element', '$scope']; + +ngModule.vnComponent('vnWorkerNote', { + template: require('./index.html'), + controller: Controller, + bindings: { + worker: '<' + } +}); diff --git a/modules/worker/front/note/index/style.scss b/modules/worker/front/note/index/style.scss new file mode 100644 index 000000000..5ff6baf4f --- /dev/null +++ b/modules/worker/front/note/index/style.scss @@ -0,0 +1,5 @@ +vn-worker-note { + .note:last-child { + margin-bottom: 0; + } +} \ No newline at end of file diff --git a/modules/worker/front/routes.json b/modules/worker/front/routes.json index 64b98bfca..64cb186d6 100644 --- a/modules/worker/front/routes.json +++ b/modules/worker/front/routes.json @@ -11,6 +11,7 @@ ], "card": [ {"state": "worker.card.basicData", "icon": "settings"}, + {"state": "worker.card.note.index", "icon": "insert_drive_file"}, {"state": "worker.card.timeControl", "icon": "access_time"}, {"state": "worker.card.calendar", "icon": "icon-calendar"}, {"state": "worker.card.pda", "icon": "phone_android"}, @@ -72,6 +73,24 @@ "component": "vn-worker-log", "description": "Log", "acl": ["salesAssistant"] + }, { + "url": "/note", + "state": "worker.card.note", + "component": "ui-view", + "abstract": true + }, { + "url": "/index", + "state": "worker.card.note.index", + "component": "vn-worker-note", + "description": "Notes", + "params": { + "worker": "$ctrl.worker" + } + }, { + "url": "/create", + "state": "worker.card.note.create", + "component": "vn-note-worker-create", + "description": "New note" }, { "url": "/pbx", "state": "worker.card.pbx", From 3fd1e7a0869d3644cd3be83a3492125af24c6b96 Mon Sep 17 00:00:00 2001 From: carlossa Date: Wed, 22 Mar 2023 15:41:36 +0100 Subject: [PATCH 32/95] =?UTF-8?q?refs=20#5439=20se=20elimina=20el=20filtro?= =?UTF-8?q?=20de=20fecha=20a=C3=B1adido?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/item/front/request-search-panel/index.html | 9 --------- modules/monitor/front/index/search-panel/index.html | 9 --------- 2 files changed, 18 deletions(-) diff --git a/modules/item/front/request-search-panel/index.html b/modules/item/front/request-search-panel/index.html index f26c05a0b..921dec0c0 100644 --- a/modules/item/front/request-search-panel/index.html +++ b/modules/item/front/request-search-panel/index.html @@ -49,15 +49,6 @@ label="Comercial"> {{firstName}} {{name}} - - {{created}} -
diff --git a/modules/monitor/front/index/search-panel/index.html b/modules/monitor/front/index/search-panel/index.html index e2dbc2e87..99c9dcd17 100644 --- a/modules/monitor/front/index/search-panel/index.html +++ b/modules/monitor/front/index/search-panel/index.html @@ -101,15 +101,6 @@ label="Comercial"> {{firstName}} {{name}} - - {{created}} - Date: Thu, 23 Mar 2023 07:53:26 +0100 Subject: [PATCH 33/95] refs #5056 adding fixtures --- db/dump/fixtures.sql | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 06b9e7c21..22c0d5106 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -2848,4 +2848,16 @@ INSERT INTO `vn`.`wagonTypeColor` (`id`, `name`, `rgb`) (3, 'green', '#00ff00'), (4, 'blue', '#0000ff'); +INSERT INTO `vn`.`wagonType` (`id`, `name`, `divisible`) + VALUES + (1, 'Wagon Type #1', 1); + +INSERT INTO `vn`.`wagonTypeTray` (`id`, `typeFk`, `height`, `colorFk`) + VALUES + (1, 1, 100, 1), + (2, 1, 50, 2), + (3, 1, 0, 3); + + + From 79c42384ee61193fcb7d9b560d4f7b43fc7741b3 Mon Sep 17 00:00:00 2001 From: carlossa Date: Thu, 23 Mar 2023 08:26:06 +0100 Subject: [PATCH 34/95] refs #5439 role actualizado --- modules/item/front/request-search-panel/index.html | 2 +- modules/monitor/front/index/search-panel/index.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/item/front/request-search-panel/index.html b/modules/item/front/request-search-panel/index.html index 921dec0c0..ae7f9bcc5 100644 --- a/modules/item/front/request-search-panel/index.html +++ b/modules/item/front/request-search-panel/index.html @@ -45,7 +45,7 @@ url="Workers/activeWithInheritedRole" search-function="{firstName: $search}" value-field="id" - where="{role: 'logistic'}" + where="{role: 'salesPerson'}" label="Comercial"> {{firstName}} {{name}} diff --git a/modules/monitor/front/index/search-panel/index.html b/modules/monitor/front/index/search-panel/index.html index 99c9dcd17..f478661c5 100644 --- a/modules/monitor/front/index/search-panel/index.html +++ b/modules/monitor/front/index/search-panel/index.html @@ -97,7 +97,7 @@ url="Workers/activeWithInheritedRole" search-function="{firstName: $search}" value-field="id" - where="{role: 'logistic'}" + where="{role: 'salesPerson'}" label="Comercial"> {{firstName}} {{name}} From a17016a1d8c1185e0498b05aa817ab0c8796b00a Mon Sep 17 00:00:00 2001 From: carlossa Date: Thu, 23 Mar 2023 08:29:25 +0100 Subject: [PATCH 35/95] refs #5439 arreglo getUserConfig --- back/methods/user-config/getUserConfig.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/back/methods/user-config/getUserConfig.js b/back/methods/user-config/getUserConfig.js index c8aef963d..4de8049e7 100644 --- a/back/methods/user-config/getUserConfig.js +++ b/back/methods/user-config/getUserConfig.js @@ -33,7 +33,7 @@ module.exports = function(Self) { let newConfig = { warehouseFk: warehouse.id, companyFk: company.id, - userFk: ctx.req.accessToken.userId, + userFk: ctx.req.accessToken.userId }; userConfig = await models.UserConfig.create(newConfig, myOptions); From 6738243534184ae85ae938223fd87508b69f535a Mon Sep 17 00:00:00 2001 From: alexandre Date: Thu, 23 Mar 2023 14:30:58 +0100 Subject: [PATCH 36/95] refs #5206 added e2e --- CHANGELOG.md | 2 +- e2e/helpers/selectors.js | 11 +++- e2e/paths/10-travel/06_search_panel.spec.js | 62 +++++++++++++++++++++ 3 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 e2e/paths/10-travel/06_search_panel.spec.js diff --git a/CHANGELOG.md b/CHANGELOG.md index dde790aaa..7abd8d6a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - ### Changed -- +- (Envíos -> Índice) Cambiado el buscador superior por uno lateral ### Fixed - diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index 0762a79f0..dbb1d998f 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -1139,7 +1139,16 @@ export default { landingDate: 'vn-travel-create vn-date-picker[ng-model="$ctrl.travel.landed"]', warehouseOut: 'vn-travel-create vn-autocomplete[ng-model="$ctrl.travel.warehouseOutFk"]', warehouseIn: 'vn-travel-create vn-autocomplete[ng-model="$ctrl.travel.warehouseInFk"]', - save: 'vn-travel-create vn-submit > button' + save: 'vn-travel-create vn-submit > button', + generalSearchFilter: 'vn-travel-search-panel vn-textfield[ng-model="$ctrl.search"]', + agencyFilter: 'vn-travel-search-panel vn-autocomplete[ng-model="$ctrl.filter.agencyModeFk"]', + warehouseOutFilter: 'vn-travel-search-panel vn-autocomplete[ng-model="$ctrl.filter.warehouseOutFk"]', + warehouseInFilter: 'vn-travel-search-panel vn-autocomplete[ng-model="$ctrl.filter.warehouseInFk"]', + scopeDaysFilter: 'vn-travel-search-panel vn-input-number[ng-model="$ctrl.filter.scopeDays"]', + continentFilter: 'vn-travel-search-panel vn-autocomplete[ng-model="$ctrl.filter.continent"]', + totalEntriesFilter: 'vn-travel-search-panel vn-input-number[ng-model="$ctrl.totalEntries"]', + chip: 'vn-travel-search-panel vn-chip > vn-icon', + }, travelExtraCommunity: { anySearchResult: 'vn-travel-extra-community > vn-card div > tbody > tr[ng-attr-id="{{::travel.id}}"]', diff --git a/e2e/paths/10-travel/06_search_panel.spec.js b/e2e/paths/10-travel/06_search_panel.spec.js new file mode 100644 index 000000000..420ceaf48 --- /dev/null +++ b/e2e/paths/10-travel/06_search_panel.spec.js @@ -0,0 +1,62 @@ +import selectors from '../../helpers/selectors.js'; +import getBrowser from '../../helpers/puppeteer'; + +describe('Travel search panel path', () => { + let browser; + let page; + let httpRequest; + + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('buyer', 'travel'); + page.on('request', req => { + if (req.url().includes(`Travels/filter`)) + httpRequest = req.url(); + }); + }); + + afterAll(async() => { + await browser.close(); + }); + + it('should filter using all the fields', async() => { + await page.click(selectors.travelIndex.chip); + await page.write(selectors.travelIndex.generalSearchFilter, 'travel'); + await page.keyboard.press('Enter'); + + expect(httpRequest).toContain('search=travel'); + + await page.click(selectors.travelIndex.chip); + await page.autocompleteSearch(selectors.travelIndex.agencyFilter, 'Entanglement'); + + expect(httpRequest).toContain('agencyModeFk'); + + await page.click(selectors.travelIndex.chip); + await page.autocompleteSearch(selectors.travelIndex.warehouseOutFilter, 'Warehouse One'); + + expect(httpRequest).toContain('warehouseOutFk'); + + await page.click(selectors.travelIndex.chip); + await page.autocompleteSearch(selectors.travelIndex.warehouseInFilter, 'Warehouse Two'); + + expect(httpRequest).toContain('warehouseInFk'); + + await page.click(selectors.travelIndex.chip); + await page.overwrite(selectors.travelIndex.scopeDaysFilter, '15'); + await page.keyboard.press('Enter'); + + expect(httpRequest).toContain('scopeDays=15'); + + await page.click(selectors.travelIndex.chip); + await page.autocompleteSearch(selectors.travelIndex.continentFilter, 'Asia'); + + expect(httpRequest).toContain('continent'); + + await page.click(selectors.travelIndex.chip); + await page.write(selectors.travelIndex.totalEntriesFilter, '1'); + await page.keyboard.press('Enter'); + + expect(httpRequest).toContain('totalEntries=1'); + }); +}); From afdfe5e3f30c2a75be410bbf761cf58367724e10 Mon Sep 17 00:00:00 2001 From: vicent Date: Thu, 23 Mar 2023 14:55:19 +0100 Subject: [PATCH 37/95] refs #5331 al filtrar por 'Pendiente' no muestra los estados 'Previa x' --- .../back/methods/sales-monitor/salesFilter.js | 43 +++++++++++++------ 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/modules/monitor/back/methods/sales-monitor/salesFilter.js b/modules/monitor/back/methods/sales-monitor/salesFilter.js index 881fc637a..32d8d3a6a 100644 --- a/modules/monitor/back/methods/sales-monitor/salesFilter.js +++ b/modules/monitor/back/methods/sales-monitor/salesFilter.js @@ -352,20 +352,37 @@ module.exports = Self => { return {'t.alertLevel': value}; case 'pending': if (value) { - return {and: [ - {'t.alertLevel': 0}, - {'t.alertLevelCode': {nin: [ - 'OK', - 'BOARDING', - 'PRINTED', - 'PRINTED_AUTO', - 'PICKER_DESIGNED' - ]}} - ]}; + return {'t.alertLevelCode': {inq: [ + 'FIXING', + 'FREE', + 'NOT_READY', + 'BLOCKED', + 'EXPANDABLE', + 'CHAINED', + 'WAITING_FOR_PAYMENT' + ]}}; } else { - return {and: [ - {'t.alertLevel': {gt: 0}} - ]}; + return {'t.alertLevelCode': {inq: [ + 'ON_PREPARATION', + 'ON_CHECKING', + 'CHECKED', + 'PACKING', + 'PACKED', + 'INVOICED', + 'ON_DELIVERY', + 'PREPARED', + 'WAITING_FOR_PICKUP', + 'DELIVERED', + 'PRINTED_BACK', + 'LAST_CALL', + 'PREVIOUS_PREPARATION', + 'ASSISTED_PREPARATION', + 'BOARD', + 'PRINTED STOWAWAY', + 'OK STOWAWAY', + 'HALF_PACKED', + 'COOLER_PREPARATION' + ]}}; } case 'agencyModeFk': case 'warehouseFk': From 74312a3cdfc537542346f1131176ed2944693bad Mon Sep 17 00:00:00 2001 From: alexandre Date: Fri, 24 Mar 2023 07:30:35 +0100 Subject: [PATCH 38/95] refs #5056 changed acl --- db/changes/231201/00-wagon.sql | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/db/changes/231201/00-wagon.sql b/db/changes/231201/00-wagon.sql index 2924fdc99..3e4d225d7 100644 --- a/db/changes/231201/00-wagon.sql +++ b/db/changes/231201/00-wagon.sql @@ -60,13 +60,13 @@ ALTER TABLE `vn`.`wagon` ADD CONSTRAINT `wagon_type` FOREIGN KEY (`typeFk`) REFE INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES - ('WagonType', '*', '*', 'ALLOW', 'ROLE', 'employee'), - ('WagonTypeColor', '*', '*', 'ALLOW', 'ROLE', 'employee'), - ('WagonTypeTray', '*', '*', 'ALLOW', 'ROLE', 'employee'), - ('WagonConfig', '*', '*', 'ALLOW', 'ROLE', 'employee'), - ('CollectionWagon', '*', '*', 'ALLOW', 'ROLE', 'employee'), - ('CollectionWagonTicket', '*', '*', 'ALLOW', 'ROLE', 'employee'), - ('Wagon', '*', '*', 'ALLOW', 'ROLE', 'employee'), - ('WagonType', 'createWagonType', '*', 'ALLOW', 'ROLE', 'employee'), - ('WagonType', 'deleteWagonType', '*', 'ALLOW', 'ROLE', 'employee'), - ('WagonType', 'editWagonType', '*', 'ALLOW', 'ROLE', 'employee'); + ('WagonType', '*', '*', 'ALLOW', 'ROLE', 'productionAssi'), + ('WagonTypeColor', '*', '*', 'ALLOW', 'ROLE', 'productionAssi'), + ('WagonTypeTray', '*', '*', 'ALLOW', 'ROLE', 'productionAssi'), + ('WagonConfig', '*', '*', 'ALLOW', 'ROLE', 'productionAssi'), + ('CollectionWagon', '*', '*', 'ALLOW', 'ROLE', 'productionAssi'), + ('CollectionWagonTicket', '*', '*', 'ALLOW', 'ROLE', 'productionAssi'), + ('Wagon', '*', '*', 'ALLOW', 'ROLE', 'productionAssi'), + ('WagonType', 'createWagonType', '*', 'ALLOW', 'ROLE', 'productionAssi'), + ('WagonType', 'deleteWagonType', '*', 'ALLOW', 'ROLE', 'productionAssi'), + ('WagonType', 'editWagonType', '*', 'ALLOW', 'ROLE', 'productionAssi'); From 0baccc47453e2964a6b392cde9a0c78204846c5b Mon Sep 17 00:00:00 2001 From: alexandre Date: Fri, 24 Mar 2023 08:25:37 +0100 Subject: [PATCH 39/95] refs #5206 fix tests front --- modules/travel/front/index/index.html | 29 ----------- modules/travel/front/index/index.js | 31 ------------ modules/travel/front/main/index.js | 3 ++ modules/travel/front/main/index.spec.js | 49 ------------------- .../travel/front/search-panel/index.spec.js | 48 +++++++----------- 5 files changed, 22 insertions(+), 138 deletions(-) delete mode 100644 modules/travel/front/main/index.spec.js diff --git a/modules/travel/front/index/index.html b/modules/travel/front/index/index.html index a6952321f..a768e4a29 100644 --- a/modules/travel/front/index/index.html +++ b/modules/travel/front/index/index.html @@ -105,32 +105,3 @@ question="Do you want to clone this travel?" message="All it's properties will be copied"> - - - - Filter by selection - - - Exclude selection - - - Remove filter - - - Remove all filters - - - Copy value - - - diff --git a/modules/travel/front/index/index.js b/modules/travel/front/index/index.js index 2c8f8fc8a..a570146fe 100644 --- a/modules/travel/front/index/index.js +++ b/modules/travel/front/index/index.js @@ -31,37 +31,6 @@ export default class Controller extends Section { if (timeDifference == 0) return 'warning'; if (timeDifference < 0) return 'success'; } - - exprBuilder(param, value) { - switch (param) { - case 'search': - return /^\d+$/.test(value) - ? {'t.id': value} - : {'t.ref': {like: `%${value}%`}}; - case 'ref': - return {'t.ref': {like: `%${value}%`}}; - case 'shipped': - return {'t.shipped': {between: this.dateRange(value)}}; - case 'landed': - return {'t.landed': {between: this.dateRange(value)}}; - case 'id': - case 'agencyModeFk': - case 'warehouseOutFk': - case 'warehouseInFk': - case 'totalEntries': - param = `t.${param}`; - return {[param]: value}; - } - } - - dateRange(value) { - const minHour = new Date(value); - minHour.setHours(0, 0, 0, 0); - const maxHour = new Date(value); - maxHour.setHours(23, 59, 59, 59); - - return [minHour, maxHour]; - } } ngModule.vnComponent('vnTravelIndex', { diff --git a/modules/travel/front/main/index.js b/modules/travel/front/main/index.js index 82ebe61af..6a153f21a 100644 --- a/modules/travel/front/main/index.js +++ b/modules/travel/front/main/index.js @@ -2,6 +2,9 @@ import ngModule from '../module'; import ModuleMain from 'salix/components/module-main'; export default class Travel extends ModuleMain { + constructor() { + super(); + } } ngModule.vnComponent('vnTravel', { diff --git a/modules/travel/front/main/index.spec.js b/modules/travel/front/main/index.spec.js deleted file mode 100644 index bf5a27b41..000000000 --- a/modules/travel/front/main/index.spec.js +++ /dev/null @@ -1,49 +0,0 @@ -import './index.js'; - -describe('Travel Component vnTravel', () => { - let controller; - - beforeEach(ngModule('travel')); - - beforeEach(inject($componentController => { - let $element = angular.element(`
`); - controller = $componentController('vnTravel', {$element}); - })); - - describe('fetchParams()', () => { - it('should return a range of dates with passed scope days', () => { - let params = controller.fetchParams({ - scopeDays: 2 - }); - const shippedFrom = Date.vnNew(); - shippedFrom.setHours(0, 0, 0, 0); - const shippedTo = new Date(shippedFrom.getTime()); - shippedTo.setDate(shippedTo.getDate() + params.scopeDays); - shippedTo.setHours(23, 59, 59, 999); - - const expectedParams = { - shippedFrom, - scopeDays: params.scopeDays, - shippedTo - }; - - expect(params).toEqual(expectedParams); - }); - - it('should return default value for scope days', () => { - let params = controller.fetchParams({ - scopeDays: 1 - }); - - expect(params.scopeDays).toEqual(1); - }); - - it('should return the given scope days', () => { - let params = controller.fetchParams({ - scopeDays: 2 - }); - - expect(params.scopeDays).toEqual(2); - }); - }); -}); diff --git a/modules/travel/front/search-panel/index.spec.js b/modules/travel/front/search-panel/index.spec.js index 884f4fb17..488143e80 100644 --- a/modules/travel/front/search-panel/index.spec.js +++ b/modules/travel/front/search-panel/index.spec.js @@ -8,41 +8,31 @@ describe('Travel Component vnTravelSearchPanel', () => { beforeEach(inject($componentController => { controller = $componentController('vnTravelSearchPanel', {$element: null}); controller.$t = () => {}; - controller.filter = {}; })); - describe('shippedFrom() setter', () => { - it('should clear the scope days when setting the from property', () => { - controller.filter.scopeDays = 1; + describe('applyFilters()', () => { + it('should apply filters', async() => { + controller.filter = {foo: 'bar'}; + controller.model = { + applyFilter: jest.fn().mockResolvedValue(), + _orgData: [{id: 1}] + }; + controller.$state = { + current: { + name: 'foo' + }, + go: jest.fn() + }; - controller.shippedFrom = Date.vnNew(); + await controller.applyFilters(true); - expect(controller.filter.scopeDays).toBeNull(); - expect(controller.shippedFrom).toBeDefined(); - }); - }); + expect(controller.model.applyFilter).toHaveBeenCalledWith({}, controller.filter); + expect(controller.$state.go).toHaveBeenCalledWith('travel.card.summary', {id: 1}); - describe('shippedTo() setter', () => { - it('should clear the scope days when setting the to property', () => { - controller.filter.scopeDays = 1; + await controller.applyFilters(false); - controller.shippedTo = Date.vnNew(); - - expect(controller.filter.scopeDays).toBeNull(); - expect(controller.shippedTo).toBeDefined(); - }); - }); - - describe('scopeDays() setter', () => { - it('should clear the date range when setting the scopeDays property', () => { - controller.filter.shippedFrom = Date.vnNew(); - controller.filter.shippedTo = Date.vnNew(); - - controller.scopeDays = 1; - - expect(controller.filter.shippedFrom).toBeNull(); - expect(controller.filter.shippedTo).toBeNull(); - expect(controller.scopeDays).toBeDefined(); + expect(controller.$state.go).toHaveBeenCalledWith(controller.$state.current.name, + {q: JSON.stringify(controller.filter)}, {location: 'replace'}); }); }); }); From fa78649607e71d224b9e604ffbb4f58b34cf4b18 Mon Sep 17 00:00:00 2001 From: carlossa Date: Fri, 24 Mar 2023 08:54:03 +0100 Subject: [PATCH 40/95] refs #5439 url filter --- modules/item/front/request-search-panel/index.html | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/item/front/request-search-panel/index.html b/modules/item/front/request-search-panel/index.html index ae7f9bcc5..6316cb32e 100644 --- a/modules/item/front/request-search-panel/index.html +++ b/modules/item/front/request-search-panel/index.html @@ -42,10 +42,9 @@ {{firstName}} {{name}} From cfe4570d3b548f63561809c8d19c4064446a50c0 Mon Sep 17 00:00:00 2001 From: alexandre Date: Fri, 24 Mar 2023 09:21:55 +0100 Subject: [PATCH 41/95] refs #5206 e2es fixed --- e2e/paths/10-travel/02_basic_data_and_log.spec.js | 3 ++- e2e/paths/10-travel/03_descriptor.spec.js | 6 ++++-- e2e/paths/10-travel/05_thermograph.spec.js | 3 ++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/e2e/paths/10-travel/02_basic_data_and_log.spec.js b/e2e/paths/10-travel/02_basic_data_and_log.spec.js index bffcb8642..5abf8a65e 100644 --- a/e2e/paths/10-travel/02_basic_data_and_log.spec.js +++ b/e2e/paths/10-travel/02_basic_data_and_log.spec.js @@ -9,7 +9,8 @@ describe('Travel basic data path', () => { browser = await getBrowser(); page = browser.page; await page.loginAndModule('buyer', 'travel'); - await page.accessToSearchResult('3'); + await page.write(selectors.travelIndex.generalSearchFilter, '3'); + await page.keyboard.press('Enter'); await page.accessToSection('travel.card.basicData'); }); diff --git a/e2e/paths/10-travel/03_descriptor.spec.js b/e2e/paths/10-travel/03_descriptor.spec.js index 79dcad514..3752400c6 100644 --- a/e2e/paths/10-travel/03_descriptor.spec.js +++ b/e2e/paths/10-travel/03_descriptor.spec.js @@ -9,7 +9,8 @@ describe('Travel descriptor path', () => { browser = await getBrowser(); page = browser.page; await page.loginAndModule('buyer', 'travel'); - await page.accessToSearchResult('1'); + await page.write(selectors.travelIndex.generalSearchFilter, '1'); + await page.keyboard.press('Enter'); await page.waitForState('travel.card.summary'); }); @@ -81,7 +82,8 @@ describe('Travel descriptor path', () => { await page.waitToClick('.cancel'); await page.waitToClick(selectors.globalItems.homeButton); await page.selectModule('travel'); - await page.accessToSearchResult('3'); + await page.write(selectors.travelIndex.generalSearchFilter, '3'); + await page.keyboard.press('Enter'); await page.waitForState('travel.card.summary'); const state = await page.getState(); diff --git a/e2e/paths/10-travel/05_thermograph.spec.js b/e2e/paths/10-travel/05_thermograph.spec.js index a99dc8352..c9709f2f5 100644 --- a/e2e/paths/10-travel/05_thermograph.spec.js +++ b/e2e/paths/10-travel/05_thermograph.spec.js @@ -10,7 +10,8 @@ describe('Travel thermograph path', () => { browser = await getBrowser(); page = browser.page; await page.loginAndModule('buyer', 'travel'); - await page.accessToSearchResult('3'); + await page.write(selectors.travelIndex.generalSearchFilter, '3'); + await page.keyboard.press('Enter'); await page.accessToSection('travel.card.thermograph.index'); }); From f689d351007e4ef980ae8f661fd689d50a7f79ee Mon Sep 17 00:00:00 2001 From: vicent Date: Fri, 24 Mar 2023 10:05:17 +0100 Subject: [PATCH 42/95] refs #5410 fix test --- modules/client/front/defaulter/index.js | 4 +--- modules/client/front/defaulter/index.spec.js | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/modules/client/front/defaulter/index.js b/modules/client/front/defaulter/index.js index d8bf12bff..e084af650 100644 --- a/modules/client/front/defaulter/index.js +++ b/modules/client/front/defaulter/index.js @@ -145,9 +145,7 @@ export default class Controller extends Section { }); } - this.$http.post(`Mails`, params) .then(() => { - this.vnApp.showMessage(this.$t('Email sended!')); - }); + this.$http.post(`Mails`, params); } exprBuilder(param, value) { diff --git a/modules/client/front/defaulter/index.spec.js b/modules/client/front/defaulter/index.spec.js index 30c40132d..b9672802e 100644 --- a/modules/client/front/defaulter/index.spec.js +++ b/modules/client/front/defaulter/index.spec.js @@ -82,7 +82,7 @@ describe('client defaulter', () => { const params = [{text: controller.defaulter.observation, clientFk: data[1].clientFk}]; const mailParams = [{subject: 'Comment added to client', body: 'Added observation', receiver: 'undefined@verdnatura.es', replyTo: 'undefined@verdnatura.es'}]; - jest.spyOn(controller.vnApp, 'showMessage'); + jest.spyOn(controller.vnApp, 'showSuccess'); $httpBackend.expect('GET', `Defaulters/filter`).respond(200); $httpBackend.expect('POST', `ClientObservations`, params).respond(200, params); $httpBackend.expect('POST', `Mails`, mailParams).respond(200); @@ -90,7 +90,7 @@ describe('client defaulter', () => { controller.onResponse(); $httpBackend.flush(); - expect(controller.vnApp.showMessage).toHaveBeenCalledWith('Email sended!'); + expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Observation saved!'); }); }); From 925774c75bb3178545f071c016445987e5663100 Mon Sep 17 00:00:00 2001 From: vicent Date: Fri, 24 Mar 2023 10:16:39 +0100 Subject: [PATCH 43/95] refs #5331 add changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e7d1da557..5caefa59f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - (Monitor tickets) Muestra un icono al lado de la zona, si el ticket es frágil y se envía por agencia ### Changed -- +- (Monitor tickets) Cuando se filtra por 'Pendiente' ya no muestra los estados de 'Previa' ### Fixed - From c68c78cc5b80fb7f935e86862e52d0c5479a344f Mon Sep 17 00:00:00 2001 From: carlossa Date: Fri, 24 Mar 2023 12:11:42 +0100 Subject: [PATCH 44/95] refs #5250 solucion error WorkerObserv --- db/changes/231201/00-workerNotes.sql | 6 ++- modules/worker/back/model-config.json | 3 ++ .../worker/back/models/worker-observation.js | 13 +++++++ .../back/models/worker-observation.json | 39 +++++++++++++++++++ modules/worker/front/note/index/index.html | 5 ++- 5 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 modules/worker/back/models/worker-observation.js create mode 100644 modules/worker/back/models/worker-observation.json diff --git a/db/changes/231201/00-workerNotes.sql b/db/changes/231201/00-workerNotes.sql index 602ea3296..0d9eaae7e 100644 --- a/db/changes/231201/00-workerNotes.sql +++ b/db/changes/231201/00-workerNotes.sql @@ -7,4 +7,8 @@ CREATE TABLE `vn`.`workerObservation` ( PRIMARY KEY (`id`), CONSTRAINT `workerFk_workerObservation_FK` FOREIGN KEY (`workerFk`) REFERENCES `vn`.`worker` (`id`) ON UPDATE CASCADE, CONSTRAINT `userFk_workerObservation_FK` FOREIGN KEY (`userFk`) REFERENCES `account`.`user`(`id`) ON UPDATE CASCADE -) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci COMMENT='Todas las observaciones referentes a un trabajador'; \ No newline at end of file +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci COMMENT='Todas las observaciones referentes a un trabajador'; + +INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) + VALUES + ('WorkerObservation', '*', '*', 'ALLOW', 'ROLE', 'hr'); diff --git a/modules/worker/back/model-config.json b/modules/worker/back/model-config.json index 63fc65827..145934700 100644 --- a/modules/worker/back/model-config.json +++ b/modules/worker/back/model-config.json @@ -53,6 +53,9 @@ "Worker": { "dataSource": "vn" }, + "WorkerObservation": { + "dataSource": "vn" + }, "WorkerConfig": { "dataSource": "vn" }, diff --git a/modules/worker/back/models/worker-observation.js b/modules/worker/back/models/worker-observation.js new file mode 100644 index 000000000..3a4480265 --- /dev/null +++ b/modules/worker/back/models/worker-observation.js @@ -0,0 +1,13 @@ +module.exports = function(Self) { + Self.validate('text', isEnabled, {message: 'Description cannot be blank'}); + function isEnabled(err) { + if (!this.text) err(); + } + + Self.observe('before save', async function(ctx) { + ctx.instance.created = new Date(); + let token = ctx.options.accessToken; + let userId = token && token.userId; + ctx.instance.userFk = userId; + }); +}; diff --git a/modules/worker/back/models/worker-observation.json b/modules/worker/back/models/worker-observation.json new file mode 100644 index 000000000..90eb35837 --- /dev/null +++ b/modules/worker/back/models/worker-observation.json @@ -0,0 +1,39 @@ +{ + "name": "WorkerObservation", + "base": "VnModel", + "options": { + "mysql": { + "table": "workerObservation" + } + }, + "properties": { + "id": { + "id": true, + "type": "number" + }, + "workerFk": { + "type": "number" + }, + "userFk": { + "type": "number" + }, + "text": { + "type": "string" + }, + "created": { + "type": "date" + } + }, + "relations": { + "worker": { + "type": "belongsTo", + "model": "Worker", + "foreignKey": "workerFk" + }, + "user":{ + "type": "belongsTo", + "model": "Account", + "foreignKey": "userFk" + } + } +} diff --git a/modules/worker/front/note/index/index.html b/modules/worker/front/note/index/index.html index 4b72d60ab..9f5c27008 100644 --- a/modules/worker/front/note/index/index.html +++ b/modules/worker/front/note/index/index.html @@ -1,8 +1,9 @@ @@ -14,7 +15,7 @@ ng-repeat="note in notes" class="note vn-pa-sm border-solid border-radius vn-mb-md"> - {{::note.worker.user.nickname}} + {{::note.user.nickname}} {{::note.created | date:'dd/MM/yyyy HH:mm'}} From 871618b122ddee5e48ddf510461223efdfdfd0ec Mon Sep 17 00:00:00 2001 From: vicent Date: Fri, 24 Mar 2023 12:29:58 +0100 Subject: [PATCH 45/95] fix: faltaba el esquema --- db/changes/231201/00-itemType_isFragile.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/db/changes/231201/00-itemType_isFragile.sql b/db/changes/231201/00-itemType_isFragile.sql index 5b25288f3..ecc1bfbb2 100644 --- a/db/changes/231201/00-itemType_isFragile.sql +++ b/db/changes/231201/00-itemType_isFragile.sql @@ -8,7 +8,7 @@ WHERE code IN ('ZKA', 'ZKE'); UPDATE `vn`.`itemType` SET isFragile = 1 WHERE id IN (SELECT it.id - FROM itemCategory ic - JOIN itemType it ON it.categoryFk = ic.id + FROM `vn`.`itemCategory` ic + JOIN `vn`.`itemType` it ON it.categoryFk = ic.id WHERE ic.code = 'plant'); From c65f01b6894fcd4dd4e0da3a7c7c98442363788b Mon Sep 17 00:00:00 2001 From: vicent Date: Fri, 24 Mar 2023 12:30:18 +0100 Subject: [PATCH 46/95] refs #5416 delete: supplierAccount triggers --- db/changes/231201/00-supplierAccount_deleteTriggers.sql | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 db/changes/231201/00-supplierAccount_deleteTriggers.sql diff --git a/db/changes/231201/00-supplierAccount_deleteTriggers.sql b/db/changes/231201/00-supplierAccount_deleteTriggers.sql new file mode 100644 index 000000000..d7f9f734a --- /dev/null +++ b/db/changes/231201/00-supplierAccount_deleteTriggers.sql @@ -0,0 +1,3 @@ +DROP TRIGGER `vn`.`supplierAccount_afterInsert`; +DROP TRIGGER `vn`.`supplierAccount_afterUpdate`; +DROP TRIGGER `vn`.`supplierAccount_afterDelete`; From 6f2de903bcdf44dc78a186408e1801e7efbf2466 Mon Sep 17 00:00:00 2001 From: alexandre Date: Mon, 27 Mar 2023 14:29:22 +0200 Subject: [PATCH 47/95] refs #5184 working on search panel --- db/changes/231201/.gitkeep | 0 db/changes/231201/00-invoiceInSerial.sql | 4 ++ db/dump/fixtures.sql | 4 +- .../back/methods/invoice-in/getSerial.js | 34 +++++++++++++++ .../back/models/invoice-in-config.json | 3 ++ modules/invoiceIn/back/models/invoice-in.js | 1 + modules/invoiceIn/front/index.js | 2 + modules/invoiceIn/front/locale/es.yml | 1 + modules/invoiceIn/front/routes.json | 15 ++++++- .../front/serial-search-panel/index.html | 26 ++++++++++++ .../front/serial-search-panel/index.js | 41 ++++++++++++++++++ .../front/serial-search-panel/style.scss | 24 +++++++++++ modules/invoiceIn/front/serial/index.html | 42 +++++++++++++++++++ modules/invoiceIn/front/serial/index.js | 35 ++++++++++++++++ modules/invoiceIn/front/serial/locale/es.yml | 3 ++ 15 files changed, 232 insertions(+), 3 deletions(-) delete mode 100644 db/changes/231201/.gitkeep create mode 100644 db/changes/231201/00-invoiceInSerial.sql create mode 100644 modules/invoiceIn/back/methods/invoice-in/getSerial.js create mode 100644 modules/invoiceIn/front/serial-search-panel/index.html create mode 100644 modules/invoiceIn/front/serial-search-panel/index.js create mode 100644 modules/invoiceIn/front/serial-search-panel/style.scss create mode 100644 modules/invoiceIn/front/serial/index.html create mode 100644 modules/invoiceIn/front/serial/index.js create mode 100644 modules/invoiceIn/front/serial/locale/es.yml diff --git a/db/changes/231201/.gitkeep b/db/changes/231201/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/db/changes/231201/00-invoiceInSerial.sql b/db/changes/231201/00-invoiceInSerial.sql new file mode 100644 index 000000000..de476027c --- /dev/null +++ b/db/changes/231201/00-invoiceInSerial.sql @@ -0,0 +1,4 @@ +ALTER TABLE `vn`.`invoiceInConfig` ADD daysAgo INT UNSIGNED DEFAULT 45 COMMENT 'Días en el pasado para mostrar facturas en invoiceIn series en salix'; +INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) + VALUES + ('InvoiceIn', 'getSerial', 'READ', 'ALLOW', 'ROLE', 'administrative'); diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index e9c70878f..61b7cba9e 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -2490,9 +2490,9 @@ REPLACE INTO `vn`.`invoiceIn`(`id`, `serialNumber`,`serial`, `supplierFk`, `issu (9, 1009, 'R', 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1242, 1, 442, 1), (10, 1010, 'R', 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1243, 1, 442, 1); -INSERT INTO `vn`.`invoiceInConfig` (`id`, `retentionRate`, `retentionName`, `sageWithholdingFk`) +INSERT INTO `vn`.`invoiceInConfig` (`id`, `retentionRate`, `retentionName`, `sageWithholdingFk`, `daysAgo`) VALUES - (1, -2, '2% retention', 2); + (1, -2, '2% retention', 2, 45); INSERT INTO `vn`.`invoiceInDueDay`(`invoiceInFk`, `dueDated`, `bankFk`, `amount`) VALUES diff --git a/modules/invoiceIn/back/methods/invoice-in/getSerial.js b/modules/invoiceIn/back/methods/invoice-in/getSerial.js new file mode 100644 index 000000000..8635a0be7 --- /dev/null +++ b/modules/invoiceIn/back/methods/invoice-in/getSerial.js @@ -0,0 +1,34 @@ +module.exports = Self => { + Self.remoteMethod('getSerial', { + description: 'Return invoiceIn serial', + accessType: 'READ', + accepts: { + arg: 'issued', + type: 'date', + required: true + }, + returns: { + type: 'object', + root: true + }, + http: { + path: '/getSerial', + verb: 'GET' + } + }); + + Self.getSerial = async(issued, options) => { + const myOptions = {}; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + const result = await Self.rawSql(` + SELECT i.serial, SUM(IF(i.isBooked, 0,1)) pending, COUNT(*) total + FROM vn.invoiceIn i + WHERE i.issued >= ? + GROUP BY i.serial`, [issued]); + + return result; + }; +}; diff --git a/modules/invoiceIn/back/models/invoice-in-config.json b/modules/invoiceIn/back/models/invoice-in-config.json index 5cf0ed64c..c0236e654 100644 --- a/modules/invoiceIn/back/models/invoice-in-config.json +++ b/modules/invoiceIn/back/models/invoice-in-config.json @@ -17,6 +17,9 @@ }, "retentionName": { "type": "string" + }, + "daysAgo": { + "type": "number" } }, "relations": { diff --git a/modules/invoiceIn/back/models/invoice-in.js b/modules/invoiceIn/back/models/invoice-in.js index 95ccc7b20..51905ccb8 100644 --- a/modules/invoiceIn/back/models/invoice-in.js +++ b/modules/invoiceIn/back/models/invoice-in.js @@ -6,4 +6,5 @@ module.exports = Self => { require('../methods/invoice-in/getTotals')(Self); require('../methods/invoice-in/invoiceInPdf')(Self); require('../methods/invoice-in/invoiceInEmail')(Self); + require('../methods/invoice-in/getSerial')(Self); }; diff --git a/modules/invoiceIn/front/index.js b/modules/invoiceIn/front/index.js index 7b6d6a77c..e257cfee3 100644 --- a/modules/invoiceIn/front/index.js +++ b/modules/invoiceIn/front/index.js @@ -13,3 +13,5 @@ import './dueDay'; import './intrastat'; import './create'; import './log'; +import './serial'; +import './serial-search-panel'; diff --git a/modules/invoiceIn/front/locale/es.yml b/modules/invoiceIn/front/locale/es.yml index 35b43f9f6..f2f77b690 100644 --- a/modules/invoiceIn/front/locale/es.yml +++ b/modules/invoiceIn/front/locale/es.yml @@ -7,6 +7,7 @@ Foreign value: Divisa InvoiceIn: Facturas recibidas InvoiceIn cloned: Factura clonada InvoiceIn deleted: Factura eliminada +InvoiceIn Serial: Facturas por series Invoice list: Listado de facturas recibidas InvoiceIn booked: Factura contabilizada Net: Neto diff --git a/modules/invoiceIn/front/routes.json b/modules/invoiceIn/front/routes.json index 4867b7db9..90c4f8472 100644 --- a/modules/invoiceIn/front/routes.json +++ b/modules/invoiceIn/front/routes.json @@ -12,6 +12,10 @@ { "state": "invoiceIn.index", "icon": "icon-invoice-in" + }, + { + "state": "invoiceIn.serial", + "icon": "icon-invoice-in" } ], "card": [ @@ -54,6 +58,15 @@ "administrative" ] }, + { + "url": "/serial", + "state": "invoiceIn.serial", + "component": "vn-invoice-in-serial", + "description": "InvoiceIn Serial", + "acl": [ + "administrative" + ] + }, { "url": "/:id", "state": "invoiceIn.card", @@ -133,4 +146,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/modules/invoiceIn/front/serial-search-panel/index.html b/modules/invoiceIn/front/serial-search-panel/index.html new file mode 100644 index 000000000..467f7439c --- /dev/null +++ b/modules/invoiceIn/front/serial-search-panel/index.html @@ -0,0 +1,26 @@ + + + + + + + + + +
+ + Id/Name: {{$ctrl.filter.search}} + +
+
diff --git a/modules/invoiceIn/front/serial-search-panel/index.js b/modules/invoiceIn/front/serial-search-panel/index.js new file mode 100644 index 000000000..334e4cf01 --- /dev/null +++ b/modules/invoiceIn/front/serial-search-panel/index.js @@ -0,0 +1,41 @@ +import ngModule from '../module'; +import SearchPanel from 'core/components/searchbar/search-panel'; +import './style.scss'; + +class Controller extends SearchPanel { + constructor($element, $) { + super($element, $); + const filter = { + fields: ['daysAgo'] + }; + this.$http.get('InvoiceInConfigs', {filter}); + } + + $onInit() { + this.filter = { + tags: [] + }; + } + + removeItemFilter(param) { + this.filter[param] = null; + this.addFilters(); + } + + onKeyPress($event) { + if ($event.key === 'Enter') + this.addFilters(); + } + + addFilters() { + return this.model.addFilter({}, this.filter); + } +} + +ngModule.component('vnInvoiceInSerialSearchPanel', { + template: require('./index.html'), + controller: Controller, + bindings: { + model: '<' + } +}); diff --git a/modules/invoiceIn/front/serial-search-panel/style.scss b/modules/invoiceIn/front/serial-search-panel/style.scss new file mode 100644 index 000000000..4abfcbfa2 --- /dev/null +++ b/modules/invoiceIn/front/serial-search-panel/style.scss @@ -0,0 +1,24 @@ +@import "variables"; + +vn-invoice-in-serial-search-panel vn-side-menu div { + & > .input { + padding-left: $spacing-md; + padding-right: $spacing-md; + border-color: $color-spacer; + border-bottom: $border-thin; + } + & > .horizontal { + grid-auto-flow: column; + grid-column-gap: $spacing-sm; + align-items: center; + } + & > .chips { + display: flex; + flex-wrap: wrap; + padding: $spacing-md; + overflow: hidden; + max-width: 100%; + border-color: $color-spacer; + border-top: $border-thin; + } +} diff --git a/modules/invoiceIn/front/serial/index.html b/modules/invoiceIn/front/serial/index.html new file mode 100644 index 000000000..f8ca4bbbb --- /dev/null +++ b/modules/invoiceIn/front/serial/index.html @@ -0,0 +1,42 @@ + + + + + + + + + + + + Serial + Pending + Total + + + + + + {{::invoiceIn.serial}} + {{::invoiceIn.pending}} + {{::invoiceIn.total}} + + + + + + + + + diff --git a/modules/invoiceIn/front/serial/index.js b/modules/invoiceIn/front/serial/index.js new file mode 100644 index 000000000..622087748 --- /dev/null +++ b/modules/invoiceIn/front/serial/index.js @@ -0,0 +1,35 @@ +import ngModule from '../module'; +import Section from 'salix/components/section'; + +export default class Controller extends Section { + constructor($element, $) { + super($element, $); + } + + exprBuilder(param, value) { + switch (param) { + case 'issued': + return {'ii.issued': { + between: this.dateRange(value)} + }; + case 'serial': + return {[`ii.${param}`]: value}; + } + } + + dateRange(value) { + const minHour = new Date(value); + minHour.setHours(0, 0, 0, 0); + const maxHour = new Date(value); + maxHour.setHours(23, 59, 59, 59); + + return [minHour, maxHour]; + } +} + +Controller.$inject = ['$element', '$scope']; + +ngModule.vnComponent('vnInvoiceInSerial', { + template: require('./index.html'), + controller: Controller +}); diff --git a/modules/invoiceIn/front/serial/locale/es.yml b/modules/invoiceIn/front/serial/locale/es.yml new file mode 100644 index 000000000..92a49cc82 --- /dev/null +++ b/modules/invoiceIn/front/serial/locale/es.yml @@ -0,0 +1,3 @@ +Serial: Serie +Pending: Pendientes +Go to InvoiceIn: Ir al listado de facturas recibidas From 87d0dc3cece9d674ff70e65894bf70d02932e7d8 Mon Sep 17 00:00:00 2001 From: alexandre Date: Tue, 28 Mar 2023 08:25:41 +0200 Subject: [PATCH 48/95] refs #5092 changed name to negative bases --- db/changes/231201/00-negativeBases.sql | 4 ++++ db/changes/231201/00-unbilledClients.sql | 4 ---- ...d_clients.spec.js => 05_negative_bases.spec.js} | 8 ++++---- .../{unbilledClients.js => negativeBases.js} | 12 ++++++------ .../{unbilledClientsCsv.js => negativeBasesCsv.js} | 14 +++++++------- ...billedClients.spec.js => negativeBases.spec.js} | 8 ++++---- modules/invoiceIn/back/models/invoice-in.js | 4 ++-- modules/invoiceIn/front/index.js | 2 +- modules/invoiceIn/front/locale/es.yml | 2 +- .../index.html | 2 +- .../{unbilled-clients => negative-bases}/index.js | 6 +++--- .../locale/es.yml | 0 .../style.scss | 2 +- modules/invoiceIn/front/routes.json | 10 +++++----- 14 files changed, 39 insertions(+), 39 deletions(-) create mode 100644 db/changes/231201/00-negativeBases.sql delete mode 100644 db/changes/231201/00-unbilledClients.sql rename e2e/paths/09-invoice-in/{05_unbilled_clients.spec.js => 05_negative_bases.spec.js} (70%) rename modules/invoiceIn/back/methods/invoice-in/{unbilledClients.js => negativeBases.js} (92%) rename modules/invoiceIn/back/methods/invoice-in/{unbilledClientsCsv.js => negativeBasesCsv.js} (69%) rename modules/invoiceIn/back/methods/invoice-in/specs/{unbilledClients.spec.js => negativeBases.spec.js} (79%) rename modules/invoiceIn/front/{unbilled-clients => negative-bases}/index.html (99%) rename modules/invoiceIn/front/{unbilled-clients => negative-bases}/index.js (94%) rename modules/invoiceIn/front/{unbilled-clients => negative-bases}/locale/es.yml (100%) rename modules/invoiceIn/front/{unbilled-clients => negative-bases}/style.scss (85%) diff --git a/db/changes/231201/00-negativeBases.sql b/db/changes/231201/00-negativeBases.sql new file mode 100644 index 000000000..0bdc6f2dc --- /dev/null +++ b/db/changes/231201/00-negativeBases.sql @@ -0,0 +1,4 @@ +INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) + VALUES + ('InvoiceIn', 'negativeBases', 'READ', 'ALLOW', 'ROLE', 'administrative'), + ('InvoiceIn', 'negativeBasesCsv', 'READ', 'ALLOW', 'ROLE', 'administrative'); diff --git a/db/changes/231201/00-unbilledClients.sql b/db/changes/231201/00-unbilledClients.sql deleted file mode 100644 index 16127dd18..000000000 --- a/db/changes/231201/00-unbilledClients.sql +++ /dev/null @@ -1,4 +0,0 @@ -INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) - VALUES - ('InvoiceIn', 'unbilledClients', 'READ', 'ALLOW', 'ROLE', 'administrative'), - ('InvoiceIn', 'unbilledClientsCsv', 'READ', 'ALLOW', 'ROLE', 'administrative'); diff --git a/e2e/paths/09-invoice-in/05_unbilled_clients.spec.js b/e2e/paths/09-invoice-in/05_negative_bases.spec.js similarity index 70% rename from e2e/paths/09-invoice-in/05_unbilled_clients.spec.js rename to e2e/paths/09-invoice-in/05_negative_bases.spec.js index 629f24404..4c9fe651f 100644 --- a/e2e/paths/09-invoice-in/05_unbilled_clients.spec.js +++ b/e2e/paths/09-invoice-in/05_negative_bases.spec.js @@ -1,6 +1,6 @@ import getBrowser from '../../helpers/puppeteer'; -describe('InvoiceIn unbilled clients path', () => { +describe('InvoiceIn negative bases path', () => { let browser; let page; const httpRequests = []; @@ -9,18 +9,18 @@ describe('InvoiceIn unbilled clients path', () => { browser = await getBrowser(); page = browser.page; page.on('request', req => { - if (req.url().includes(`InvoiceIns/unbilledClients`)) + if (req.url().includes(`InvoiceIns/negativeBases`)) httpRequests.push(req.url()); }); await page.loginAndModule('administrative', 'invoiceIn'); - await page.accessToSection('invoiceIn.unbilled-clients'); + await page.accessToSection('invoiceIn.negative-bases'); }); afterAll(async() => { await browser.close(); }); - it('should show unbilled clients in a date range', async() => { + it('should show negative bases in a date range', async() => { const request = httpRequests.find(req => req.includes(`from`) && req.includes(`to`)); diff --git a/modules/invoiceIn/back/methods/invoice-in/unbilledClients.js b/modules/invoiceIn/back/methods/invoice-in/negativeBases.js similarity index 92% rename from modules/invoiceIn/back/methods/invoice-in/unbilledClients.js rename to modules/invoiceIn/back/methods/invoice-in/negativeBases.js index 216af4d48..4d5975fab 100644 --- a/modules/invoiceIn/back/methods/invoice-in/unbilledClients.js +++ b/modules/invoiceIn/back/methods/invoice-in/negativeBases.js @@ -2,8 +2,8 @@ const UserError = require('vn-loopback/util/user-error'); const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; module.exports = Self => { - Self.remoteMethodCtx('unbilledClients', { - description: 'Find all unbilled clients', + Self.remoteMethodCtx('negativeBases', { + description: 'Find all negative bases', accessType: 'READ', accepts: [ { @@ -27,12 +27,12 @@ module.exports = Self => { root: true }, http: { - path: `/unbilledClients`, + path: `/negativeBases`, verb: 'GET' } }); - Self.unbilledClients = async(ctx, options) => { + Self.negativeBases = async(ctx, options) => { const conn = Self.dataSource.connector; const args = ctx.args; @@ -99,14 +99,14 @@ module.exports = Self => { stmt.merge(conn.makeWhere(args.filter.where)); stmt.merge(conn.makeOrderBy(args.filter.order)); - const clientsIndex = stmts.push(stmt) - 1; + const negativeBasesIndex = stmts.push(stmt) - 1; stmts.push(`DROP TEMPORARY TABLE tmp.filter, tmp.ticket, tmp.ticketTax, tmp.ticketAmount`); const sql = ParameterizedSQL.join(stmts, ';'); const result = await conn.executeStmt(sql, myOptions); - return clientsIndex === 0 ? result : result[clientsIndex]; + return negativeBasesIndex === 0 ? result : result[negativeBasesIndex]; }; }; diff --git a/modules/invoiceIn/back/methods/invoice-in/unbilledClientsCsv.js b/modules/invoiceIn/back/methods/invoice-in/negativeBasesCsv.js similarity index 69% rename from modules/invoiceIn/back/methods/invoice-in/unbilledClientsCsv.js rename to modules/invoiceIn/back/methods/invoice-in/negativeBasesCsv.js index f9b30d83b..963151b7d 100644 --- a/modules/invoiceIn/back/methods/invoice-in/unbilledClientsCsv.js +++ b/modules/invoiceIn/back/methods/invoice-in/negativeBasesCsv.js @@ -1,11 +1,11 @@ const {toCSV} = require('vn-loopback/util/csv'); module.exports = Self => { - Self.remoteMethodCtx('unbilledClientsCsv', { - description: 'Returns the unbilled clients as .csv', + Self.remoteMethodCtx('negativeBasesCsv', { + description: 'Returns the negative bases as .csv', accessType: 'READ', accepts: [{ - arg: 'unbilledClients', + arg: 'negativeBases', type: ['object'], required: true }, @@ -35,19 +35,19 @@ module.exports = Self => { } ], http: { - path: '/unbilledClientsCsv', + path: '/negativeBasesCsv', verb: 'GET' } }); - Self.unbilledClientsCsv = async ctx => { + Self.negativeBasesCsv = async ctx => { const args = ctx.args; - const content = toCSV(args.unbilledClients); + const content = toCSV(args.negativeBases); return [ content, 'text/csv', - `attachment; filename="unbilled-clients-${new Date(args.from).toLocaleDateString()}-${new Date(args.to).toLocaleDateString()}.csv"` + `attachment; filename="negative-bases-${new Date(args.from).toLocaleDateString()}-${new Date(args.to).toLocaleDateString()}.csv"` ]; }; }; diff --git a/modules/invoiceIn/back/methods/invoice-in/specs/unbilledClients.spec.js b/modules/invoiceIn/back/methods/invoice-in/specs/negativeBases.spec.js similarity index 79% rename from modules/invoiceIn/back/methods/invoice-in/specs/unbilledClients.spec.js rename to modules/invoiceIn/back/methods/invoice-in/specs/negativeBases.spec.js index fcb3173ab..a5c6e3102 100644 --- a/modules/invoiceIn/back/methods/invoice-in/specs/unbilledClients.spec.js +++ b/modules/invoiceIn/back/methods/invoice-in/specs/negativeBases.spec.js @@ -1,7 +1,7 @@ const models = require('vn-loopback/server/server').models; -describe('invoiceIn unbilledClients()', () => { - it('should return all unbilled clients in a date range', async() => { +describe('invoiceIn negativeBases()', () => { + it('should return all negative bases in a date range', async() => { const tx = await models.InvoiceIn.beginTransaction({}); const options = {transaction: tx}; const ctx = { @@ -13,7 +13,7 @@ describe('invoiceIn unbilledClients()', () => { }; try { - const result = await models.InvoiceIn.unbilledClients(ctx, options); + const result = await models.InvoiceIn.negativeBases(ctx, options); expect(result.length).toBeGreaterThan(0); @@ -35,7 +35,7 @@ describe('invoiceIn unbilledClients()', () => { }; try { - await models.InvoiceIn.unbilledClients(ctx, options); + await models.InvoiceIn.negativeBases(ctx, options); await tx.rollback(); } catch (e) { error = e; diff --git a/modules/invoiceIn/back/models/invoice-in.js b/modules/invoiceIn/back/models/invoice-in.js index ebb2981e1..d87b8c111 100644 --- a/modules/invoiceIn/back/models/invoice-in.js +++ b/modules/invoiceIn/back/models/invoice-in.js @@ -6,6 +6,6 @@ module.exports = Self => { require('../methods/invoice-in/getTotals')(Self); require('../methods/invoice-in/invoiceInPdf')(Self); require('../methods/invoice-in/invoiceInEmail')(Self); - require('../methods/invoice-in/unbilledClients')(Self); - require('../methods/invoice-in/unbilledClientsCsv')(Self); + require('../methods/invoice-in/negativeBases')(Self); + require('../methods/invoice-in/negativeBasesCsv')(Self); }; diff --git a/modules/invoiceIn/front/index.js b/modules/invoiceIn/front/index.js index 7576848bf..69593dd5b 100644 --- a/modules/invoiceIn/front/index.js +++ b/modules/invoiceIn/front/index.js @@ -13,4 +13,4 @@ import './dueDay'; import './intrastat'; import './create'; import './log'; -import './unbilled-clients'; +import './negative-bases'; diff --git a/modules/invoiceIn/front/locale/es.yml b/modules/invoiceIn/front/locale/es.yml index 2b444f75b..71fd3b87b 100644 --- a/modules/invoiceIn/front/locale/es.yml +++ b/modules/invoiceIn/front/locale/es.yml @@ -22,4 +22,4 @@ Total stems: Total tallos Show agricultural receipt as PDF: Ver recibo agrícola como PDF Send agricultural receipt as PDF: Enviar recibo agrícola como PDF New InvoiceIn: Nueva Factura -Unbilled clients: Clientes sin facturar +Negative bases: Bases negativas diff --git a/modules/invoiceIn/front/unbilled-clients/index.html b/modules/invoiceIn/front/negative-bases/index.html similarity index 99% rename from modules/invoiceIn/front/unbilled-clients/index.html rename to modules/invoiceIn/front/negative-bases/index.html index c4c561191..368f44461 100644 --- a/modules/invoiceIn/front/unbilled-clients/index.html +++ b/modules/invoiceIn/front/negative-bases/index.html @@ -1,6 +1,6 @@ diff --git a/modules/invoiceIn/front/unbilled-clients/index.js b/modules/invoiceIn/front/negative-bases/index.js similarity index 94% rename from modules/invoiceIn/front/unbilled-clients/index.js rename to modules/invoiceIn/front/negative-bases/index.js index b1f55abac..0f6f04692 100644 --- a/modules/invoiceIn/front/unbilled-clients/index.js +++ b/modules/invoiceIn/front/negative-bases/index.js @@ -68,8 +68,8 @@ export default class Controller extends Section { return result; }, {})); }); - this.vnReport.show('InvoiceIns/unbilledClientsCsv', { - unbilledClients: data, + this.vnReport.show('InvoiceIns/negativeBasesCsv', { + negativeBases: data, from: this.params.from, to: this.params.to }); @@ -78,7 +78,7 @@ export default class Controller extends Section { Controller.$inject = ['$element', '$scope', 'vnReport']; -ngModule.vnComponent('vnUnbilledClients', { +ngModule.vnComponent('vnNegativeBases', { template: require('./index.html'), controller: Controller }); diff --git a/modules/invoiceIn/front/unbilled-clients/locale/es.yml b/modules/invoiceIn/front/negative-bases/locale/es.yml similarity index 100% rename from modules/invoiceIn/front/unbilled-clients/locale/es.yml rename to modules/invoiceIn/front/negative-bases/locale/es.yml diff --git a/modules/invoiceIn/front/unbilled-clients/style.scss b/modules/invoiceIn/front/negative-bases/style.scss similarity index 85% rename from modules/invoiceIn/front/unbilled-clients/style.scss rename to modules/invoiceIn/front/negative-bases/style.scss index dbed8b967..2d628cb94 100644 --- a/modules/invoiceIn/front/unbilled-clients/style.scss +++ b/modules/invoiceIn/front/negative-bases/style.scss @@ -1,6 +1,6 @@ @import "./variables"; -vn-unbilled-clients { +vn-negative-bases { vn-date-picker{ padding-right: 5%; } diff --git a/modules/invoiceIn/front/routes.json b/modules/invoiceIn/front/routes.json index 567323571..0d95c7e80 100644 --- a/modules/invoiceIn/front/routes.json +++ b/modules/invoiceIn/front/routes.json @@ -10,7 +10,7 @@ "menus": { "main": [ { "state": "invoiceIn.index", "icon": "icon-invoice-in"}, - { "state": "invoiceIn.unbilled-clients", "icon": "person"} + { "state": "invoiceIn.negative-bases", "icon": "icon-ticket"} ], "card": [ { @@ -53,10 +53,10 @@ ] }, { - "url": "/unbilled-clients", - "state": "invoiceIn.unbilled-clients", - "component": "vn-unbilled-clients", - "description": "Unbilled clients", + "url": "/negative-bases", + "state": "invoiceIn.negative-bases", + "component": "vn-negative-bases", + "description": "Negative bases", "acl": [ "administrative" ] From 06ac8f9910991c4991d3c10359233e78af4ca02c Mon Sep 17 00:00:00 2001 From: vicent Date: Tue, 28 Mar 2023 09:41:39 +0200 Subject: [PATCH 49/95] refs #5275 fix: si tenia valor el minPrice el checkbox siempre se marcaba. El checkbox no funcionaba cuando le pulsabas --- modules/item/back/methods/fixed-price/upsertFixedPrice.js | 2 +- modules/item/front/fixed-price/index.html | 3 ++- modules/item/front/fixed-price/index.js | 2 -- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/modules/item/back/methods/fixed-price/upsertFixedPrice.js b/modules/item/back/methods/fixed-price/upsertFixedPrice.js index eb3eec1bd..edbd23604 100644 --- a/modules/item/back/methods/fixed-price/upsertFixedPrice.js +++ b/modules/item/back/methods/fixed-price/upsertFixedPrice.js @@ -87,7 +87,7 @@ module.exports = Self => { await targetItem.updateAttributes({ minPrice: args.minPrice, - hasMinPrice: args.minPrice ? true : false + hasMinPrice: args.hasMinPrice }, myOptions); const itemFields = [ diff --git a/modules/item/front/fixed-price/index.html b/modules/item/front/fixed-price/index.html index ce7cefe7a..43fe89552 100644 --- a/modules/item/front/fixed-price/index.html +++ b/modules/item/front/fixed-price/index.html @@ -140,7 +140,8 @@ + ng-model="price.hasMinPrice" + on-change="$ctrl.upsertPrice(price)"> Date: Tue, 28 Mar 2023 10:07:14 +0200 Subject: [PATCH 50/95] refs #5250 Self.validatesPresenceOf --- modules/worker/back/models/worker-observation.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/worker/back/models/worker-observation.js b/modules/worker/back/models/worker-observation.js index 3a4480265..413d9a2ba 100644 --- a/modules/worker/back/models/worker-observation.js +++ b/modules/worker/back/models/worker-observation.js @@ -1,5 +1,5 @@ module.exports = function(Self) { - Self.validate('text', isEnabled, {message: 'Description cannot be blank'}); + Self.validatesPresenceOf('text', isEnabled, {message: 'Description cannot be blank'}); function isEnabled(err) { if (!this.text) err(); } From fb1b39da175c107b1bc0cbee14dc177ffed5c518 Mon Sep 17 00:00:00 2001 From: vicent Date: Tue, 28 Mar 2023 10:30:02 +0200 Subject: [PATCH 51/95] =?UTF-8?q?refs=20#5275=20fix:=20al=20a=C3=B1adir=20?= =?UTF-8?q?art=C3=ADculo=20desde=20cero=20se=20muestra=20el=20nombre=20y?= =?UTF-8?q?=20se=20establecen=20las=20fechas=20por=20defecto?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../back/methods/fixed-price/upsertFixedPrice.js | 2 +- modules/item/front/fixed-price/index.html | 3 ++- modules/item/front/fixed-price/index.js | 12 +++++++++++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/modules/item/back/methods/fixed-price/upsertFixedPrice.js b/modules/item/back/methods/fixed-price/upsertFixedPrice.js index edbd23604..d815ed426 100644 --- a/modules/item/back/methods/fixed-price/upsertFixedPrice.js +++ b/modules/item/back/methods/fixed-price/upsertFixedPrice.js @@ -87,7 +87,7 @@ module.exports = Self => { await targetItem.updateAttributes({ minPrice: args.minPrice, - hasMinPrice: args.hasMinPrice + hasMinPrice: args.hasMinPrice ? args.hasMinPrice : false }, myOptions); const itemFields = [ diff --git a/modules/item/front/fixed-price/index.html b/modules/item/front/fixed-price/index.html index 43fe89552..584c4b14e 100644 --- a/modules/item/front/fixed-price/index.html +++ b/modules/item/front/fixed-price/index.html @@ -64,6 +64,7 @@ - {{price.name}} + {{itemFk.selection.name}}

{{price.subName}}

diff --git a/modules/item/front/fixed-price/index.js b/modules/item/front/fixed-price/index.js index 2eb53cfbd..1a7bf6466 100644 --- a/modules/item/front/fixed-price/index.js +++ b/modules/item/front/fixed-price/index.js @@ -36,7 +36,17 @@ export default class Controller extends Section { if (!this.$.model.data || this.$.model.data.length == 0) { this.$.model.data = []; this.$.model.proxiedData = []; - this.$.model.insert({}); + + const today = Date.vnNew(); + + const millisecsInDay = 86400000; + const daysInWeek = 7; + const nextWeek = new Date(today.getTime() + daysInWeek * millisecsInDay); + + this.$.model.insert({ + started: today, + ended: nextWeek + }); return; } From 695444f6ae4d7a65d909b1189a4880c327a26511 Mon Sep 17 00:00:00 2001 From: alexandre Date: Tue, 28 Mar 2023 11:34:14 +0200 Subject: [PATCH 52/95] refs #5184 back and front tests added --- .../back/methods/invoice-in/getSerial.js | 35 ++++++++++----- .../invoice-in/specs/getSerial.spec.js | 21 +++++++++ modules/invoiceIn/front/locale/es.yml | 1 + .../front/serial-search-panel/index.html | 18 ++++---- .../front/serial-search-panel/index.js | 17 +++++--- .../front/serial-search-panel/index.spec.js | 43 +++++++++++++++++++ modules/invoiceIn/front/serial/index.html | 6 +-- modules/invoiceIn/front/serial/index.js | 22 ++-------- 8 files changed, 115 insertions(+), 48 deletions(-) create mode 100644 modules/invoiceIn/back/methods/invoice-in/specs/getSerial.spec.js create mode 100644 modules/invoiceIn/front/serial-search-panel/index.spec.js diff --git a/modules/invoiceIn/back/methods/invoice-in/getSerial.js b/modules/invoiceIn/back/methods/invoice-in/getSerial.js index 8635a0be7..a6c5ad00e 100644 --- a/modules/invoiceIn/back/methods/invoice-in/getSerial.js +++ b/modules/invoiceIn/back/methods/invoice-in/getSerial.js @@ -1,12 +1,17 @@ +const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; + module.exports = Self => { Self.remoteMethod('getSerial', { description: 'Return invoiceIn serial', accessType: 'READ', - accepts: { - arg: 'issued', - type: 'date', + accepts: [{ + arg: 'daysAgo', + type: 'number', required: true - }, + }, { + arg: 'serial', + type: 'string' + }], returns: { type: 'object', root: true @@ -17,17 +22,25 @@ module.exports = Self => { } }); - Self.getSerial = async(issued, options) => { - const myOptions = {}; + Self.getSerial = async(daysAgo, serial) => { + const conn = Self.dataSource.connector; + const stmt = []; - if (typeof options == 'object') - Object.assign(myOptions, options); + const issued = Date.vnNew(); + issued.setDate(issued.getDate() - daysAgo); - const result = await Self.rawSql(` + stmt.push(new ParameterizedSQL(` SELECT i.serial, SUM(IF(i.isBooked, 0,1)) pending, COUNT(*) total FROM vn.invoiceIn i - WHERE i.issued >= ? - GROUP BY i.serial`, [issued]); + WHERE i.issued >= ? `, [issued])); + + if (serial) + stmt.push(new ParameterizedSQL(`AND i.serial LIKE ? `, [serial])); + + stmt.push(`GROUP BY i.serial`); + + const sql = ParameterizedSQL.join(stmt); + const result = await conn.executeStmt(sql); return result; }; diff --git a/modules/invoiceIn/back/methods/invoice-in/specs/getSerial.spec.js b/modules/invoiceIn/back/methods/invoice-in/specs/getSerial.spec.js new file mode 100644 index 000000000..d07fef196 --- /dev/null +++ b/modules/invoiceIn/back/methods/invoice-in/specs/getSerial.spec.js @@ -0,0 +1,21 @@ +const models = require('vn-loopback/server/server').models; + +describe('invoiceIn getSerial()', () => { + it('should check that returns without serial param', async() => { + const result = await models.InvoiceIn.getSerial(45); + + expect(result.length).toBeGreaterThan(0); + }); + + it('should check that returns with serial param', async() => { + const result = await models.InvoiceIn.getSerial(45, 'R'); + + expect(result.length).toBeGreaterThan(0); + }); + + it('should check that returns with non exist serial param', async() => { + const result = await models.InvoiceIn.getSerial(45, 'Mock serial'); + + expect(result.length).toEqual(0); + }); +}); diff --git a/modules/invoiceIn/front/locale/es.yml b/modules/invoiceIn/front/locale/es.yml index f2f77b690..a2d658519 100644 --- a/modules/invoiceIn/front/locale/es.yml +++ b/modules/invoiceIn/front/locale/es.yml @@ -23,3 +23,4 @@ Total stems: Total tallos Show agricultural receipt as PDF: Ver recibo agrícola como PDF Send agricultural receipt as PDF: Enviar recibo agrícola como PDF New InvoiceIn: Nueva Factura +Days ago: Últimos días diff --git a/modules/invoiceIn/front/serial-search-panel/index.html b/modules/invoiceIn/front/serial-search-panel/index.html index 467f7439c..c412e783c 100644 --- a/modules/invoiceIn/front/serial-search-panel/index.html +++ b/modules/invoiceIn/front/serial-search-panel/index.html @@ -1,26 +1,28 @@ - - + ng-keydown="$ctrl.onKeyPress($event)" + required="true" + min="0"> +
- Id/Name: {{$ctrl.filter.search}} + {{$ctrl.$t('Serial')}}: {{$ctrl.filter.serial}}
diff --git a/modules/invoiceIn/front/serial-search-panel/index.js b/modules/invoiceIn/front/serial-search-panel/index.js index 334e4cf01..b11911ee3 100644 --- a/modules/invoiceIn/front/serial-search-panel/index.js +++ b/modules/invoiceIn/front/serial-search-panel/index.js @@ -5,16 +5,16 @@ import './style.scss'; class Controller extends SearchPanel { constructor($element, $) { super($element, $); + this.filter = {}; const filter = { fields: ['daysAgo'] }; - this.$http.get('InvoiceInConfigs', {filter}); - } - - $onInit() { - this.filter = { - tags: [] - }; + this.$http.get('InvoiceInConfigs', {filter}).then(res => { + if (res.data) { + this.invoiceInConfig = res.data[0]; + this.addFilters(); + } + }); } removeItemFilter(param) { @@ -28,6 +28,9 @@ class Controller extends SearchPanel { } addFilters() { + if (!this.filter.daysAgo) + this.filter.daysAgo = this.invoiceInConfig.daysAgo; + return this.model.addFilter({}, this.filter); } } diff --git a/modules/invoiceIn/front/serial-search-panel/index.spec.js b/modules/invoiceIn/front/serial-search-panel/index.spec.js new file mode 100644 index 000000000..b5228e126 --- /dev/null +++ b/modules/invoiceIn/front/serial-search-panel/index.spec.js @@ -0,0 +1,43 @@ +import './index.js'; + +describe('InvoiceIn', () => { + describe('Component serial-search-panel', () => { + let controller; + let $scope; + + beforeEach(ngModule('invoiceIn')); + + beforeEach(inject(($componentController, $rootScope) => { + $scope = $rootScope.$new(); + const $element = angular.element(''); + controller = $componentController('vnInvoiceInSerialSearchPanel', {$element, $scope}); + controller.model = { + addFilter: jest.fn(), + }; + controller.invoiceInConfig = { + daysAgo: 45, + }; + })); + + describe('addFilters()', () => { + it('should add default daysAgo if it is not already set', () => { + controller.filter = { + serial: 'R', + }; + controller.addFilters(); + + expect(controller.filter.daysAgo).toEqual(controller.invoiceInConfig.daysAgo); + }); + + it('should not add default daysAgo if it is already set', () => { + controller.filter = { + daysAgo: 1, + serial: 'R', + }; + controller.addFilters(); + + expect(controller.filter.daysAgo).toEqual(1); + }); + }); + }); +}); diff --git a/modules/invoiceIn/front/serial/index.html b/modules/invoiceIn/front/serial/index.html index f8ca4bbbb..e381e7293 100644 --- a/modules/invoiceIn/front/serial/index.html +++ b/modules/invoiceIn/front/serial/index.html @@ -1,9 +1,7 @@ + limit="20"> @@ -30,7 +28,7 @@ {{::invoiceIn.total}} diff --git a/modules/invoiceIn/front/serial/index.js b/modules/invoiceIn/front/serial/index.js index 622087748..9d27e4e8f 100644 --- a/modules/invoiceIn/front/serial/index.js +++ b/modules/invoiceIn/front/serial/index.js @@ -6,24 +6,10 @@ export default class Controller extends Section { super($element, $); } - exprBuilder(param, value) { - switch (param) { - case 'issued': - return {'ii.issued': { - between: this.dateRange(value)} - }; - case 'serial': - return {[`ii.${param}`]: value}; - } - } - - dateRange(value) { - const minHour = new Date(value); - minHour.setHours(0, 0, 0, 0); - const maxHour = new Date(value); - maxHour.setHours(23, 59, 59, 59); - - return [minHour, maxHour]; + goToIndex(daysAgo) { + const issued = Date.vnNew(); + issued.setDate(issued.getDate() - daysAgo); + this.$state.go('invoiceIn.index', {q: `{"isBooked": true, "from": ${issued.getTime()}}`}); } } From 69be91b96442f6d6bae52d8405c8bda60923b3c1 Mon Sep 17 00:00:00 2001 From: alexandre Date: Tue, 28 Mar 2023 13:45:26 +0200 Subject: [PATCH 53/95] refs #5184 fix back test, added e2e --- e2e/helpers/selectors.js | 9 ++++ e2e/paths/09-invoice-in/05_serial.spec.js | 48 +++++++++++++++++ .../back/methods/invoice-in/getSerial.js | 52 +++++++++++++------ .../invoice-in/specs/getSerial.spec.js | 9 ++-- .../front/serial-search-panel/index.html | 1 - modules/invoiceIn/front/serial/index.html | 2 +- modules/invoiceIn/front/serial/index.js | 5 +- 7 files changed, 104 insertions(+), 22 deletions(-) create mode 100644 e2e/paths/09-invoice-in/05_serial.spec.js diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index f4c67f002..97693e71e 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -1127,6 +1127,15 @@ export default { saveButton: 'vn-invoice-in-tax vn-submit', }, + invoiceInIndex: { + topbarSearchParams: 'vn-searchbar div.search-params > span', + }, + invoiceInSerial: { + daysAgo: 'vn-invoice-in-serial-search-panel vn-input-number[ng-model="$ctrl.filter.daysAgo"]', + serial: 'vn-invoice-in-serial-search-panel vn-textfield[ng-model="$ctrl.filter.serial"]', + chip: 'vn-chip > vn-icon', + goToIndex: 'vn-invoice-in-serial vn-icon-button[icon="icon-invoice-in"]', + }, travelIndex: { anySearchResult: 'vn-travel-index vn-tbody > a', firstSearchResult: 'vn-travel-index vn-tbody > a:nth-child(1)', diff --git a/e2e/paths/09-invoice-in/05_serial.spec.js b/e2e/paths/09-invoice-in/05_serial.spec.js new file mode 100644 index 000000000..3aa94f48c --- /dev/null +++ b/e2e/paths/09-invoice-in/05_serial.spec.js @@ -0,0 +1,48 @@ +import selectors from '../../helpers/selectors.js'; +import getBrowser from '../../helpers/puppeteer'; + +describe('InvoiceIn serial path', () => { + let browser; + let page; + let httpRequest; + + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('administrative', 'invoiceIn'); + await page.accessToSection('invoiceIn.serial'); + page.on('request', req => { + if (req.url().includes(`InvoiceIns/getSerial`)) + httpRequest = req.url(); + }); + }); + + afterAll(async() => { + await browser.close(); + }); + + it('should check that passes the correct params to back', async() => { + await page.overwrite(selectors.invoiceInSerial.daysAgo, '30'); + await page.keyboard.press('Enter'); + + expect(httpRequest).toContain('daysAgo=30'); + + await page.overwrite(selectors.invoiceInSerial.serial, 'R'); + await page.keyboard.press('Enter'); + + expect(httpRequest).toContain('serial=R'); + await page.click(selectors.invoiceInSerial.chip); + }); + + it('should go to index and check if the search-panel has the correct params', async() => { + await page.click(selectors.invoiceInSerial.goToIndex); + const params = await page.$$(selectors.invoiceInIndex.topbarSearchParams); + const serial = await params[0].getProperty('title'); + const isBooked = await params[1].getProperty('title'); + const from = await params[2].getProperty('title'); + + expect(await serial.jsonValue()).toContain('serial'); + expect(await isBooked.jsonValue()).toContain('not isBooked'); + expect(await from.jsonValue()).toContain('from'); + }); +}); diff --git a/modules/invoiceIn/back/methods/invoice-in/getSerial.js b/modules/invoiceIn/back/methods/invoice-in/getSerial.js index a6c5ad00e..ebafd6fc4 100644 --- a/modules/invoiceIn/back/methods/invoice-in/getSerial.js +++ b/modules/invoiceIn/back/methods/invoice-in/getSerial.js @@ -1,10 +1,15 @@ const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; +const buildFilter = require('vn-loopback/util/filter').buildFilter; +const mergeFilters = require('vn-loopback/util/filter').mergeFilters; module.exports = Self => { - Self.remoteMethod('getSerial', { + Self.remoteMethodCtx('getSerial', { description: 'Return invoiceIn serial', accessType: 'READ', accepts: [{ + arg: 'filter', + type: 'object' + }, { arg: 'daysAgo', type: 'number', required: true @@ -22,26 +27,43 @@ module.exports = Self => { } }); - Self.getSerial = async(daysAgo, serial) => { + Self.getSerial = async(ctx, options) => { const conn = Self.dataSource.connector; - const stmt = []; + const args = ctx.args; + const myOptions = {}; + if (typeof options == 'object') + Object.assign(myOptions, options); + + const where = buildFilter(args, (param, value) => { + switch (param) { + case 'serial': + return {'f.serial': {like: `%${value}%`}}; + } + }); + + filter = mergeFilters(args.filter, {where}); const issued = Date.vnNew(); - issued.setDate(issued.getDate() - daysAgo); + issued.setDate(issued.getDate() - args.daysAgo); - stmt.push(new ParameterizedSQL(` - SELECT i.serial, SUM(IF(i.isBooked, 0,1)) pending, COUNT(*) total - FROM vn.invoiceIn i - WHERE i.issued >= ? `, [issued])); + const stmts = []; + const stmt = new ParameterizedSQL( + `SELECT * + FROM ( + SELECT i.serial, SUM(IF(i.isBooked, 0,1)) pending, COUNT(*) total + FROM vn.invoiceIn i + WHERE i.issued >= ? + GROUP BY i.serial) f` + , [issued]); - if (serial) - stmt.push(new ParameterizedSQL(`AND i.serial LIKE ? `, [serial])); + stmt.merge(conn.makeWhere(filter.where)); + stmt.merge(conn.makeOrderBy(filter.order)); + stmt.merge(conn.makeLimit(filter)); - stmt.push(`GROUP BY i.serial`); + const invoiceInIndex = stmts.push(stmt) - 1; + const sql = ParameterizedSQL.join(stmts, ';'); + const result = await conn.executeStmt(sql, myOptions); - const sql = ParameterizedSQL.join(stmt); - const result = await conn.executeStmt(sql); - - return result; + return invoiceInIndex === 0 ? result : result[invoiceInIndex]; }; }; diff --git a/modules/invoiceIn/back/methods/invoice-in/specs/getSerial.spec.js b/modules/invoiceIn/back/methods/invoice-in/specs/getSerial.spec.js index d07fef196..6224ce9ac 100644 --- a/modules/invoiceIn/back/methods/invoice-in/specs/getSerial.spec.js +++ b/modules/invoiceIn/back/methods/invoice-in/specs/getSerial.spec.js @@ -2,19 +2,22 @@ const models = require('vn-loopback/server/server').models; describe('invoiceIn getSerial()', () => { it('should check that returns without serial param', async() => { - const result = await models.InvoiceIn.getSerial(45); + const ctx = {args: {daysAgo: 45}}; + const result = await models.InvoiceIn.getSerial(ctx); expect(result.length).toBeGreaterThan(0); }); it('should check that returns with serial param', async() => { - const result = await models.InvoiceIn.getSerial(45, 'R'); + const ctx = {args: {daysAgo: 45, serial: 'R'}}; + const result = await models.InvoiceIn.getSerial(ctx); expect(result.length).toBeGreaterThan(0); }); it('should check that returns with non exist serial param', async() => { - const result = await models.InvoiceIn.getSerial(45, 'Mock serial'); + const ctx = {args: {daysAgo: 45, serial: 'Mock serial'}}; + const result = await models.InvoiceIn.getSerial(ctx); expect(result.length).toEqual(0); }); diff --git a/modules/invoiceIn/front/serial-search-panel/index.html b/modules/invoiceIn/front/serial-search-panel/index.html index c412e783c..0dda54852 100644 --- a/modules/invoiceIn/front/serial-search-panel/index.html +++ b/modules/invoiceIn/front/serial-search-panel/index.html @@ -5,7 +5,6 @@ ng-model="$ctrl.filter.daysAgo" vn-focus ng-keydown="$ctrl.onKeyPress($event)" - required="true" min="0">
diff --git a/modules/invoiceIn/front/serial/index.html b/modules/invoiceIn/front/serial/index.html index e381e7293..1649ec7d7 100644 --- a/modules/invoiceIn/front/serial/index.html +++ b/modules/invoiceIn/front/serial/index.html @@ -28,7 +28,7 @@ {{::invoiceIn.total}} diff --git a/modules/invoiceIn/front/serial/index.js b/modules/invoiceIn/front/serial/index.js index 9d27e4e8f..193a57492 100644 --- a/modules/invoiceIn/front/serial/index.js +++ b/modules/invoiceIn/front/serial/index.js @@ -6,10 +6,11 @@ export default class Controller extends Section { super($element, $); } - goToIndex(daysAgo) { + goToIndex(daysAgo, serial) { const issued = Date.vnNew(); issued.setDate(issued.getDate() - daysAgo); - this.$state.go('invoiceIn.index', {q: `{"isBooked": true, "from": ${issued.getTime()}}`}); + this.$state.go('invoiceIn.index', + {q: `{"serial": "${serial}", "isBooked": false, "from": ${issued.getTime()}}`}); } } From b4e04fcdad29c33815329b4c7492bb69cc8eff17 Mon Sep 17 00:00:00 2001 From: vicent Date: Tue, 28 Mar 2023 14:40:14 +0200 Subject: [PATCH 54/95] refs #5275 feat: colorear fechas --- modules/item/front/fixed-price/index.html | 24 +++++++----- modules/item/front/fixed-price/index.js | 22 +++++++++++ modules/item/front/fixed-price/style.scss | 46 +++++++++++++++-------- 3 files changed, 66 insertions(+), 26 deletions(-) diff --git a/modules/item/front/fixed-price/index.html b/modules/item/front/fixed-price/index.html index 584c4b14e..0bc53aa3f 100644 --- a/modules/item/front/fixed-price/index.html +++ b/modules/item/front/fixed-price/index.html @@ -152,18 +152,22 @@ - - + + + + - - + + + + 0) return 'warning'; + } + add() { if (!this.$.model.data || this.$.model.data.length == 0) { this.$.model.data = []; diff --git a/modules/item/front/fixed-price/style.scss b/modules/item/front/fixed-price/style.scss index ba3878dba..d1f968c37 100644 --- a/modules/item/front/fixed-price/style.scss +++ b/modules/item/front/fixed-price/style.scss @@ -1,20 +1,34 @@ @import "variables"; -smart-table table{ - [shrink-field]{ - width: 80px; - max-width: 80px; +vn-fixed-price{ + smart-table table{ + [shrink-field]{ + width: 80px; + max-width: 80px; + } + [shrink-field-expand]{ + width: 150px; + max-width: 150px; + } } - [shrink-field-expand]{ - width: 150px; - max-width: 150px; + + .minPrice { + align-items: center; + text-align: center; + vn-input-number { + width: 90px; + max-width: 90px; + } + } + + smart-table table tbody > * > td .chip { + padding: 0px; + } + + smart-table table tbody > * > td .chip.warning { + color: $color-font-bg + } + + .vn-field > .container > .infix > .control > input { + color: inherit; } } - -.minPrice { - align-items: center; - text-align: center; - vn-input-number { - width: 90px; - max-width: 90px; - } -} \ No newline at end of file From bf5f1011e85dd0f553089ed2c8c1616d6416bfb0 Mon Sep 17 00:00:00 2001 From: carlossa Date: Tue, 28 Mar 2023 14:56:20 +0200 Subject: [PATCH 55/95] =?UTF-8?q?refs=20#5490=20traducci=C3=B3n=20corregid?= =?UTF-8?q?a?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/ticket/front/expedition/locale/es.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ticket/front/expedition/locale/es.yml b/modules/ticket/front/expedition/locale/es.yml index 278dcc8f2..1933bac20 100644 --- a/modules/ticket/front/expedition/locale/es.yml +++ b/modules/ticket/front/expedition/locale/es.yml @@ -1,4 +1,4 @@ -Status log: Hitorial de estados +Status log: Historial de estados Expedition removed: Expedición eliminada Move: Mover New ticket without route: Nuevo ticket sin ruta From c53c54b6cd1f18b8c9c0f16e7c72272f4274b8ed Mon Sep 17 00:00:00 2001 From: vicent Date: Tue, 28 Mar 2023 14:59:08 +0200 Subject: [PATCH 56/95] refs #5275 feat: modificar masivamente --- modules/item/front/fixed-price/index.html | 113 ++++++++++++++++--- modules/item/front/fixed-price/index.js | 99 +++++++++++++++- modules/item/front/fixed-price/locale/es.yml | 2 + modules/item/front/fixed-price/style.scss | 12 ++ 4 files changed, 209 insertions(+), 17 deletions(-) diff --git a/modules/item/front/fixed-price/index.html b/modules/item/front/fixed-price/index.html index 0bc53aa3f..af41b1bc8 100644 --- a/modules/item/front/fixed-price/index.html +++ b/modules/item/front/fixed-price/index.html @@ -31,15 +31,21 @@ + - + + - +
+ + + Item ID Description - Warehouse - Grouping price @@ -57,11 +63,21 @@ Ended + Warehouse +
+ + + - - - - {{price.rate2 | currency: 'EUR':2}} + + {{price.rate2 | currency: 'EUR':2}} + - {{price.rate3 | currency: 'EUR':2}} + + {{price.rate3 | currency: 'EUR':2}} + @@ -169,6 +180,15 @@ + + + + +
+ + + + +
+ + + Edit + + {{::$ctrl.totalChecked}} + + buy(s) + + + + + + + + + + + + + + + + + + + diff --git a/modules/item/front/fixed-price/index.js b/modules/item/front/fixed-price/index.js index 0decf7275..eacd54ff6 100644 --- a/modules/item/front/fixed-price/index.js +++ b/modules/item/front/fixed-price/index.js @@ -5,6 +5,9 @@ import './style.scss'; export default class Controller extends Section { constructor($element, $) { super($element, $); + this.editedColumn; + this.checkAll = false; + this.checkedFixedPrices = []; this.smartTableOptions = { activeButtons: { @@ -30,6 +33,98 @@ export default class Controller extends Section { } ] }; + + this.filterParams = { + warehouseFk: this.vnConfig.warehouseFk + }; + } + + getFilterParams() { + return { + warehouseFk: this.vnConfig.warehouseFk + }; + } + + get columns() { + if (this._columns) return this._columns; + + this._columns = [ + {field: 'rate2', displayName: this.$t('Grouping price')}, + {field: 'rate3', displayName: this.$t('Packing price')}, + {field: 'hasMinPrice', displayName: this.$t('Has min price')}, + {field: 'minPrice', displayName: this.$t('Min price')}, + {field: 'started', displayName: this.$t('Started')}, + {field: 'ended', displayName: this.$t('Ended')}, + {field: 'warehouseFk', displayName: this.$t('Warehouse')} + ]; + + return this._columns; + } + + get checked() { + const fixedPrices = this.$.model.data || []; + const checkedBuys = []; + for (let fixedPrice of fixedPrices) { + if (fixedPrice.checked) + checkedBuys.push(fixedPrice); + } + + return checkedBuys; + } + + uncheck() { + this.checkAll = false; + this.checkedFixedPrices = []; + } + + get totalChecked() { + if (this.checkedDummyCount) + return this.checkedDummyCount; + + return this.checked.length; + } + + saveChecked(fixedPriceId) { + const index = this.checkedFixedPrices.indexOf(fixedPriceId); + if (index !== -1) + return this.checkedFixedPrices.splice(index, 1); + return this.checkedFixedPrices.push(fixedPriceId); + } + + reCheck() { + if (!this.$.model.data) return; + if (!this.checkedFixedPrices.length) return; + + this.$.model.data.forEach(fixedPrice => { + if (this.checkedFixedPrices.includes(fixedPrice.id)) + fixedPrice.checked = true; + }); + } + + onEditAccept() { + for (const fixedPrice of this.checked) { + fixedPrice[this.editedColumn.field] = this.editedColumn.newValue; + console.log(fixedPrice); + + this.upsertPrice(fixedPrice, false); + } + + // if (this.checkedDummyCount && this.checkedDummyCount > 0) { + // const params = {}; + // if (this.$.model.userParams) { + // const userParams = this.$.model.userParams; + // for (let param in userParams) { + // let newParam = this.exprBuilder(param, userParams[param]); + // if (!newParam) + // newParam = {[param]: userParams[param]}; + // Object.assign(params, newParam); + // } + // } + // if (this.$.model.userFilter) + // Object.assign(params, this.$.model.userFilter.where); + + // data.filter = params; + // } } isBigger(date) { @@ -98,8 +193,8 @@ export default class Controller extends Section { if (resetMinPrice) delete price['minPrice']; - let requiredFields = ['itemFk', 'started', 'ended', 'rate2', 'rate3']; - for (let field of requiredFields) + const requiredFields = ['itemFk', 'started', 'ended', 'rate2', 'rate3']; + for (const field of requiredFields) if (price[field] == undefined) return; const query = 'FixedPrices/upsertFixedPrice'; diff --git a/modules/item/front/fixed-price/locale/es.yml b/modules/item/front/fixed-price/locale/es.yml index 6bdfcb678..6dacf96c9 100644 --- a/modules/item/front/fixed-price/locale/es.yml +++ b/modules/item/front/fixed-price/locale/es.yml @@ -3,3 +3,5 @@ Search prices by item ID or code: Buscar por ID de artículo o código Search fixed prices: Buscar precios fijados Add fixed price: Añadir precio fijado This row will be removed: Esta linea se eliminará +Edit fixed price(s): Editar precio(s) fijado(s) +Has min price: Tiene precio mínimo diff --git a/modules/item/front/fixed-price/style.scss b/modules/item/front/fixed-price/style.scss index d1f968c37..97ceaf7cd 100644 --- a/modules/item/front/fixed-price/style.scss +++ b/modules/item/front/fixed-price/style.scss @@ -24,6 +24,12 @@ vn-fixed-price{ padding: 0px; } + smart-table table tbody > * > td{ + padding: 0px; + padding-left: 5px; + padding-right: 5px; + } + smart-table table tbody > * > td .chip.warning { color: $color-font-bg } @@ -31,4 +37,10 @@ vn-fixed-price{ .vn-field > .container > .infix > .control > input { color: inherit; } + + vn-input-number.inactive{ + input { + color: $color-font-light !important; + } + } } From 3ad85c0de3cc06ec1ccb570c403848bc1a3db504 Mon Sep 17 00:00:00 2001 From: alexandre Date: Wed, 29 Mar 2023 08:44:35 +0200 Subject: [PATCH 57/95] refs #5184 subselect deleted --- .../back/methods/invoice-in/getSerial.js | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/modules/invoiceIn/back/methods/invoice-in/getSerial.js b/modules/invoiceIn/back/methods/invoice-in/getSerial.js index ebafd6fc4..3ef37d401 100644 --- a/modules/invoiceIn/back/methods/invoice-in/getSerial.js +++ b/modules/invoiceIn/back/methods/invoice-in/getSerial.js @@ -35,28 +35,27 @@ module.exports = Self => { if (typeof options == 'object') Object.assign(myOptions, options); + const issued = Date.vnNew(); const where = buildFilter(args, (param, value) => { switch (param) { + case 'daysAgo': + issued.setDate(issued.getDate() - value); + return {'i.issued': {gte: issued}}; case 'serial': - return {'f.serial': {like: `%${value}%`}}; + return {'i.serial': {like: `%${value}%`}}; } }); filter = mergeFilters(args.filter, {where}); - const issued = Date.vnNew(); - issued.setDate(issued.getDate() - args.daysAgo); const stmts = []; const stmt = new ParameterizedSQL( - `SELECT * - FROM ( - SELECT i.serial, SUM(IF(i.isBooked, 0,1)) pending, COUNT(*) total - FROM vn.invoiceIn i - WHERE i.issued >= ? - GROUP BY i.serial) f` - , [issued]); + `SELECT i.serial, SUM(IF(i.isBooked, 0,1)) pending, COUNT(*) total + FROM vn.invoiceIn i` + ); stmt.merge(conn.makeWhere(filter.where)); + stmt.merge(`GROUP BY i.serial`); stmt.merge(conn.makeOrderBy(filter.order)); stmt.merge(conn.makeLimit(filter)); From 9a713d2753d80451da3637d6f1a78346bfc31e90 Mon Sep 17 00:00:00 2001 From: alexandre Date: Wed, 29 Mar 2023 08:48:54 +0200 Subject: [PATCH 58/95] refs #5184 stmts removed --- modules/invoiceIn/back/methods/invoice-in/getSerial.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/modules/invoiceIn/back/methods/invoice-in/getSerial.js b/modules/invoiceIn/back/methods/invoice-in/getSerial.js index 3ef37d401..dcc1fbc3c 100644 --- a/modules/invoiceIn/back/methods/invoice-in/getSerial.js +++ b/modules/invoiceIn/back/methods/invoice-in/getSerial.js @@ -48,7 +48,6 @@ module.exports = Self => { filter = mergeFilters(args.filter, {where}); - const stmts = []; const stmt = new ParameterizedSQL( `SELECT i.serial, SUM(IF(i.isBooked, 0,1)) pending, COUNT(*) total FROM vn.invoiceIn i` @@ -59,10 +58,8 @@ module.exports = Self => { stmt.merge(conn.makeOrderBy(filter.order)); stmt.merge(conn.makeLimit(filter)); - const invoiceInIndex = stmts.push(stmt) - 1; - const sql = ParameterizedSQL.join(stmts, ';'); - const result = await conn.executeStmt(sql, myOptions); + const result = await conn.executeStmt(stmt, myOptions); - return invoiceInIndex === 0 ? result : result[invoiceInIndex]; + return result; }; }; From 3b615d98796b7e95445f77bf3b72233012df6d82 Mon Sep 17 00:00:00 2001 From: vicent Date: Wed, 29 Mar 2023 09:11:40 +0200 Subject: [PATCH 59/95] refs #5275 fix: actualiza correctamete los elementos del checkedDummy --- .../methods/fixed-price/editFixedPrice.js | 96 +++++++++++++++++++ .../item/back/methods/fixed-price/filter.js | 3 +- modules/item/back/models/fixed-price.js | 1 + modules/item/front/fixed-price/index.js | 49 ++++++---- 4 files changed, 127 insertions(+), 22 deletions(-) create mode 100644 modules/item/back/methods/fixed-price/editFixedPrice.js diff --git a/modules/item/back/methods/fixed-price/editFixedPrice.js b/modules/item/back/methods/fixed-price/editFixedPrice.js new file mode 100644 index 000000000..13e0fc41b --- /dev/null +++ b/modules/item/back/methods/fixed-price/editFixedPrice.js @@ -0,0 +1,96 @@ +module.exports = Self => { + Self.remoteMethodCtx('editFixedPrice', { + description: 'Updates a column for one or more fixed price', + accessType: 'WRITE', + accepts: [{ + arg: 'field', + type: 'string', + required: true, + description: `the column to edit` + }, + { + arg: 'newValue', + type: 'any', + required: true, + description: `The new value to save` + }, + { + arg: 'lines', + type: ['object'], + required: true, + description: `the buys which will be modified` + }, + { + arg: 'filter', + type: 'object', + description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string' + }], + returns: { + type: 'object', + root: true + }, + http: { + path: `/editFixedPrice`, + verb: 'POST' + } + }); + + Self.editFixedPrice = async(ctx, field, newValue, lines, filter, options) => { + let tx; + const myOptions = {}; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + if (!myOptions.transaction) { + tx = await Self.beginTransaction({}); + myOptions.transaction = tx; + } + + let modelName; + let identifier; + + switch (field) { + case 'hasMinPrice': + case 'minPrice': + modelName = 'Item'; + identifier = 'itemFk'; + break; + case 'rate2': + case 'rate3': + case 'started': + case 'ended': + case 'warehouseFk': + modelName = 'FixedPrice'; + identifier = 'id'; + } + + const models = Self.app.models; + const model = models[modelName]; + try { + const promises = []; + const value = {}; + value[field] = newValue; + + if (filter) { + filter = {where: filter}; + lines = await models.FixedPrice.filter(ctx, filter, myOptions); + } + + const targets = lines.map(line => { + return line[identifier]; + }); + for (let target of targets) + promises.push(model.upsertWithWhere({id: target}, value, myOptions)); + + const result = await Promise.all(promises); + + if (tx) await tx.commit(); + + return result; + } catch (e) { + if (tx) await tx.rollback(); + throw e; + } + }; +}; diff --git a/modules/item/back/methods/fixed-price/filter.js b/modules/item/back/methods/fixed-price/filter.js index c15ae67f0..9c91886c1 100644 --- a/modules/item/back/methods/fixed-price/filter.js +++ b/modules/item/back/methods/fixed-price/filter.js @@ -184,8 +184,7 @@ module.exports = Self => { } } - stmt.merge(conn.makeWhere(filter.where)); - stmt.merge(conn.makePagination(filter)); + stmt.merge(conn.makeSuffix(filter)); const fixedPriceIndex = stmts.push(stmt) - 1; const sql = ParameterizedSQL.join(stmts, ';'); diff --git a/modules/item/back/models/fixed-price.js b/modules/item/back/models/fixed-price.js index 91010805f..45f8d79ef 100644 --- a/modules/item/back/models/fixed-price.js +++ b/modules/item/back/models/fixed-price.js @@ -2,4 +2,5 @@ module.exports = Self => { require('../methods/fixed-price/filter')(Self); require('../methods/fixed-price/upsertFixedPrice')(Self); require('../methods/fixed-price/getRate2')(Self); + require('../methods/fixed-price/editFixedPrice')(Self); }; diff --git a/modules/item/front/fixed-price/index.js b/modules/item/front/fixed-price/index.js index eacd54ff6..a39cd6602 100644 --- a/modules/item/front/fixed-price/index.js +++ b/modules/item/front/fixed-price/index.js @@ -102,29 +102,38 @@ export default class Controller extends Section { } onEditAccept() { - for (const fixedPrice of this.checked) { - fixedPrice[this.editedColumn.field] = this.editedColumn.newValue; - console.log(fixedPrice); + const rowsToEdit = []; + for (let row of this.checked) + rowsToEdit.push({id: row.id, itemFk: row.itemFk}); - this.upsertPrice(fixedPrice, false); + const data = { + field: this.editedColumn.field, + newValue: this.editedColumn.newValue, + lines: rowsToEdit + }; + + if (this.checkedDummyCount && this.checkedDummyCount > 0) { + const params = {}; + if (this.$.model.userParams) { + const userParams = this.$.model.userParams; + for (let param in userParams) { + let newParam = this.exprBuilder(param, userParams[param]); + if (!newParam) + newParam = {[param]: userParams[param]}; + Object.assign(params, newParam); + } + } + if (this.$.model.userFilter) + Object.assign(params, this.$.model.userFilter.where); + + data.filter = params; } - // if (this.checkedDummyCount && this.checkedDummyCount > 0) { - // const params = {}; - // if (this.$.model.userParams) { - // const userParams = this.$.model.userParams; - // for (let param in userParams) { - // let newParam = this.exprBuilder(param, userParams[param]); - // if (!newParam) - // newParam = {[param]: userParams[param]}; - // Object.assign(params, newParam); - // } - // } - // if (this.$.model.userFilter) - // Object.assign(params, this.$.model.userFilter.where); - - // data.filter = params; - // } + return this.$http.post('FixedPrices/editFixedPrice', data) + .then(() => { + this.uncheck(); + this.$.model.refresh(); + }); } isBigger(date) { From d066c4ea0be719ff48948c5b3349b9f104862108 Mon Sep 17 00:00:00 2001 From: vicent Date: Wed, 29 Mar 2023 11:27:48 +0200 Subject: [PATCH 60/95] refs #4856 feat: se envia el registro a todos los teletrabajadores. Tmb se pone estado 'SENDED' cuando se da a 'Reenviar' --- .../back/methods/worker-time-control/sendMail.js | 14 ++------------ modules/worker/front/time-control/index.js | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/modules/worker/back/methods/worker-time-control/sendMail.js b/modules/worker/back/methods/worker-time-control/sendMail.js index 579a83112..7aff9e790 100644 --- a/modules/worker/back/methods/worker-time-control/sendMail.js +++ b/modules/worker/back/methods/worker-time-control/sendMail.js @@ -131,20 +131,10 @@ module.exports = Self => { JOIN business b ON b.id = tb.businessFk LEFT JOIN tmp.timeControlCalculate tc ON tc.userFk = tb.userFk AND tc.dated = tb.dated LEFT JOIN worker w ON w.id = u.id - JOIN (SELECT tb.userFk, - SUM(IF(tb.type IS NULL, - IF(tc.timeWorkDecimal > 0, FALSE, IF(tb.timeWorkDecimal > 0, TRUE, FALSE)), - TRUE))isTeleworkingWeek - FROM tmp.timeBusinessCalculate tb - LEFT JOIN tmp.timeControlCalculate tc ON tc.userFk = tb.userFk - AND tc.dated = tb.dated - GROUP BY tb.userFk - HAVING isTeleworkingWeek > 0 - )sub ON sub.userFk = u.id - WHERE d.hasToRefill - AND IFNULL(?, u.id) = u.id + WHERE IFNULL(?, u.id) = u.id AND b.companyCodeFk = 'VNL' AND w.businessFk + AND d.isTeleworking ORDER BY u.id, tb.dated `, [args.workerId]); const index = stmts.push(stmt) - 1; diff --git a/modules/worker/front/time-control/index.js b/modules/worker/front/time-control/index.js index 9ed454d31..3e4aeaa5c 100644 --- a/modules/worker/front/time-control/index.js +++ b/modules/worker/front/time-control/index.js @@ -379,6 +379,20 @@ class Controller extends Section { }); } + isSended() { + const params = { + workerId: this.worker.id, + year: this.date.getFullYear(), + week: this.weekNumber, + state: 'SENDED' + }; + const query = `WorkerTimeControls/updateWorkerTimeControlMail`; + this.$http.post(query, params).then(() => { + this.getMailStates(this.date); + this.getWeekData(); + }); + } + changeState(state, reason) { this.state = state; this.reason = reason; @@ -412,6 +426,7 @@ class Controller extends Section { }; this.$http.post(`WorkerTimeControls/weekly-hour-hecord-email`, params) .then(() => { + this.isSended(); this.vnApp.showSuccess(this.$t('Email sended')); }); } From b0d205c4dad353e725b80bb7795d2e8b8927acb7 Mon Sep 17 00:00:00 2001 From: vicent Date: Wed, 29 Mar 2023 13:36:23 +0200 Subject: [PATCH 61/95] refs #5464 fix: utiliza una sola cookie --- back/methods/osticket/closeTicket.js | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/back/methods/osticket/closeTicket.js b/back/methods/osticket/closeTicket.js index 32b369c8d..aa827bbbb 100644 --- a/back/methods/osticket/closeTicket.js +++ b/back/methods/osticket/closeTicket.js @@ -69,15 +69,15 @@ module.exports = Self => { const result = response.headers.get('set-cookie'); const [firtHeader] = result.split(' '); - const firtCookie = firtHeader.substring(0, firtHeader.length - 1); + const cookie = firtHeader.substring(0, firtHeader.length - 1); const body = await response.text(); const dom = new jsdom.JSDOM(body); const token = dom.window.document.querySelector('[name="__CSRFToken__"]').value; - await login(token, firtCookie); + await login(token, cookie); } - async function login(token, firtCookie) { + async function login(token, cookie) { const data = { __CSRFToken__: token, do: 'scplogin', @@ -90,21 +90,18 @@ module.exports = Self => { body: new URLSearchParams(data), headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', - 'Cookie': firtCookie + 'Cookie': cookie } }; - const response = await fetch(ostUri, params); - const result = response.headers.get('set-cookie'); - const [firtHeader] = result.split(' '); - const secondCookie = firtHeader.substring(0, firtHeader.length - 1); + await fetch(ostUri, params); - await close(token, secondCookie); + await close(token, cookie); } - async function close(token, secondCookie) { + async function close(token, cookie) { for (const ticketId of ticketsId) { try { - const lock = await getLockCode(token, secondCookie, ticketId); + const lock = await getLockCode(token, cookie, ticketId); if (!lock.code) { let error = `Can't get lock code`; if (lock.msg) error += `: ${lock.msg}`; @@ -127,7 +124,7 @@ module.exports = Self => { method: 'POST', body: form, headers: { - 'Cookie': secondCookie + 'Cookie': cookie } }; await fetch(ostUri, params); @@ -139,13 +136,13 @@ module.exports = Self => { } } - async function getLockCode(token, secondCookie, ticketId) { + async function getLockCode(token, cookie, ticketId) { const ostUri = `${config.host}/ajax.php/lock/ticket/${ticketId}`; const params = { method: 'POST', headers: { 'X-CSRFToken': token, - 'Cookie': secondCookie + 'Cookie': cookie } }; const response = await fetch(ostUri, params); From d5fd15224ec1e6d0f9c8cd33c1f91f861fba1740 Mon Sep 17 00:00:00 2001 From: joan Date: Wed, 29 Mar 2023 14:57:14 +0200 Subject: [PATCH 62/95] fix(sqlConnector): handled malformed json parse Refs #4862 --- loopback/server/connectors/vn-mysql.js | 119 +++++++++++++++---------- 1 file changed, 73 insertions(+), 46 deletions(-) diff --git a/loopback/server/connectors/vn-mysql.js b/loopback/server/connectors/vn-mysql.js index 5c1ceaa32..728454d86 100644 --- a/loopback/server/connectors/vn-mysql.js +++ b/loopback/server/connectors/vn-mysql.js @@ -1,8 +1,7 @@ const mysql = require('mysql'); -const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; const MySQL = require('loopback-connector-mysql').MySQL; const EnumFactory = require('loopback-connector-mysql').EnumFactory; -const Transaction = require('loopback-connector').Transaction; +const { Transaction, SQLConnector, ParameterizedSQL } = require('loopback-connector'); const fs = require('fs'); const limitSet = new Set([ @@ -254,49 +253,49 @@ class VnMySQL extends MySQL { } create(model, data, opts, cb) { - const ctx = {data}; + const ctx = { data }; this.invokeMethod('create', arguments, model, ctx, opts, cb); } createAll(model, data, opts, cb) { - const ctx = {data}; + const ctx = { data }; this.invokeMethod('createAll', arguments, model, ctx, opts, cb); } save(model, data, opts, cb) { - const ctx = {data}; + const ctx = { data }; this.invokeMethod('save', arguments, model, ctx, opts, cb); } updateOrCreate(model, data, opts, cb) { - const ctx = {data}; + const ctx = { data }; this.invokeMethod('updateOrCreate', arguments, model, ctx, opts, cb); } replaceOrCreate(model, data, opts, cb) { - const ctx = {data}; + const ctx = { data }; this.invokeMethod('replaceOrCreate', arguments, model, ctx, opts, cb); } destroyAll(model, where, opts, cb) { - const ctx = {where}; + const ctx = { where }; this.invokeMethod('destroyAll', arguments, model, ctx, opts, cb); } update(model, where, data, opts, cb) { - const ctx = {where, data}; + const ctx = { where, data }; this.invokeMethod('update', arguments, model, ctx, opts, cb); } replaceById(model, id, data, opts, cb) { - const ctx = {id, data}; + const ctx = { id, data }; this.invokeMethod('replaceById', arguments, model, ctx, opts, cb); } @@ -321,16 +320,16 @@ class VnMySQL extends MySQL { let tx; if (!opts.transaction) { tx = await Transaction.begin(this, {}); - opts = Object.assign({transaction: tx, httpCtx: opts.httpCtx}, opts); + opts = Object.assign({ transaction: tx, httpCtx: opts.httpCtx }, opts); } try { // Fetch old values (update|delete) or login let where, id, data, idName, limit, op, oldInstances, newInstances; const hasGrabUser = settings.log && settings.log.grabUser; - if(hasGrabUser){ + if (hasGrabUser) { const userId = opts.httpCtx && opts.httpCtx.active.accessToken.userId; - const user = await Model.app.models.Account.findById(userId, {fields: ['name']}, opts); + const user = await Model.app.models.Account.findById(userId, { fields: ['name'] }, opts); await this.executeP(`CALL account.myUser_loginWithName(?)`, [user.name], opts); } else { @@ -344,18 +343,18 @@ class VnMySQL extends MySQL { op = opMap.get(method); if (!where) { - if (id) where = {[idName]: id}; - else where = {[idName]: data[idName]}; + if (id) where = { [idName]: id }; + else where = { [idName]: data[idName] }; } // Fetch old values switch (op) { - case 'update': - case 'delete': - // Single entity operation - const stmt = this.buildSelectStmt(op, data, idName, model, where, limit); - stmt.merge(`FOR UPDATE`); - oldInstances = await this.executeStmt(stmt, opts); + case 'update': + case 'delete': + // Single entity operation + const stmt = this.buildSelectStmt(op, data, idName, model, where, limit); + stmt.merge(`FOR UPDATE`); + oldInstances = await this.executeStmt(stmt, opts); } } @@ -365,30 +364,30 @@ class VnMySQL extends MySQL { super[method].apply(this, fnArgs); }); - if(hasGrabUser) + if (hasGrabUser) await this.executeP(`CALL account.myUser_logout()`, null, opts); else { // Fetch new values const ids = []; switch (op) { - case 'insert': - case 'update': { + case 'insert': + case 'update': { switch (method) { - case 'createAll': - for (const row of res[1]) - ids.push(row[idName]); - break; - case 'create': - ids.push(res[1]); - break; - case 'update': - if (data[idName] != null) - ids.push(data[idName]); - break; + case 'createAll': + for (const row of res[1]) + ids.push(row[idName]); + break; + case 'create': + ids.push(res[1]); + break; + case 'update': + if (data[idName] != null) + ids.push(data[idName]); + break; } - const newWhere = ids.length ? {[idName]: ids} : where; + const newWhere = ids.length ? { [idName]: ids } : where; const stmt = this.buildSelectStmt(op, data, idName, model, newWhere, limit); newInstances = await this.executeStmt(stmt, opts); @@ -431,9 +430,9 @@ class VnMySQL extends MySQL { const stmt = new ParameterizedSQL( 'SELECT ' + - this.buildColumnNames(model, {fields}) + - ' FROM ' + - this.tableEscaped(model) + this.buildColumnNames(model, { fields }) + + ' FROM ' + + this.tableEscaped(model) ); stmt.merge(this.buildWhere(model, where)); if (limit) stmt.merge(`LIMIT 1`); @@ -505,8 +504,8 @@ class VnMySQL extends MySQL { if (oldI) { Object.keys(oldI).forEach(prop => { const hasChanges = oldI[prop] instanceof Date ? - oldI[prop]?.getTime() != newI[prop]?.getTime() : - oldI[prop] != newI[prop]; + oldI[prop]?.getTime() != newI[prop]?.getTime() : + oldI[prop] != newI[prop]; if (!hasChanges) { delete oldI[prop]; @@ -537,13 +536,13 @@ exports.initialize = function initialize(dataSource, callback) { modelBuilder.defineValueType.bind(modelBuilder) : modelBuilder.constructor.registerType.bind(modelBuilder.constructor); - defineType(function Point() {}); + defineType(function Point() { }); dataSource.EnumFactory = EnumFactory; if (callback) { if (dataSource.settings.lazyConnect) { - process.nextTick(function() { + process.nextTick(function () { callback(); }); } else @@ -551,13 +550,13 @@ exports.initialize = function initialize(dataSource, callback) { } }; -MySQL.prototype.connect = function(callback) { +MySQL.prototype.connect = function (callback) { const self = this; const options = generateOptions(this.settings); if (this.client) { if (callback) { - process.nextTick(function() { + process.nextTick(function () { callback(null, self.client); }); } @@ -566,7 +565,7 @@ MySQL.prototype.connect = function(callback) { function connectionHandler(options, callback) { const client = mysql.createPool(options); - client.getConnection(function(err, connection) { + client.getConnection(function (err, connection) { const conn = connection; if (!err) { if (self.debug) @@ -645,3 +644,31 @@ function generateOptions(settings) { } return options; } + + +SQLConnector.prototype.all = function find(model, filter, options, cb) { + const self = this; + // Order by id if no order is specified + filter = filter || {}; + const stmt = this.buildSelect(model, filter, options); + this.execute(stmt.sql, stmt.params, options, function (err, data) { + if (err) { + return cb(err, []); + } + + try { + const objs = data.map(function (obj) { + return self.fromRow(model, obj); + }); + if (filter && filter.include) { + self.getModelDefinition(model).model.include( + objs, filter.include, options, cb, + ); + } else { + cb(null, objs); + } + } catch (error) { + cb(error, []) + } + }); +}; \ No newline at end of file From 5a67f473054fbf1ad2bec943b45366fd3e4217bd Mon Sep 17 00:00:00 2001 From: vicent Date: Thu, 30 Mar 2023 08:14:17 +0200 Subject: [PATCH 63/95] refs #4856 fix: actualizar estado a 'SENDED' movido al back --- .../updateWorkerTimeControlMail.js | 6 +++++ .../weeklyHourRecordEmail.js | 24 +++++++++++-------- .../back/models/worker-time-control-mail.json | 3 +++ modules/worker/front/time-control/index.html | 2 +- modules/worker/front/time-control/index.js | 18 +++----------- 5 files changed, 27 insertions(+), 26 deletions(-) diff --git a/modules/worker/back/methods/worker-time-control/updateWorkerTimeControlMail.js b/modules/worker/back/methods/worker-time-control/updateWorkerTimeControlMail.js index 642ff90d2..3c44bda40 100644 --- a/modules/worker/back/methods/worker-time-control/updateWorkerTimeControlMail.js +++ b/modules/worker/back/methods/worker-time-control/updateWorkerTimeControlMail.js @@ -69,6 +69,12 @@ module.exports = Self => { reason: args.reason || null }, myOptions); + if (args.state == 'SENDED') { + await workerTimeControlMail.updateAttributes({ + sendedCounter: workerTimeControlMail.sendedCounter + 1 + }, myOptions); + } + const logRecord = { originFk: args.workerId, userFk: userId, diff --git a/modules/worker/back/methods/worker-time-control/weeklyHourRecordEmail.js b/modules/worker/back/methods/worker-time-control/weeklyHourRecordEmail.js index 6feadb936..8e9b325a6 100644 --- a/modules/worker/back/methods/worker-time-control/weeklyHourRecordEmail.js +++ b/modules/worker/back/methods/worker-time-control/weeklyHourRecordEmail.js @@ -25,6 +25,16 @@ module.exports = Self => { arg: 'url', type: 'string', required: true + }, + { + arg: 'workerId', + type: 'number', + required: true + }, + { + arg: 'state', + type: 'string', + required: true } ], returns: { @@ -37,17 +47,11 @@ module.exports = Self => { } }); - Self.weeklyHourRecordEmail = async(ctx, recipient, week, year, url) => { - const params = { - recipient: recipient, - lang: ctx.req.getLocale(), - week: week, - year: year, - url: url - }; + Self.weeklyHourRecordEmail = async ctx => { + const models = Self.app.models; - const email = new Email('weekly-hour-record', params); + Self.sendTemplate(ctx, 'weekly-hour-record'); - return email.send(); + return models.WorkerTimeControl.updateWorkerTimeControlMail(ctx); }; }; diff --git a/modules/worker/back/models/worker-time-control-mail.json b/modules/worker/back/models/worker-time-control-mail.json index 78b99881d..87eae9217 100644 --- a/modules/worker/back/models/worker-time-control-mail.json +++ b/modules/worker/back/models/worker-time-control-mail.json @@ -28,6 +28,9 @@ }, "reason": { "type": "string" + }, + "sendedCounter": { + "type": "number" } }, "acls": [ diff --git a/modules/worker/front/time-control/index.html b/modules/worker/front/time-control/index.html index bd7e68b89..044ea4038 100644 --- a/modules/worker/front/time-control/index.html +++ b/modules/worker/front/time-control/index.html @@ -204,7 +204,7 @@ vn-id="sendEmailConfirmation" on-accept="$ctrl.resendEmail()" message="Send time control email"> - + Are you sure you want to send it? diff --git a/modules/worker/front/time-control/index.js b/modules/worker/front/time-control/index.js index 3e4aeaa5c..ebfc8b444 100644 --- a/modules/worker/front/time-control/index.js +++ b/modules/worker/front/time-control/index.js @@ -379,20 +379,6 @@ class Controller extends Section { }); } - isSended() { - const params = { - workerId: this.worker.id, - year: this.date.getFullYear(), - week: this.weekNumber, - state: 'SENDED' - }; - const query = `WorkerTimeControls/updateWorkerTimeControlMail`; - this.$http.post(query, params).then(() => { - this.getMailStates(this.date); - this.getWeekData(); - }); - } - changeState(state, reason) { this.state = state; this.reason = reason; @@ -423,10 +409,12 @@ class Controller extends Section { week: this.weekNumber, year: this.date.getFullYear(), url: url, + workerId: this.worker.id, + state: 'SENDED' }; this.$http.post(`WorkerTimeControls/weekly-hour-hecord-email`, params) .then(() => { - this.isSended(); + this.getMailStates(this.date); this.vnApp.showSuccess(this.$t('Email sended')); }); } From 4edb2463b8c9f4a97eabaf35a234e7ade33d5e66 Mon Sep 17 00:00:00 2001 From: carlossa Date: Thu, 30 Mar 2023 08:23:53 +0200 Subject: [PATCH 64/95] refs #5250 eliminacion isEnabled --- modules/worker/back/models/worker-observation.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/modules/worker/back/models/worker-observation.js b/modules/worker/back/models/worker-observation.js index 413d9a2ba..cccc2cfbd 100644 --- a/modules/worker/back/models/worker-observation.js +++ b/modules/worker/back/models/worker-observation.js @@ -1,8 +1,7 @@ module.exports = function(Self) { - Self.validatesPresenceOf('text', isEnabled, {message: 'Description cannot be blank'}); - function isEnabled(err) { - if (!this.text) err(); - } + Self.validatesPresenceOf('text', { + message: 'Description cannot be blank' + }); Self.observe('before save', async function(ctx) { ctx.instance.created = new Date(); From 6ff60046279e300218211a6f0123b58cef701f69 Mon Sep 17 00:00:00 2001 From: joan Date: Thu, 30 Mar 2023 08:35:04 +0200 Subject: [PATCH 65/95] Added version 2314.01 --- CHANGELOG.md | 14 +++++++++++--- db/changes/231401/.gitkeep | 0 package.json | 2 +- 3 files changed, 12 insertions(+), 4 deletions(-) create mode 100644 db/changes/231401/.gitkeep diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c993b657..25c1fc2fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2314.01] - 2023-04-20 + +### Added +- + +### Changed +- + +### Fixed +- + ## [2312.01] - 2023-04-06 ### Added @@ -15,9 +26,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - (Envíos -> Extra comunitarios) Se agrupan las entradas del mismo travel. Añadidos campos Referencia y Importe. - (Envíos -> Índice) Cambiado el buscador superior por uno lateral -### Fixed -- - ## [2310.01] - 2023-03-23 ### Added diff --git a/db/changes/231401/.gitkeep b/db/changes/231401/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/package.json b/package.json index 3d0fc4aed..8fa177646 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "salix-back", - "version": "23.12.01", + "version": "23.14.01", "author": "Verdnatura Levante SL", "description": "Salix backend", "license": "GPL-3.0", From e1bfdc3f3cb5d4b57e8c0b05cefecb1a399f09f1 Mon Sep 17 00:00:00 2001 From: vicent Date: Thu, 30 Mar 2023 11:13:40 +0200 Subject: [PATCH 66/95] eliminada variable que no se usa --- .../back/methods/worker-time-control/weeklyHourRecordEmail.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/modules/worker/back/methods/worker-time-control/weeklyHourRecordEmail.js b/modules/worker/back/methods/worker-time-control/weeklyHourRecordEmail.js index 8e9b325a6..4c6f647cb 100644 --- a/modules/worker/back/methods/worker-time-control/weeklyHourRecordEmail.js +++ b/modules/worker/back/methods/worker-time-control/weeklyHourRecordEmail.js @@ -1,5 +1,3 @@ -const {Email} = require('vn-print'); - module.exports = Self => { Self.remoteMethodCtx('weeklyHourRecordEmail', { description: 'Sends the weekly hour record', From 67689695e4e8bc329800f540bcf5ad42921d9780 Mon Sep 17 00:00:00 2001 From: vicent Date: Thu, 30 Mar 2023 14:29:19 +0200 Subject: [PATCH 67/95] refs #5275 filtra por defecto por el this.vnConfig.warehouseFk --- modules/item/front/fixed-price/index.html | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/item/front/fixed-price/index.html b/modules/item/front/fixed-price/index.html index af41b1bc8..a82fd2742 100644 --- a/modules/item/front/fixed-price/index.html +++ b/modules/item/front/fixed-price/index.html @@ -1,6 +1,7 @@ From 0ea30552dd7226635ef8d238e8b7563fadc08ae9 Mon Sep 17 00:00:00 2001 From: joan Date: Thu, 30 Mar 2023 14:57:53 +0200 Subject: [PATCH 68/95] Eslint as default formatter --- .vscode/settings.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 159cecdc9..05d23f3bb 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -6,5 +6,9 @@ "source.fixAll.eslint": true }, "search.useIgnoreFiles": false, - "editor.defaultFormatter": "dbaeumer.vscode-eslint" + "editor.defaultFormatter": "dbaeumer.vscode-eslint", + "eslint.format.enable": true, + "[javascript]": { + "editor.defaultFormatter": "dbaeumer.vscode-eslint" + } } From 02a1bcbfd30737b6c0fc26ff763fc5f887f28693 Mon Sep 17 00:00:00 2001 From: joan Date: Mon, 3 Apr 2023 08:54:15 +0200 Subject: [PATCH 69/95] fix(setPassword): proper access type Refs #5471 --- back/methods/account/change-password.js | 1 + back/methods/account/set-password.js | 1 + 2 files changed, 2 insertions(+) diff --git a/back/methods/account/change-password.js b/back/methods/account/change-password.js index c0956b193..b8f9de341 100644 --- a/back/methods/account/change-password.js +++ b/back/methods/account/change-password.js @@ -2,6 +2,7 @@ module.exports = Self => { Self.remoteMethod('changePassword', { description: 'Changes the user password', + accessType: 'WRITE', accepts: [ { arg: 'id', diff --git a/back/methods/account/set-password.js b/back/methods/account/set-password.js index ab4d3b3fe..093935948 100644 --- a/back/methods/account/set-password.js +++ b/back/methods/account/set-password.js @@ -1,6 +1,7 @@ module.exports = Self => { Self.remoteMethod('setPassword', { description: 'Sets the user password', + accessType: 'WRITE', accepts: [ { arg: 'id', From 862101c4b018cfc217b1fffc8432551f60d258e0 Mon Sep 17 00:00:00 2001 From: vicent Date: Mon, 3 Apr 2023 21:29:02 +0200 Subject: [PATCH 70/95] refs #4856 feat: si se modifica una fichada actualiza el estado a 'SENDED' y notifica al trabajador --- .../worker-time-control/addTimeEntry.js | 2 + .../worker-time-control/deleteTimeEntry.js | 6 +- .../resendWeeklyHourEmail.js | 68 +++++++++++++++++++ .../methods/worker-time-control/sendMail.js | 21 +++--- .../worker-time-control/updateTimeEntry.js | 6 +- .../weeklyHourRecordEmail.js | 46 +++++++++++-- .../worker/back/models/worker-time-control.js | 1 + modules/worker/front/time-control/index.js | 12 ++-- 8 files changed, 139 insertions(+), 23 deletions(-) create mode 100644 modules/worker/back/methods/worker-time-control/resendWeeklyHourEmail.js diff --git a/modules/worker/back/methods/worker-time-control/addTimeEntry.js b/modules/worker/back/methods/worker-time-control/addTimeEntry.js index fef3cf223..c8c08d9b1 100644 --- a/modules/worker/back/methods/worker-time-control/addTimeEntry.js +++ b/modules/worker/back/methods/worker-time-control/addTimeEntry.js @@ -51,6 +51,8 @@ module.exports = Self => { if (response[0] && response[0].error) throw new UserError(response[0].error); + await models.WorkerTimeControl.resendWeeklyHourEmail(ctx, workerId, args.timed, myOptions); + return response; }; }; diff --git a/modules/worker/back/methods/worker-time-control/deleteTimeEntry.js b/modules/worker/back/methods/worker-time-control/deleteTimeEntry.js index c80dcab81..e33d6b790 100644 --- a/modules/worker/back/methods/worker-time-control/deleteTimeEntry.js +++ b/modules/worker/back/methods/worker-time-control/deleteTimeEntry.js @@ -38,7 +38,11 @@ module.exports = Self => { if (isSubordinate === false || (isSubordinate && isHimself && !isTeamBoss)) throw new UserError(`You don't have enough privileges`); - return Self.rawSql('CALL vn.workerTimeControl_remove(?, ?)', [ + const response = await Self.rawSql('CALL vn.workerTimeControl_remove(?, ?)', [ targetTimeEntry.userFk, targetTimeEntry.timed], myOptions); + + await models.WorkerTimeControl.resendWeeklyHourEmail(ctx, targetTimeEntry.userFk, targetTimeEntry.timed, myOptions); + + return response; }; }; diff --git a/modules/worker/back/methods/worker-time-control/resendWeeklyHourEmail.js b/modules/worker/back/methods/worker-time-control/resendWeeklyHourEmail.js new file mode 100644 index 000000000..5fae6988c --- /dev/null +++ b/modules/worker/back/methods/worker-time-control/resendWeeklyHourEmail.js @@ -0,0 +1,68 @@ +module.exports = Self => { + Self.remoteMethodCtx('resendWeeklyHourEmail', { + description: 'Adds a new hour registry', + accessType: 'WRITE', + accepts: [{ + arg: 'id', + type: 'number', + description: 'The worker id', + http: {source: 'path'} + }, + { + arg: 'dated', + type: 'date', + required: true + }], + returns: [{ + type: 'Object', + root: true + }], + http: { + path: `/:id/resendWeeklyHourEmail`, + verb: 'POST' + } + }); + + Self.resendWeeklyHourEmail = async(ctx, workerId, dated, options) => { + const models = Self.app.models; + const myOptions = {}; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + const yearNumber = dated.getFullYear(); + const weekNumber = getWeekNumber(dated); + const workerTimeControlMail = await models.WorkerTimeControlMail.findOne({ + where: { + workerFk: workerId, + year: yearNumber, + week: weekNumber + } + }, myOptions); + + if (workerTimeControlMail && workerTimeControlMail.state != 'SENDED') { + const worker = await models.EmailUser.findById(workerId); + ctx.args = { + recipient: worker.email, + year: yearNumber, + week: weekNumber, + workerId: workerId, + state: 'SENDED' + }; + return models.WorkerTimeControl.weeklyHourRecordEmail(ctx, myOptions); + } + + return false; + }; + + function getWeekNumber(date) { + const tempDate = new Date(date); + let dayOfWeek = tempDate.getDay(); + dayOfWeek = (dayOfWeek === 0) ? 7 : dayOfWeek; + const firstDayOfWeek = new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate() - (dayOfWeek - 1)); + const firstDayOfYear = new Date(tempDate.getFullYear(), 0, 1); + const differenceInMilliseconds = firstDayOfWeek.getTime() - firstDayOfYear.getTime(); + const weekNumber = Math.floor(differenceInMilliseconds / (1000 * 60 * 60 * 24 * 7)) + 1; + return weekNumber; + } +}; diff --git a/modules/worker/back/methods/worker-time-control/sendMail.js b/modules/worker/back/methods/worker-time-control/sendMail.js index 7aff9e790..9d17265e8 100644 --- a/modules/worker/back/methods/worker-time-control/sendMail.js +++ b/modules/worker/back/methods/worker-time-control/sendMail.js @@ -322,17 +322,20 @@ module.exports = Self => { const lastDay = days[index][days[index].length - 1]; if (day.workerFk != previousWorkerFk || day == lastDay) { - const salix = await models.Url.findOne({ - where: { - appName: 'salix', - environment: process.env.NODE_ENV || 'dev' - } + await models.WorkerTimeControlMail.create({ + workerFk: previousWorkerFk, + year: args.year, + week: args.week }, myOptions); - const timestamp = started.getTime() / 1000; - const url = `${salix.url}worker/${previousWorkerFk}/time-control?timestamp=${timestamp}`; - - await models.WorkerTimeControl.weeklyHourRecordEmail(ctx, previousReceiver, args.week, args.year, url); + ctx.args = { + recipient: previousReceiver, + year: args.year, + week: args.week, + workerId: previousWorkerFk, + state: 'SENDED' + }; + await models.WorkerTimeControl.weeklyHourRecordEmail(ctx, myOptions); previousWorkerFk = day.workerFk; previousReceiver = day.receiver; diff --git a/modules/worker/back/methods/worker-time-control/updateTimeEntry.js b/modules/worker/back/methods/worker-time-control/updateTimeEntry.js index a99a61770..83349ea63 100644 --- a/modules/worker/back/methods/worker-time-control/updateTimeEntry.js +++ b/modules/worker/back/methods/worker-time-control/updateTimeEntry.js @@ -46,8 +46,12 @@ module.exports = Self => { if (notAllowed) throw new UserError(`You don't have enough privileges`); - return targetTimeEntry.updateAttributes({ + const timeEntryUpdated = await targetTimeEntry.updateAttributes({ direction: args.direction }, myOptions); + + await models.WorkerTimeControl.resendWeeklyHourEmail(ctx, targetTimeEntry.userFk, targetTimeEntry.timed, myOptions); + + return timeEntryUpdated; }; }; diff --git a/modules/worker/back/methods/worker-time-control/weeklyHourRecordEmail.js b/modules/worker/back/methods/worker-time-control/weeklyHourRecordEmail.js index 4c6f647cb..f44080559 100644 --- a/modules/worker/back/methods/worker-time-control/weeklyHourRecordEmail.js +++ b/modules/worker/back/methods/worker-time-control/weeklyHourRecordEmail.js @@ -19,11 +19,6 @@ module.exports = Self => { type: 'number', required: true }, - { - arg: 'url', - type: 'string', - required: true - }, { arg: 'workerId', type: 'number', @@ -45,11 +40,48 @@ module.exports = Self => { } }); - Self.weeklyHourRecordEmail = async ctx => { + Self.weeklyHourRecordEmail = async(ctx, options) => { const models = Self.app.models; + const args = ctx.args; + const myOptions = {}; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + const salix = await models.Url.findOne({ + where: { + appName: 'salix', + environment: process.env.NODE_ENV || 'dev' + } + }, myOptions); + + const dated = getMondayDateFromYearWeek(args.year, args.week); + const timestamp = dated.getTime() / 1000; + + const url = `${salix.url}worker/${args.workerId}/time-control?timestamp=${timestamp}`; + ctx.args.url = url; Self.sendTemplate(ctx, 'weekly-hour-record'); - return models.WorkerTimeControl.updateWorkerTimeControlMail(ctx); + return models.WorkerTimeControl.updateWorkerTimeControlMail(ctx, myOptions); }; + + function getMondayDateFromYearWeek(yearNumber, weekNumber) { + const yearStart = new Date(yearNumber, 0, 1); + const firstMonday = new Date(yearStart.getTime() + ((7 - yearStart.getDay() + 1) % 7) * 86400000); + const firstMondayWeekNumber = getWeekNumber(firstMonday); + + if (firstMondayWeekNumber > 1) + firstMonday.setDate(firstMonday.getDate() + 7); + + firstMonday.setDate(firstMonday.getDate() + (weekNumber - 1) * 7); + + return firstMonday; + } + + function getWeekNumber(date) { + const firstDayOfYear = new Date(date.getFullYear(), 0, 1); + const daysPassed = (date - firstDayOfYear) / 86400000; + return Math.ceil((daysPassed + firstDayOfYear.getDay() + 1) / 7); + } }; diff --git a/modules/worker/back/models/worker-time-control.js b/modules/worker/back/models/worker-time-control.js index 5b13e17f2..d5da680cf 100644 --- a/modules/worker/back/models/worker-time-control.js +++ b/modules/worker/back/models/worker-time-control.js @@ -9,6 +9,7 @@ module.exports = Self => { require('../methods/worker-time-control/updateWorkerTimeControlMail')(Self); require('../methods/worker-time-control/weeklyHourRecordEmail')(Self); require('../methods/worker-time-control/getMailStates')(Self); + require('../methods/worker-time-control/resendWeeklyHourEmail')(Self); Self.rewriteDbError(function(err) { if (err.code === 'ER_DUP_ENTRY') diff --git a/modules/worker/front/time-control/index.js b/modules/worker/front/time-control/index.js index ebfc8b444..85ddcedfe 100644 --- a/modules/worker/front/time-control/index.js +++ b/modules/worker/front/time-control/index.js @@ -303,7 +303,10 @@ class Controller extends Section { const query = `WorkerTimeControls/${this.worker.id}/addTimeEntry`; this.$http.post(query, entry) - .then(() => this.fetchHours()); + .then(() => { + this.fetchHours(); + this.getMailStates(this.date); + }); } catch (e) { this.vnApp.showError(this.$t(e.message)); return false; @@ -324,6 +327,7 @@ class Controller extends Section { this.$http.post(`WorkerTimeControls/${entryId}/deleteTimeEntry`).then(() => { this.fetchHours(); + this.getMailStates(this.date); this.vnApp.showSuccess(this.$t('Entry removed')); }); } @@ -395,20 +399,18 @@ class Controller extends Section { this.$http.post(query, {direction: entry.direction}) .then(() => this.vnApp.showSuccess(this.$t('Data saved!'))) .then(() => this.$.editEntry.hide()) - .then(() => this.fetchHours()); + .then(() => this.fetchHours()) + .then(() => this.getMailStates(this.date)); } catch (e) { this.vnApp.showError(this.$t(e.message)); } } resendEmail() { - const timestamp = this.date.getTime() / 1000; - const url = `${window.location.origin}/#!/worker/${this.worker.id}/time-control?timestamp=${timestamp}`; const params = { recipient: this.worker.user.emailUser.email, week: this.weekNumber, year: this.date.getFullYear(), - url: url, workerId: this.worker.id, state: 'SENDED' }; From 32df51eccaf965523de58c3dbc3a2e29bee4f801 Mon Sep 17 00:00:00 2001 From: alexandre Date: Tue, 4 Apr 2023 08:40:51 +0200 Subject: [PATCH 71/95] refs #5092 moved sql --- db/changes/231401/.gitkeep | 0 db/changes/{231201 => 231401}/00-negativeBases.sql | 0 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 db/changes/231401/.gitkeep rename db/changes/{231201 => 231401}/00-negativeBases.sql (100%) diff --git a/db/changes/231401/.gitkeep b/db/changes/231401/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/db/changes/231201/00-negativeBases.sql b/db/changes/231401/00-negativeBases.sql similarity index 100% rename from db/changes/231201/00-negativeBases.sql rename to db/changes/231401/00-negativeBases.sql From 98f61ecfdbfc34b6aa596ed03adafd31e5cecbe2 Mon Sep 17 00:00:00 2001 From: alexandre Date: Tue, 4 Apr 2023 08:47:56 +0200 Subject: [PATCH 72/95] refs #5092 changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 25c1fc2fe..c5ee05fe4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [2314.01] - 2023-04-20 ### Added -- +- (Facturas recibidas -> Bases negativas) Nueva sección ### Changed - From 21b7050cfd6b95fa32a9cb8241911ad1690bdb1f Mon Sep 17 00:00:00 2001 From: vicent Date: Tue, 4 Apr 2023 09:29:40 +0200 Subject: [PATCH 73/95] refs #4856 otros usuarios pueden actualizar el estado --- .../worker-time-control/updateWorkerTimeControlMail.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/modules/worker/back/methods/worker-time-control/updateWorkerTimeControlMail.js b/modules/worker/back/methods/worker-time-control/updateWorkerTimeControlMail.js index 3c44bda40..6f794511f 100644 --- a/modules/worker/back/methods/worker-time-control/updateWorkerTimeControlMail.js +++ b/modules/worker/back/methods/worker-time-control/updateWorkerTimeControlMail.js @@ -47,10 +47,6 @@ module.exports = Self => { if (typeof options == 'object') Object.assign(myOptions, options); - const isHimself = userId == args.workerId; - if (!isHimself) - throw new UserError(`You don't have enough privileges`); - const workerTimeControlMail = await models.WorkerTimeControlMail.findOne({ where: { workerFk: args.workerId, From 0db3bc5e26c53e33bf4c1858cebd13a38aeef42e Mon Sep 17 00:00:00 2001 From: vicent Date: Tue, 4 Apr 2023 09:29:51 +0200 Subject: [PATCH 74/95] refs #4856 fix test --- .../specs/sendMail.spec.js | 120 ------------------ .../worker/front/time-control/index.spec.js | 9 ++ 2 files changed, 9 insertions(+), 120 deletions(-) delete mode 100644 modules/worker/back/methods/worker-time-control/specs/sendMail.spec.js diff --git a/modules/worker/back/methods/worker-time-control/specs/sendMail.spec.js b/modules/worker/back/methods/worker-time-control/specs/sendMail.spec.js deleted file mode 100644 index 24bfd6904..000000000 --- a/modules/worker/back/methods/worker-time-control/specs/sendMail.spec.js +++ /dev/null @@ -1,120 +0,0 @@ -const models = require('vn-loopback/server/server').models; - -describe('workerTimeControl sendMail()', () => { - const workerId = 18; - const activeCtx = { - getLocale: () => { - return 'en'; - } - }; - const ctx = {req: activeCtx, args: {}}; - - it('should fill time control of a worker without records in Journey and with rest', async() => { - const tx = await models.WorkerTimeControl.beginTransaction({}); - - try { - const options = {transaction: tx}; - - await models.WorkerTimeControl.sendMail(ctx, options); - - const workerTimeControl = await models.WorkerTimeControl.find({ - where: {userFk: workerId} - }, options); - - expect(workerTimeControl[0].timed.getHours()).toEqual(8); - expect(workerTimeControl[1].timed.getHours()).toEqual(9); - expect(`${workerTimeControl[2].timed.getHours()}:${workerTimeControl[2].timed.getMinutes()}`).toEqual('9:20'); - expect(workerTimeControl[3].timed.getHours()).toEqual(16); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - throw e; - } - }); - - it('should fill time control of a worker without records in Journey and without rest', async() => { - const workdayOf20Hours = 3; - const tx = await models.WorkerTimeControl.beginTransaction({}); - - try { - const options = {transaction: tx}; - query = `UPDATE business b - SET b.calendarTypeFk = ? - WHERE b.workerFk = ?; `; - await models.WorkerTimeControl.rawSql(query, [workdayOf20Hours, workerId], options); - - await models.WorkerTimeControl.sendMail(ctx, options); - - const workerTimeControl = await models.WorkerTimeControl.find({ - where: {userFk: workerId} - }, options); - - expect(workerTimeControl[0].timed.getHours()).toEqual(8); - expect(workerTimeControl[1].timed.getHours()).toEqual(12); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - throw e; - } - }); - - it('should fill time control of a worker with records in Journey and with rest', async() => { - const tx = await models.WorkerTimeControl.beginTransaction({}); - - try { - const options = {transaction: tx}; - query = `INSERT INTO postgresql.journey(journey_id, day_id, start, end, business_id) - VALUES - (1, 1, '09:00:00', '13:00:00', ?), - (2, 1, '14:00:00', '19:00:00', ?);`; - await models.WorkerTimeControl.rawSql(query, [workerId, workerId, workerId], options); - - await models.WorkerTimeControl.sendMail(ctx, options); - - const workerTimeControl = await models.WorkerTimeControl.find({ - where: {userFk: workerId} - }, options); - - expect(workerTimeControl[0].timed.getHours()).toEqual(9); - expect(workerTimeControl[2].timed.getHours()).toEqual(10); - expect(`${workerTimeControl[3].timed.getHours()}:${workerTimeControl[3].timed.getMinutes()}`).toEqual('10:20'); - expect(workerTimeControl[1].timed.getHours()).toEqual(13); - expect(workerTimeControl[4].timed.getHours()).toEqual(14); - expect(workerTimeControl[5].timed.getHours()).toEqual(19); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - throw e; - } - }); - - it('should fill time control of a worker with records in Journey and without rest', async() => { - const tx = await models.WorkerTimeControl.beginTransaction({}); - - try { - const options = {transaction: tx}; - query = `INSERT INTO postgresql.journey(journey_id, day_id, start, end, business_id) - VALUES - (1, 1, '12:30:00', '14:00:00', ?);`; - await models.WorkerTimeControl.rawSql(query, [workerId, workerId, workerId], options); - - await models.WorkerTimeControl.sendMail(ctx, options); - - const workerTimeControl = await models.WorkerTimeControl.find({ - where: {userFk: workerId} - }, options); - - expect(`${workerTimeControl[0].timed.getHours()}:${workerTimeControl[0].timed.getMinutes()}`).toEqual('12:30'); - expect(workerTimeControl[1].timed.getHours()).toEqual(14); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - throw e; - } - }); -}); - diff --git a/modules/worker/front/time-control/index.spec.js b/modules/worker/front/time-control/index.spec.js index 0f9b48f6b..94f9d3d48 100644 --- a/modules/worker/front/time-control/index.spec.js +++ b/modules/worker/front/time-control/index.spec.js @@ -120,6 +120,13 @@ describe('Component vnWorkerTimeControl', () => { describe('save() ', () => { it(`should make a query an then call to the fetchHours() method`, () => { + const today = Date.vnNew(); + + jest.spyOn(controller, 'getWeekData').mockReturnThis(); + jest.spyOn(controller, 'getMailStates').mockReturnThis(); + + controller.$.model = {applyFilter: jest.fn().mockReturnValue(Promise.resolve())}; + controller.date = today; controller.fetchHours = jest.fn(); controller.selectedRow = {id: 1, timed: Date.vnNew(), direction: 'in'}; controller.$.editEntry = { @@ -240,7 +247,9 @@ describe('Component vnWorkerTimeControl', () => { describe('resendEmail() ', () => { it(`should make a query an then call showSuccess method`, () => { const today = Date.vnNew(); + jest.spyOn(controller, 'getWeekData').mockReturnThis(); + jest.spyOn(controller, 'getMailStates').mockReturnThis(); jest.spyOn(controller.vnApp, 'showSuccess'); controller.$.model = {applyFilter: jest.fn().mockReturnValue(Promise.resolve())}; From 9380b88460e106320585d89b97a06d76afc87601 Mon Sep 17 00:00:00 2001 From: alexandre Date: Tue, 4 Apr 2023 12:40:03 +0200 Subject: [PATCH 75/95] refs #5437 back and test deprecated --- .../back/methods/client/checkDuplicated.js | 63 ------------------- .../client/specs/checkDuplicated.spec.js | 24 ------- modules/client/back/models/client-methods.js | 1 - modules/client/front/basic-data/index.js | 4 +- modules/client/front/create/index.js | 1 - 5 files changed, 1 insertion(+), 92 deletions(-) delete mode 100644 modules/client/back/methods/client/checkDuplicated.js delete mode 100644 modules/client/back/methods/client/specs/checkDuplicated.spec.js diff --git a/modules/client/back/methods/client/checkDuplicated.js b/modules/client/back/methods/client/checkDuplicated.js deleted file mode 100644 index 522cd088f..000000000 --- a/modules/client/back/methods/client/checkDuplicated.js +++ /dev/null @@ -1,63 +0,0 @@ -module.exports = Self => { - Self.remoteMethod('checkDuplicatedData', { - description: 'Checks if a client has same email, mobile or phone than other client and send an email', - accepts: [{ - arg: 'id', - type: 'number', - required: true, - description: 'The client id' - }], - returns: { - type: 'object', - root: true - }, - http: { - verb: 'GET', - path: '/:id/checkDuplicatedData' - } - }); - - Self.checkDuplicatedData = async function(id, options) { - const myOptions = {}; - - if (typeof options == 'object') - Object.assign(myOptions, options); - - const client = await Self.app.models.Client.findById(id, myOptions); - - const findParams = []; - if (client.email) { - const emails = client.email.split(','); - for (let email of emails) - findParams.push({email: email}); - } - - if (client.phone) - findParams.push({phone: client.phone}); - - if (client.mobile) - findParams.push({mobile: client.mobile}); - - const filterObj = { - where: { - and: [ - {or: findParams}, - {id: {neq: client.id}} - ] - } - }; - - const clientSameData = await Self.findOne(filterObj, myOptions); - - if (clientSameData) { - await Self.app.models.Mail.create({ - receiver: 'direccioncomercial@verdnatura.es', - subject: `Cliente con email/teléfono/móvil duplicados`, - body: 'El cliente ' + client.id + ' comparte alguno de estos datos con el cliente ' + clientSameData.id + - '\n- Email: ' + client.email + - '\n- Teléfono: ' + client.phone + - '\n- Móvil: ' + client.mobile - }, myOptions); - } - }; -}; diff --git a/modules/client/back/methods/client/specs/checkDuplicated.spec.js b/modules/client/back/methods/client/specs/checkDuplicated.spec.js deleted file mode 100644 index 1b682ca35..000000000 --- a/modules/client/back/methods/client/specs/checkDuplicated.spec.js +++ /dev/null @@ -1,24 +0,0 @@ -const models = require('vn-loopback/server/server').models; - -describe('client checkDuplicated()', () => { - it('should send an mail if mobile/phone/email is duplicated', async() => { - const tx = await models.Client.beginTransaction({}); - - try { - const options = {transaction: tx}; - - const id = 1110; - const mailModel = models.Mail; - spyOn(mailModel, 'create'); - - await models.Client.checkDuplicatedData(id, options); - - expect(mailModel.create).toHaveBeenCalled(); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - throw e; - } - }); -}); diff --git a/modules/client/back/models/client-methods.js b/modules/client/back/models/client-methods.js index fc77fc090..3538dbeb8 100644 --- a/modules/client/back/models/client-methods.js +++ b/modules/client/back/models/client-methods.js @@ -2,7 +2,6 @@ module.exports = Self => { require('../methods/client/addressesPropagateRe')(Self); require('../methods/client/canBeInvoiced')(Self); require('../methods/client/canCreateTicket')(Self); - require('../methods/client/checkDuplicated')(Self); require('../methods/client/confirmTransaction')(Self); require('../methods/client/consumption')(Self); require('../methods/client/createAddress')(Self); diff --git a/modules/client/front/basic-data/index.js b/modules/client/front/basic-data/index.js index b08d642d1..ed34eefc4 100644 --- a/modules/client/front/basic-data/index.js +++ b/modules/client/front/basic-data/index.js @@ -9,9 +9,7 @@ export default class Controller extends Section { } onSubmit() { - return this.$.watcher.submit().then(() => { - this.$http.get(`Clients/${this.$params.id}/checkDuplicatedData`); - }); + return this.$.watcher.submit(); } } diff --git a/modules/client/front/create/index.js b/modules/client/front/create/index.js index 9ca58ed10..631029802 100644 --- a/modules/client/front/create/index.js +++ b/modules/client/front/create/index.js @@ -12,7 +12,6 @@ export default class Controller extends Section { onSubmit() { return this.$.watcher.submit().then(json => { this.$state.go('client.card.basicData', {id: json.data.id}); - this.$http.get(`Clients/${this.client.id}/checkDuplicatedData`); }); } From e8f0a49f0c2dd223a9e6672b324d2b362076d9e2 Mon Sep 17 00:00:00 2001 From: joan Date: Tue, 4 Apr 2023 13:51:44 +0200 Subject: [PATCH 76/95] fix(resetPassword): increased token TTL for password recovery Refs #5474 --- back/models/user.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/back/models/user.json b/back/models/user.json index 921362e0e..d992fd9db 100644 --- a/back/models/user.json +++ b/back/models/user.json @@ -4,7 +4,8 @@ "options": { "mysql": { "table": "salix.User" - } + }, + "resetPasswordTokenTTL": "604800" }, "properties": { "id": { From c126c6044acb635a1373305ea1a4fc901d023f9b Mon Sep 17 00:00:00 2001 From: joan Date: Tue, 4 Apr 2023 13:55:44 +0200 Subject: [PATCH 77/95] Updated format --- .../back/methods/item-image-queue/download.js | 22 ++-- .../item-image-queue/downloadImages.js | 105 ------------------ 2 files changed, 11 insertions(+), 116 deletions(-) delete mode 100644 modules/item/back/methods/item-image-queue/downloadImages.js diff --git a/modules/item/back/methods/item-image-queue/download.js b/modules/item/back/methods/item-image-queue/download.js index cdc0fe049..5f1b460fc 100644 --- a/modules/item/back/methods/item-image-queue/download.js +++ b/modules/item/back/methods/item-image-queue/download.js @@ -1,7 +1,7 @@ const axios = require('axios'); const uuid = require('uuid'); const fs = require('fs/promises'); -const { createWriteStream } = require('fs'); +const {createWriteStream} = require('fs'); const path = require('path'); const gm = require('gm'); @@ -15,7 +15,7 @@ module.exports = Self => { }, }); - Self.download = async () => { + Self.download = async() => { const models = Self.app.models; const tempContainer = await models.TempContainer.container( 'salix-image' @@ -32,13 +32,13 @@ module.exports = Self => { let tempFilePath; let queueRow; try { - const myOptions = { transaction: tx }; + const myOptions = {transaction: tx}; queueRow = await Self.findOne( { fields: ['id', 'itemFk', 'url', 'attempts'], where: { - url: { neq: null }, + url: {neq: null}, attempts: { lt: maxAttempts, }, @@ -59,7 +59,7 @@ module.exports = Self => { 'model', 'property', ], - where: { name: collectionName }, + where: {name: collectionName}, include: { relation: 'sizes', scope: { @@ -116,16 +116,16 @@ module.exports = Self => { const collectionDir = path.join(rootPath, collectionName); // To max size - const { maxWidth, maxHeight } = collection; + const {maxWidth, maxHeight} = collection; const fullSizePath = path.join(collectionDir, 'full'); const toFullSizePath = `${fullSizePath}/${fileName}`; - await fs.mkdir(fullSizePath, { recursive: true }); + await fs.mkdir(fullSizePath, {recursive: true}); await new Promise((resolve, reject) => { gm(tempFilePath) .resize(maxWidth, maxHeight, '>') .setFormat('png') - .write(toFullSizePath, function (err) { + .write(toFullSizePath, function(err) { if (err) reject(err); if (!err) resolve(); }); @@ -133,12 +133,12 @@ module.exports = Self => { // To collection sizes for (const size of collection.sizes()) { - const { width, height } = size; + const {width, height} = size; const sizePath = path.join(collectionDir, `${width}x${height}`); const toSizePath = `${sizePath}/${fileName}`; - await fs.mkdir(sizePath, { recursive: true }); + await fs.mkdir(sizePath, {recursive: true}); await new Promise((resolve, reject) => { const gmInstance = gm(tempFilePath); @@ -153,7 +153,7 @@ module.exports = Self => { gmInstance .setFormat('png') - .write(toSizePath, function (err) { + .write(toSizePath, function(err) { if (err) reject(err); if (!err) resolve(); }); diff --git a/modules/item/back/methods/item-image-queue/downloadImages.js b/modules/item/back/methods/item-image-queue/downloadImages.js deleted file mode 100644 index 7f53df95a..000000000 --- a/modules/item/back/methods/item-image-queue/downloadImages.js +++ /dev/null @@ -1,105 +0,0 @@ -const https = require('https'); -const fs = require('fs-extra'); -const path = require('path'); -const uuid = require('uuid'); - -module.exports = Self => { - Self.remoteMethod('downloadImages', { - description: 'Returns last entries', - accessType: 'WRITE', - returns: { - type: ['Object'], - root: true - }, - http: { - path: `/downloadImages`, - verb: 'POST' - } - }); - - Self.downloadImages = async() => { - const models = Self.app.models; - const container = await models.TempContainer.container('salix-image'); - const tempPath = path.join(container.client.root, container.name); - const maxAttempts = 3; - - const images = await Self.find({ - where: {attempts: {eq: maxAttempts}} - }); - - for (let image of images) { - const currentStamp = Date.vnNew().getTime(); - const updatedStamp = image.updated.getTime(); - const graceTime = Math.abs(currentStamp - updatedStamp); - const maxTTL = 3600 * 48 * 1000; // 48 hours in ms; - - if (graceTime >= maxTTL) - await Self.destroyById(image.itemFk); - } - - download(); - - async function download() { - const image = await Self.findOne({ - where: {url: {neq: null}, attempts: {lt: maxAttempts}}, - order: 'priority, attempts, updated' - }); - - if (!image) return; - - const fileName = `${uuid.v4()}.png`; - const filePath = path.join(tempPath, fileName); - const imageUrl = image.url.replace('http://', 'https://'); - - https.get(imageUrl, async response => { - if (response.statusCode != 200) { - const error = new Error(`Could not download the image. Status code ${response.statusCode}`); - - return await errorHandler(image.itemFk, error, filePath); - } - - const writeStream = fs.createWriteStream(filePath); - writeStream.on('open', () => response.pipe(writeStream)); - writeStream.on('error', async error => - await errorHandler(image.itemFk, error, filePath)); - writeStream.on('finish', () => writeStream.end()); - - writeStream.on('close', async function() { - try { - await models.Image.registerImage('catalog', filePath, fileName, image.itemFk); - await image.destroy(); - - download(); - } catch (error) { - await errorHandler(image.itemFk, error, filePath); - } - }); - }).on('error', async error => { - await errorHandler(image.itemFk, error, filePath); - }); - } - - async function errorHandler(rowId, error, filePath) { - try { - const row = await Self.findById(rowId); - - if (!row) return; - - if (row.attempts < maxAttempts) { - await row.updateAttributes({ - error: error, - attempts: row.attempts + 1, - updated: Date.vnNew() - }); - } - - if (filePath && fs.existsSync(filePath)) - await fs.unlink(filePath); - - download(); - } catch (err) { - throw new Error(`Image download failed: ${err}`); - } - } - }; -}; From 3630c7d39832148dcf56963554422adbd56da084 Mon Sep 17 00:00:00 2001 From: vicent Date: Tue, 4 Apr 2023 14:09:55 +0200 Subject: [PATCH 78/95] refs #5410 creada ruta de back para enviar emails --- loopback/locale/es.json | 8 +-- .../methods/defaulter/observationEmail.js | 52 +++++++++++++++++++ modules/client/back/models/defaulter.js | 1 + modules/client/front/defaulter/index.js | 21 ++------ modules/client/front/defaulter/index.spec.js | 3 +- modules/client/front/defaulter/locale/es.yml | 2 - 6 files changed, 64 insertions(+), 23 deletions(-) create mode 100644 modules/client/back/methods/defaulter/observationEmail.js diff --git a/loopback/locale/es.json b/loopback/locale/es.json index d6588c0b2..42276efe7 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -268,9 +268,11 @@ "Exists an invoice with a previous date": "Existe una factura con fecha anterior", "Invoice date can't be less than max date": "La fecha de factura no puede ser inferior a la fecha límite", "Warehouse inventory not set": "El almacén inventario no está establecido", - "This locker has already been assigned": "Esta taquilla ya ha sido asignada", + "This locker has already been assigned": "Esta taquilla ya ha sido asignada", "Tickets with associated refunds": "No se pueden borrar tickets con abonos asociados. Este ticket está asociado al abono Nº {{id}}", "Not exist this branch": "La rama no existe", - "This ticket cannot be signed because it has not been boxed": "Este ticket no puede firmarse porque no ha sido encajado", - "Insert a date range": "Inserte un rango de fechas" + "This ticket cannot be signed because it has not been boxed": "Este ticket no puede firmarse porque no ha sido encajado", + "Insert a date range": "Inserte un rango de fechas", + "Added observation": "{{user}} añadió esta observacion: {{text}}", + "Comment added to client": "Observación añadida al cliente {{clientFk}}" } diff --git a/modules/client/back/methods/defaulter/observationEmail.js b/modules/client/back/methods/defaulter/observationEmail.js new file mode 100644 index 000000000..c3c96010e --- /dev/null +++ b/modules/client/back/methods/defaulter/observationEmail.js @@ -0,0 +1,52 @@ +module.exports = Self => { + Self.remoteMethodCtx('observationEmail', { + description: 'Send an email with the observation', + accessType: 'WRITE', + accepts: [ + { + arg: 'defaulters', + type: ['object'], + required: true, + description: 'The defaulters to send the email' + }, + { + arg: 'observation', + type: 'string', + required: true, + description: 'The observation' + }], + returns: { + arg: 'observationEmail' + }, + http: { + path: `/observationEmail`, + verb: 'POST' + } + }); + + Self.observationEmail = async(ctx, defaulters, observation, options) => { + const models = Self.app.models; + const $t = ctx.req.__; // $translate + const myOptions = {}; + const userId = ctx.req.accessToken.userId; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + for (const defaulter of defaulters) { + const user = await models.Account.findById(userId, {fields: ['name']}, myOptions); + + const body = $t('Added observation', { + user: user.name, + text: observation + }); + + await models.Mail.create({ + subject: $t('Comment added to client', {clientFk: defaulter.clientFk}), + body: body, + receiver: `${defaulter.salesPersonName}@verdnatura.es`, + replyTo: `${user.name}@verdnatura.es` + }, myOptions); + } + }; +}; diff --git a/modules/client/back/models/defaulter.js b/modules/client/back/models/defaulter.js index 13bb1a614..868d6cd0a 100644 --- a/modules/client/back/models/defaulter.js +++ b/modules/client/back/models/defaulter.js @@ -1,3 +1,4 @@ module.exports = Self => { require('../methods/defaulter/filter')(Self); + require('../methods/defaulter/observationEmail')(Self); }; diff --git a/modules/client/front/defaulter/index.js b/modules/client/front/defaulter/index.js index e084af650..6289f9202 100644 --- a/modules/client/front/defaulter/index.js +++ b/modules/client/front/defaulter/index.js @@ -130,22 +130,11 @@ export default class Controller extends Section { } sendMail() { - const params = []; - for (let defaulter of this.checked) { - const body = this.$t('Added observation', { - salesPersonName: defaulter.salesPersonName, - text: this.defaulter.observation - }); - - params.push({ - subject: this.$t('Comment added to client', {clientFk: defaulter.clientFk}), - body: body, - receiver: `${defaulter.salesPersonName}@verdnatura.es`, - replyTo: `${window.localStorage.lastUser}@verdnatura.es` - }); - } - - this.$http.post(`Mails`, params); + const params = { + defaulters: this.checked, + observation: this.defaulter.observation + }; + this.$http.post(`Defaulters/observationEmail`, params); } exprBuilder(param, value) { diff --git a/modules/client/front/defaulter/index.spec.js b/modules/client/front/defaulter/index.spec.js index b9672802e..b4a9df184 100644 --- a/modules/client/front/defaulter/index.spec.js +++ b/modules/client/front/defaulter/index.spec.js @@ -80,12 +80,11 @@ describe('client defaulter', () => { controller.defaulter = {observation: 'My new observation'}; const params = [{text: controller.defaulter.observation, clientFk: data[1].clientFk}]; - const mailParams = [{subject: 'Comment added to client', body: 'Added observation', receiver: 'undefined@verdnatura.es', replyTo: 'undefined@verdnatura.es'}]; jest.spyOn(controller.vnApp, 'showSuccess'); $httpBackend.expect('GET', `Defaulters/filter`).respond(200); $httpBackend.expect('POST', `ClientObservations`, params).respond(200, params); - $httpBackend.expect('POST', `Mails`, mailParams).respond(200); + $httpBackend.expect('POST', `Defaulters/observationEmail`).respond(200); controller.onResponse(); $httpBackend.flush(); diff --git a/modules/client/front/defaulter/locale/es.yml b/modules/client/front/defaulter/locale/es.yml index a301a50e0..fe06a15a1 100644 --- a/modules/client/front/defaulter/locale/es.yml +++ b/modules/client/front/defaulter/locale/es.yml @@ -7,7 +7,5 @@ L. O. Date: Fecha Ú. O. Last observation date: Fecha última observación Search client: Buscar clientes Worker who made the last observation: Trabajador que ha realizado la última observación -Added observation: '{{salesPersonName}} añadió esta observacion: {{text}}' -Comment added to client: Observación añadida al cliente {{clientFk}} Email sended!: Email enviado! Observation saved!: Observación añadida! From 35d19e586a4ab686329734e1c2f4ef5371ac538b Mon Sep 17 00:00:00 2001 From: vicent Date: Tue, 4 Apr 2023 14:27:16 +0200 Subject: [PATCH 79/95] add translatiojn --- modules/supplier/front/agency-term/locale/es.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/supplier/front/agency-term/locale/es.yml b/modules/supplier/front/agency-term/locale/es.yml index f4ba7d87d..cdbd7c2ca 100644 --- a/modules/supplier/front/agency-term/locale/es.yml +++ b/modules/supplier/front/agency-term/locale/es.yml @@ -5,4 +5,5 @@ M3 Price: Precio M3 Route Price: Precio ruta Minimum Km: Km minimos Remove row: Eliminar fila -Add row: Añadir fila \ No newline at end of file +Add row: Añadir fila +New autonomous: Nuevo autónomo From eed1ecc208163e29ed8a24371adeb7c939ca931c Mon Sep 17 00:00:00 2001 From: alexandre Date: Tue, 4 Apr 2023 14:47:13 +0200 Subject: [PATCH 80/95] refs #4954 trigger modified --- db/changes/231401/00-clientBeforeUpdate.sql | 72 +++++++++++++++++++++ modules/client/front/fiscal-data/index.js | 4 ++ 2 files changed, 76 insertions(+) create mode 100644 db/changes/231401/00-clientBeforeUpdate.sql diff --git a/db/changes/231401/00-clientBeforeUpdate.sql b/db/changes/231401/00-clientBeforeUpdate.sql new file mode 100644 index 000000000..8f9f70dd5 --- /dev/null +++ b/db/changes/231401/00-clientBeforeUpdate.sql @@ -0,0 +1,72 @@ +DROP TRIGGER IF EXISTS `vn`.`client_beforeUpdate`; +USE `vn`; + +DELIMITER $$ +$$ +CREATE DEFINER=`root`@`localhost` TRIGGER `vn`.`client_beforeUpdate` + BEFORE UPDATE ON `client` + FOR EACH ROW +BEGIN + DECLARE vText VARCHAR(255) DEFAULT NULL; + DECLARE vPayMethodFk INT; + -- Comprueba que el formato de los teléfonos es válido + + IF !(NEW.phone <=> OLD.phone) AND (NEW.phone <> '') THEN + CALL pbx.phone_isValid(NEW.phone); + END IF; + + IF !(NEW.mobile <=> OLD.mobile) AND (NEW.mobile <> '')THEN + CALL pbx.phone_isValid(NEW.mobile); + END IF; + + SELECT id INTO vPayMethodFk + FROM vn.payMethod + WHERE code = 'bankDraft'; + + IF NEW.payMethodFk = vPayMethodFk AND NEW.dueDay = 0 THEN + SET NEW.dueDay = 5; + END IF; + + -- Avisar al comercial si ha llegado la documentación sepa/core + + IF NEW.hasSepaVnl AND !OLD.hasSepaVnl THEN + SET vText = 'Sepa de VNL'; + END IF; + + IF NEW.hasCoreVnl AND !OLD.hasCoreVnl THEN + SET vText = 'Core de VNL'; + END IF; + + IF vText IS NOT NULL + THEN + INSERT INTO mail(receiver, replyTo, `subject`, body) + SELECT + CONCAT(IF(ac.id,u.name, 'jgallego'), '@verdnatura.es'), + 'administracion@verdnatura.es', + CONCAT('Cliente ', NEW.id), + CONCAT('Recibida la documentación: ', vText) + FROM worker w + LEFT JOIN account.user u ON w.userFk = u.id AND u.active + LEFT JOIN account.account ac ON ac.id = u.id + WHERE w.id = NEW.salesPersonFk; + END IF; + + IF NEW.salespersonFk IS NULL AND OLD.salespersonFk IS NOT NULL THEN + IF (SELECT COUNT(clientFk) + FROM clientProtected + WHERE clientFk = NEW.id + ) > 0 THEN + CALL util.throw("HAS_CLIENT_PROTECTED"); + END IF; + END IF; + + IF !(NEW.salesPersonFk <=> OLD.salesPersonFk) THEN + SET NEW.lastSalesPersonFk = IFNULL(NEW.salesPersonFk, OLD.salesPersonFk); + END IF; + + IF !(NEW.businessTypeFk <=> OLD.businessTypeFk) AND (NEW.businessTypeFk = 'individual' OR OLD.businessTypeFk = 'individual') THEN + SET NEW.isTaxDataChecked = 0; + END IF; + +END$$ +DELIMITER ; diff --git a/modules/client/front/fiscal-data/index.js b/modules/client/front/fiscal-data/index.js index d76944c42..acad38185 100644 --- a/modules/client/front/fiscal-data/index.js +++ b/modules/client/front/fiscal-data/index.js @@ -2,6 +2,10 @@ import ngModule from '../module'; import Section from 'salix/components/section'; export default class Controller extends Section { + $onInit() { + this.card.reload(); + } + onSubmit() { const orgData = this.$.watcher.orgData; delete this.client.despiteOfClient; From 81cf35f2d3d50a8becba767926e24a842620ca76 Mon Sep 17 00:00:00 2001 From: alexandre Date: Tue, 4 Apr 2023 14:55:37 +0200 Subject: [PATCH 81/95] refs #5259 drop procedure invoiceOut_afterInsert --- db/changes/231401/00-invoiceOutAfterInsert.sql | 1 + 1 file changed, 1 insertion(+) create mode 100644 db/changes/231401/00-invoiceOutAfterInsert.sql diff --git a/db/changes/231401/00-invoiceOutAfterInsert.sql b/db/changes/231401/00-invoiceOutAfterInsert.sql new file mode 100644 index 000000000..24836e1fb --- /dev/null +++ b/db/changes/231401/00-invoiceOutAfterInsert.sql @@ -0,0 +1 @@ +DROP PROCEDURE IF EXISTS `vn`.`invoiceOut_afterInsert`; From 589e996b699565d4ebc2dec6113cb0874e40e326 Mon Sep 17 00:00:00 2001 From: alexandre Date: Tue, 4 Apr 2023 15:17:19 +0200 Subject: [PATCH 82/95] refs #5259 minor fix --- db/changes/231401/00-invoiceOutAfterInsert.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/changes/231401/00-invoiceOutAfterInsert.sql b/db/changes/231401/00-invoiceOutAfterInsert.sql index 24836e1fb..cf921fd17 100644 --- a/db/changes/231401/00-invoiceOutAfterInsert.sql +++ b/db/changes/231401/00-invoiceOutAfterInsert.sql @@ -1 +1 @@ -DROP PROCEDURE IF EXISTS `vn`.`invoiceOut_afterInsert`; +DROP TRIGGER IF EXISTS `vn`.`invoiceOut_afterInsert`; From 8f4de7e7e95a9082f82a7e3ad689f2839c47bcb1 Mon Sep 17 00:00:00 2001 From: alexandre Date: Tue, 4 Apr 2023 15:27:10 +0200 Subject: [PATCH 83/95] refs #5259 undo delete, update trigger --- db/changes/231401/00-invoiceOutAfterInsert.sql | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/db/changes/231401/00-invoiceOutAfterInsert.sql b/db/changes/231401/00-invoiceOutAfterInsert.sql index cf921fd17..adeaf9834 100644 --- a/db/changes/231401/00-invoiceOutAfterInsert.sql +++ b/db/changes/231401/00-invoiceOutAfterInsert.sql @@ -1 +1,13 @@ DROP TRIGGER IF EXISTS `vn`.`invoiceOut_afterInsert`; +USE vn; + +DELIMITER $$ +$$ +CREATE DEFINER=`root`@`localhost` TRIGGER `vn`.`invoiceOut_afterInsert` + AFTER INSERT ON `invoiceOut` + FOR EACH ROW +BEGIN + CALL clientRisk_update(NEW.clientFk, NEW.companyFk, NEW.amount); +END$$ +DELIMITER ; + From e97b5a9f80fa944ddf6ac553a70b3379ad66d752 Mon Sep 17 00:00:00 2001 From: vicent Date: Wed, 5 Apr 2023 07:54:56 +0200 Subject: [PATCH 84/95] refs #5275 fix backTest --- .../back/methods/fixed-price/specs/upsertFixedPrice.spec.js | 6 +++--- modules/item/back/methods/fixed-price/upsertFixedPrice.js | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/item/back/methods/fixed-price/specs/upsertFixedPrice.spec.js b/modules/item/back/methods/fixed-price/specs/upsertFixedPrice.spec.js index 86f73122d..823406500 100644 --- a/modules/item/back/methods/fixed-price/specs/upsertFixedPrice.spec.js +++ b/modules/item/back/methods/fixed-price/specs/upsertFixedPrice.spec.js @@ -42,7 +42,7 @@ describe('upsertFixedPrice()', () => { delete ctx.args.started; delete ctx.args.ended; - ctx.args.hasMinPrice = true; + ctx.args.hasMinPrice = false; expect(result).toEqual(jasmine.objectContaining(ctx.args)); @@ -74,7 +74,7 @@ describe('upsertFixedPrice()', () => { delete ctx.args.started; delete ctx.args.ended; - ctx.args.hasMinPrice = false; + ctx.args.hasMinPrice = true; expect(result).toEqual(jasmine.objectContaining(ctx.args)); @@ -105,7 +105,7 @@ describe('upsertFixedPrice()', () => { rate2: rate2, rate3: firstRate3, minPrice: 0, - hasMinPrice: false + hasMinPrice: true }}; // create new fixed price diff --git a/modules/item/back/methods/fixed-price/upsertFixedPrice.js b/modules/item/back/methods/fixed-price/upsertFixedPrice.js index d815ed426..edbd23604 100644 --- a/modules/item/back/methods/fixed-price/upsertFixedPrice.js +++ b/modules/item/back/methods/fixed-price/upsertFixedPrice.js @@ -87,7 +87,7 @@ module.exports = Self => { await targetItem.updateAttributes({ minPrice: args.minPrice, - hasMinPrice: args.hasMinPrice ? args.hasMinPrice : false + hasMinPrice: args.hasMinPrice }, myOptions); const itemFields = [ From 77b91b77b234b573724e1c2498647f198b8aff5a Mon Sep 17 00:00:00 2001 From: carlossa Date: Wed, 5 Apr 2023 08:19:50 +0200 Subject: [PATCH 85/95] refs #5439 requesterFk solve --- modules/item/front/request-search-panel/index.html | 10 ++++++---- modules/ticket/back/methods/ticket-request/filter.js | 7 +++++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/modules/item/front/request-search-panel/index.html b/modules/item/front/request-search-panel/index.html index 6316cb32e..a431d4fd6 100644 --- a/modules/item/front/request-search-panel/index.html +++ b/modules/item/front/request-search-panel/index.html @@ -39,16 +39,18 @@ - - {{firstName}} {{name}} + {{firstName}} {{lastName}} +
{ type: 'number', description: `Search requests attended by a given worker id` }, + { + arg: 'requesterFk', + type: 'number' + }, { arg: 'mine', type: 'boolean', @@ -89,6 +93,8 @@ module.exports = Self => { return {'t.id': value}; case 'attenderFk': return {'tr.attenderFk': value}; + case 'requesterFk': + return {'tr.requesterFk': value}; case 'state': switch (value) { case 'pending': @@ -125,6 +131,7 @@ module.exports = Self => { tr.description, tr.response, tr.saleFk, + tr.requesterFk, tr.isOk, s.quantity AS saleQuantity, s.itemFk, From fb5969a120a58749cdd6e11da90d0656f3fe0611 Mon Sep 17 00:00:00 2001 From: vicent Date: Wed, 5 Apr 2023 08:43:47 +0200 Subject: [PATCH 86/95] refs #5275 add test --- .../fixed-price/specs/editFixedPrice.spec.js | 63 ++++++++++++++ modules/item/front/fixed-price/index.spec.js | 84 +++++++++++++++++++ 2 files changed, 147 insertions(+) create mode 100644 modules/item/back/methods/fixed-price/specs/editFixedPrice.spec.js diff --git a/modules/item/back/methods/fixed-price/specs/editFixedPrice.spec.js b/modules/item/back/methods/fixed-price/specs/editFixedPrice.spec.js new file mode 100644 index 000000000..a5e6cd35a --- /dev/null +++ b/modules/item/back/methods/fixed-price/specs/editFixedPrice.spec.js @@ -0,0 +1,63 @@ +const models = require('vn-loopback/server/server').models; + +describe('Item editFixedPrice()', () => { + it('should change the value of a given column for the selected buys', async() => { + const tx = await models.FixedPrice.beginTransaction({}); + const options = {transaction: tx}; + + try { + const ctx = { + args: { + search: '1' + }, + req: {accessToken: {userId: 1}} + }; + + const [original] = await models.FixedPrice.filter(ctx, null, options); + + const field = 'rate2'; + const newValue = 99; + const lines = [{itemFk: original.itemFk, id: original.id}]; + + await models.FixedPrice.editFixedPrice(ctx, field, newValue, lines, null, options); + + const [result] = await models.FixedPrice.filter(ctx, null, options); + + expect(result[field]).toEqual(newValue); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); + + it('should change the value of a given column for filter', async() => { + const tx = await models.FixedPrice.beginTransaction({}); + const options = {transaction: tx}; + + try { + const filter = {'it.categoryFk': 1}; + const ctx = { + args: { + filter: filter + }, + req: {accessToken: {userId: 1}} + }; + + const field = 'rate2'; + const newValue = 88; + + await models.FixedPrice.editFixedPrice(ctx, field, newValue, null, filter, options); + + const [result] = await models.FixedPrice.filter(ctx, null, options); + + expect(result[field]).toEqual(newValue); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); +}); diff --git a/modules/item/front/fixed-price/index.spec.js b/modules/item/front/fixed-price/index.spec.js index 42dd898b3..ae24da60b 100644 --- a/modules/item/front/fixed-price/index.spec.js +++ b/modules/item/front/fixed-price/index.spec.js @@ -12,8 +12,92 @@ describe('fixed price', () => { const $scope = $rootScope.$new(); const $element = angular.element(''); controller = $componentController('vnFixedPrice', {$element, $scope}); + controller.$ = { + model: {refresh: () => {}}, + edit: {hide: () => {}} + }; })); + describe('get columns', () => { + it(`should return a set of columns`, () => { + let result = controller.columns; + + let length = result.length; + let anyColumn = Object.keys(result[Math.floor(Math.random() * Math.floor(length))]); + + expect(anyColumn).toContain('field', 'displayName'); + }); + }); + + describe('get checked', () => { + it(`should return a set of checked lines`, () => { + controller.$.model.data = [ + {checked: true, id: 1}, + {checked: true, id: 2}, + {checked: true, id: 3}, + {checked: false, id: 4}, + ]; + + let result = controller.checked; + + expect(result.length).toEqual(3); + }); + }); + + describe('reCheck()', () => { + it(`should recheck buys`, () => { + controller.$.model.data = [ + {checked: false, id: 1}, + {checked: false, id: 2}, + {checked: false, id: 3}, + {checked: false, id: 4}, + ]; + controller.checkedFixedPrices = [1, 2]; + + controller.reCheck(); + + expect(controller.$.model.data[0].checked).toEqual(true); + expect(controller.$.model.data[1].checked).toEqual(true); + expect(controller.$.model.data[2].checked).toEqual(false); + expect(controller.$.model.data[3].checked).toEqual(false); + }); + }); + + describe('saveChecked()', () => { + it(`should check buy`, () => { + const buyCheck = 3; + controller.checkedFixedPrices = [1, 2]; + + controller.saveChecked(buyCheck); + + expect(controller.checkedFixedPrices[2]).toEqual(buyCheck); + }); + + it(`should uncheck buy`, () => { + const buyUncheck = 3; + controller.checkedFixedPrices = [1, 2, 3]; + + controller.saveChecked(buyUncheck); + + expect(controller.checkedFixedPrices[2]).toEqual(undefined); + }); + }); + + describe('onEditAccept()', () => { + it(`should perform a query to update columns`, () => { + controller.editedColumn = {field: 'my field', newValue: 'the new value'}; + const query = 'FixedPrices/editFixedPrice'; + + $httpBackend.expectPOST(query).respond(); + controller.onEditAccept(); + $httpBackend.flush(); + + const result = controller.checked; + + expect(result.length).toEqual(0); + }); + }); + describe('upsertPrice()', () => { it('should do nothing if one or more required arguments are missing', () => { jest.spyOn(controller.vnApp, 'showSuccess'); From 7d3c6a98f3578443e217651c04b14788192b1731 Mon Sep 17 00:00:00 2001 From: carlossa Date: Wed, 5 Apr 2023 08:48:15 +0200 Subject: [PATCH 87/95] refs #5439 search panel solve --- modules/monitor/front/index/search-panel/index.html | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/modules/monitor/front/index/search-panel/index.html b/modules/monitor/front/index/search-panel/index.html index f478661c5..5458202d2 100644 --- a/modules/monitor/front/index/search-panel/index.html +++ b/modules/monitor/front/index/search-panel/index.html @@ -91,16 +91,6 @@ ng-model="filter.provinceFk" url="Provinces"> - - {{firstName}} {{name}} - Date: Wed, 5 Apr 2023 09:20:56 +0200 Subject: [PATCH 88/95] refs #5275 fix test e2e --- e2e/helpers/selectors.js | 3 ++- e2e/paths/04-item/13_fixedPrice.spec.js | 8 +++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index 32a60a4e2..06d6ed082 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -426,7 +426,8 @@ export default { fourthStarted: 'vn-fixed-price tr:nth-child(5) vn-date-picker[ng-model="price.started"]', fourthEnded: 'vn-fixed-price tr:nth-child(5) vn-date-picker[ng-model="price.ended"]', fourthDeleteIcon: 'vn-fixed-price tr:nth-child(5) > td:nth-child(9) > vn-icon-button[icon="delete"]', - orderColumnId: 'vn-fixed-price th[field="itemFk"]' + orderColumnId: 'vn-fixed-price th[field="itemFk"]', + removeWarehouseFilter: 'vn-searchbar > form > vn-textfield > div.container > div.prepend > prepend > div > span:nth-child(1) > vn-icon > i' }, itemCreateView: { temporalName: 'vn-item-create vn-textfield[ng-model="$ctrl.item.provisionalName"]', diff --git a/e2e/paths/04-item/13_fixedPrice.spec.js b/e2e/paths/04-item/13_fixedPrice.spec.js index 1b0f82d83..ec8238b87 100644 --- a/e2e/paths/04-item/13_fixedPrice.spec.js +++ b/e2e/paths/04-item/13_fixedPrice.spec.js @@ -15,8 +15,9 @@ describe('Item fixed prices path', () => { await browser.close(); }); - it('should click on the add new foxed price button', async() => { - await page.doSearch(); + it('should click on the add new fixed price button', async() => { + await page.waitToClick(selectors.itemFixedPrice.removeWarehouseFilter); + await page.waitForSpinnerLoad(); await page.waitToClick(selectors.itemFixedPrice.add); await page.waitForSelector(selectors.itemFixedPrice.fourthFixedPrice); }); @@ -37,7 +38,8 @@ describe('Item fixed prices path', () => { it('should reload the section and check the created price has the expected ID', async() => { await page.accessToSection('item.index'); await page.accessToSection('item.fixedPrice'); - await page.doSearch(); + await page.waitToClick(selectors.itemFixedPrice.removeWarehouseFilter); + await page.waitForSpinnerLoad(); const result = await page.waitToGetProperty(selectors.itemFixedPrice.fourthItemID, 'value'); From de31d98e2ef4f65921ab548027deec83bc61e199 Mon Sep 17 00:00:00 2001 From: vicent Date: Wed, 5 Apr 2023 13:03:18 +0200 Subject: [PATCH 89/95] refs #5275 fix test e2e --- .../01-salix/03_smartTable_searchBar_integrations.spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/e2e/paths/01-salix/03_smartTable_searchBar_integrations.spec.js b/e2e/paths/01-salix/03_smartTable_searchBar_integrations.spec.js index ad558ace2..a3d747f1c 100644 --- a/e2e/paths/01-salix/03_smartTable_searchBar_integrations.spec.js +++ b/e2e/paths/01-salix/03_smartTable_searchBar_integrations.spec.js @@ -90,7 +90,7 @@ describe('SmartTable SearchBar integration', () => { await page.waitToClick(selectors.itemFixedPrice.orderColumnId); const result = await page.waitToGetProperty(selectors.itemFixedPrice.firstItemID, 'value'); - expect(result).toEqual('13'); + expect(result).toEqual('3'); }); it('should reload page and have same order', async() => { @@ -99,7 +99,7 @@ describe('SmartTable SearchBar integration', () => { }); const result = await page.waitToGetProperty(selectors.itemFixedPrice.firstItemID, 'value'); - expect(result).toEqual('13'); + expect(result).toEqual('3'); }); }); }); From a44a640d155ee5b271860217e8bd1beedc73fb18 Mon Sep 17 00:00:00 2001 From: vicent Date: Wed, 5 Apr 2023 15:14:42 +0200 Subject: [PATCH 90/95] refs #4856 manejo errores --- .../methods/worker-time-control/sendMail.js | 60 ++++++++++++++----- 1 file changed, 44 insertions(+), 16 deletions(-) diff --git a/modules/worker/back/methods/worker-time-control/sendMail.js b/modules/worker/back/methods/worker-time-control/sendMail.js index 9d17265e8..17893e6ad 100644 --- a/modules/worker/back/methods/worker-time-control/sendMail.js +++ b/modules/worker/back/methods/worker-time-control/sendMail.js @@ -82,14 +82,9 @@ module.exports = Self => { updated: Date.vnNew(), state: 'SENDED' }, myOptions); - stmt = new ParameterizedSQL( - `CALL vn.timeControl_calculateByUser(?, ?, ?) - `, [args.workerId, started, ended]); + stmt = new ParameterizedSQL('DROP TEMPORARY TABLE IF EXISTS tmp.`user`'); stmts.push(stmt); - - stmt = new ParameterizedSQL( - `CALL vn.timeBusiness_calculateByUser(?, ?, ?) - `, [args.workerId, started, ended]); + stmt = new ParameterizedSQL('CREATE TEMPORARY TABLE tmp.`user` SELECT id userFk FROM account.user WHERE id = vUserFk', [args.workerId]); stmts.push(stmt); } else { await models.WorkerTimeControl.destroyAll({ @@ -105,13 +100,27 @@ module.exports = Self => { updated: Date.vnNew(), state: 'SENDED' }, myOptions); - stmt = new ParameterizedSQL(`CALL vn.timeControl_calculateAll(?, ?)`, [started, ended]); + stmt = new ParameterizedSQL('DROP TEMPORARY TABLE IF EXISTS tmp.`user`'); stmts.push(stmt); - - stmt = new ParameterizedSQL(`CALL vn.timeBusiness_calculateAll(?, ?)`, [started, ended]); + stmt = new ParameterizedSQL('CREATE TEMPORARY TABLE IF NOT EXISTS tmp.`user` SELECT userFk FROM vn.worker w JOIN account.`user` u ON u.id = w.userFk WHERE userFk IS NOT NULL'); stmts.push(stmt); } + stmt = new ParameterizedSQL( + `CALL vn.timeControl_calculate(?, ?) + `, [started, ended]); + stmts.push(stmt); + + stmt = new ParameterizedSQL( + `CALL vn.timeControl_getError(?, ?) + `, [started, ended]); + stmts.push(stmt); + + stmt = new ParameterizedSQL( + `CALL vn.timeBusiness_calculate(?, ?) + `, [started, ended]); + stmts.push(stmt); + stmt = new ParameterizedSQL(` SELECT CONCAT(u.name, '@verdnatura.es') receiver, u.id workerFk, @@ -131,7 +140,13 @@ module.exports = Self => { JOIN business b ON b.id = tb.businessFk LEFT JOIN tmp.timeControlCalculate tc ON tc.userFk = tb.userFk AND tc.dated = tb.dated LEFT JOIN worker w ON w.id = u.id - WHERE IFNULL(?, u.id) = u.id + LEFT JOIN ( + SELECT DISTINCT wtc.userFk + FROM tmp.timeControlError tce + JOIN vn.workerTimeControl wtc ON wtc.id = tce.id + )sub ON sub.userFk = tb.userFk + WHERE sub.userFK IS NULL + AND IFNULL(?, u.id) = u.id AND b.companyCodeFk = 'VNL' AND w.businessFk AND d.isTeleworking @@ -322,11 +337,9 @@ module.exports = Self => { const lastDay = days[index][days[index].length - 1]; if (day.workerFk != previousWorkerFk || day == lastDay) { - await models.WorkerTimeControlMail.create({ - workerFk: previousWorkerFk, - year: args.year, - week: args.week - }, myOptions); + const query = `INSERT IGNORE INTO workerTimeControlMail (workerFk, year, week) + VALUES(?, ?, ?);`; + await Self.rawSql(query, [previousWorkerFk, args.year, args.week]); ctx.args = { recipient: previousReceiver, @@ -351,6 +364,21 @@ module.exports = Self => { } } + // await Self.rawSql('DROP TEMPORARY TABLE IF EXISTS tmp.`user`'); + await Self.rawSql('CREATE TEMPORARY TABLE IF NOT EXISTS tmp.`user` SELECT userFk FROM vn.worker w JOIN account.`user` u ON u.id = w.userFk WHERE userFk IS NOT NULL'); + + await Self.rawSql(`CALL vn.timeControl_getError(?, ?);`, [started, ended]); + const query = `INSERT INTO mail (receiver, replyTo, subject, body) + SELECT CONCAT(u.name, '@verdnatura.es'), + CONCAT('Error registro de horas semana ', vWeek, ' año ', vYear) , + CONCAT('No se ha podido enviar el registro de horas al empleado/s: ', GROUP_CONCAT(DISTINCT CONCAT('
', w.id, ' ', w.firstName, ' ', w.lastName))) + FROM tmp.timeControlError tce + JOIN vn.workerTimeControl wtc ON wtc.id = tce.id + JOIN worker w ON w.id = wtc.userFK + JOIN account.user u ON u.id = w.bossFk + GROUP BY w.bossFk;`; + await Self.rawSql(query, [previousWorkerFk, args.year, args.week]); + return true; }; From 041590e541965af477e6a373d6867d8428b131ed Mon Sep 17 00:00:00 2001 From: vicent Date: Thu, 6 Apr 2023 08:54:12 +0200 Subject: [PATCH 92/95] refs #4856 maneja errores y notifica a los jefes --- .../methods/worker-time-control/sendMail.js | 32 ++++++++----------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/modules/worker/back/methods/worker-time-control/sendMail.js b/modules/worker/back/methods/worker-time-control/sendMail.js index 17893e6ad..2c827e320 100644 --- a/modules/worker/back/methods/worker-time-control/sendMail.js +++ b/modules/worker/back/methods/worker-time-control/sendMail.js @@ -84,7 +84,7 @@ module.exports = Self => { stmt = new ParameterizedSQL('DROP TEMPORARY TABLE IF EXISTS tmp.`user`'); stmts.push(stmt); - stmt = new ParameterizedSQL('CREATE TEMPORARY TABLE tmp.`user` SELECT id userFk FROM account.user WHERE id = vUserFk', [args.workerId]); + stmt = new ParameterizedSQL('CREATE TEMPORARY TABLE tmp.`user` SELECT id userFk FROM account.user WHERE id = ?', [args.workerId]); stmts.push(stmt); } else { await models.WorkerTimeControl.destroyAll({ @@ -112,15 +112,26 @@ module.exports = Self => { stmts.push(stmt); stmt = new ParameterizedSQL( - `CALL vn.timeControl_getError(?, ?) + `CALL vn.timeBusiness_calculate(?, ?) `, [started, ended]); stmts.push(stmt); stmt = new ParameterizedSQL( - `CALL vn.timeBusiness_calculate(?, ?) + `CALL vn.timeControl_getError(?, ?) `, [started, ended]); stmts.push(stmt); + stmt = new ParameterizedSQL(`INSERT INTO mail (receiver, subject, body) + SELECT CONCAT(u.name, '@verdnatura.es'), + CONCAT('Error registro de horas semana ', ?, ' año ', ?) , + CONCAT('No se ha podido enviar el registro de horas al empleado/s: ', GROUP_CONCAT(DISTINCT CONCAT('
', w.id, ' ', w.firstName, ' ', w.lastName))) + FROM tmp.timeControlError tce + JOIN vn.workerTimeControl wtc ON wtc.id = tce.id + JOIN worker w ON w.id = wtc.userFK + JOIN account.user u ON u.id = w.bossFk + GROUP BY w.bossFk`, [args.week, args.year]); + stmts.push(stmt); + stmt = new ParameterizedSQL(` SELECT CONCAT(u.name, '@verdnatura.es') receiver, u.id workerFk, @@ -364,21 +375,6 @@ module.exports = Self => { } } - // await Self.rawSql('DROP TEMPORARY TABLE IF EXISTS tmp.`user`'); - await Self.rawSql('CREATE TEMPORARY TABLE IF NOT EXISTS tmp.`user` SELECT userFk FROM vn.worker w JOIN account.`user` u ON u.id = w.userFk WHERE userFk IS NOT NULL'); - - await Self.rawSql(`CALL vn.timeControl_getError(?, ?);`, [started, ended]); - const query = `INSERT INTO mail (receiver, replyTo, subject, body) - SELECT CONCAT(u.name, '@verdnatura.es'), - CONCAT('Error registro de horas semana ', vWeek, ' año ', vYear) , - CONCAT('No se ha podido enviar el registro de horas al empleado/s: ', GROUP_CONCAT(DISTINCT CONCAT('
', w.id, ' ', w.firstName, ' ', w.lastName))) - FROM tmp.timeControlError tce - JOIN vn.workerTimeControl wtc ON wtc.id = tce.id - JOIN worker w ON w.id = wtc.userFK - JOIN account.user u ON u.id = w.bossFk - GROUP BY w.bossFk;`; - await Self.rawSql(query, [previousWorkerFk, args.year, args.week]); - return true; }; From f307f79dc2fe478b1f64cf612c8b598fbb200356 Mon Sep 17 00:00:00 2001 From: carlossa Date: Thu, 6 Apr 2023 09:34:46 +0200 Subject: [PATCH 93/95] refs #5250 cambio a ult version de changes --- db/changes/{231201 => 231401}/00-workerNotes.sql | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename db/changes/{231201 => 231401}/00-workerNotes.sql (100%) diff --git a/db/changes/231201/00-workerNotes.sql b/db/changes/231401/00-workerNotes.sql similarity index 100% rename from db/changes/231201/00-workerNotes.sql rename to db/changes/231401/00-workerNotes.sql From 8a297469d6dbd1a899ff398fb05bc1089025def3 Mon Sep 17 00:00:00 2001 From: vicent Date: Thu, 6 Apr 2023 10:06:29 +0200 Subject: [PATCH 94/95] =?UTF-8?q?refs=20#4856=20a=C3=B1adido=20myOptions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../back/methods/worker-time-control/resendWeeklyHourEmail.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/worker/back/methods/worker-time-control/resendWeeklyHourEmail.js b/modules/worker/back/methods/worker-time-control/resendWeeklyHourEmail.js index 5fae6988c..2452a29f9 100644 --- a/modules/worker/back/methods/worker-time-control/resendWeeklyHourEmail.js +++ b/modules/worker/back/methods/worker-time-control/resendWeeklyHourEmail.js @@ -41,7 +41,7 @@ module.exports = Self => { }, myOptions); if (workerTimeControlMail && workerTimeControlMail.state != 'SENDED') { - const worker = await models.EmailUser.findById(workerId); + const worker = await models.EmailUser.findById(workerId, null, myOptions); ctx.args = { recipient: worker.email, year: yearNumber, From ec03c6edfa699ca6a1b988fa6e0c418a8337d1c7 Mon Sep 17 00:00:00 2001 From: vicent Date: Tue, 11 Apr 2023 10:23:33 +0200 Subject: [PATCH 95/95] fix intermittent backTest --- .../item/back/methods/fixed-price/specs/editFixedPrice.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/item/back/methods/fixed-price/specs/editFixedPrice.spec.js b/modules/item/back/methods/fixed-price/specs/editFixedPrice.spec.js index a5e6cd35a..9c265f28a 100644 --- a/modules/item/back/methods/fixed-price/specs/editFixedPrice.spec.js +++ b/modules/item/back/methods/fixed-price/specs/editFixedPrice.spec.js @@ -50,7 +50,7 @@ describe('Item editFixedPrice()', () => { await models.FixedPrice.editFixedPrice(ctx, field, newValue, null, filter, options); - const [result] = await models.FixedPrice.filter(ctx, null, options); + const [result] = await models.FixedPrice.filter(ctx, filter, options); expect(result[field]).toEqual(newValue);