diff --git a/db/changes/232401/00-printer.sql b/db/changes/232401/00-printer.sql new file mode 100644 index 000000000..6280c2c6d --- /dev/null +++ b/db/changes/232401/00-printer.sql @@ -0,0 +1,3 @@ +ALTER TABLE `vn`.`sector` DROP COLUMN `printerFk`; +ALTER TABLE `vn`.`sector` ADD COLUMN `mainPrinterFk` tinyint(3) unsigned; +ALTER TABLE `vn`.`sector` ADD CONSTRAINT sector_FK_1 FOREIGN KEY (mainPrinterFk) REFERENCES vn.printer(id) ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 0457f1165..8dcebf686 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -179,6 +179,8 @@ INSERT INTO `vn`.`printer` (`id`, `name`, `path`, `isLabeler`, `sectorFk`, `ipAd (2, 'printer2', 'path2', 1, 1 , NULL), (4, 'printer4', 'path4', 0, NULL, '10.1.10.4'); +UPDATE `vn`.`sector` SET mainPrinterFk = 1 WHERE id = 1; + INSERT INTO `vn`.`worker`(`id`, `code`, `firstName`, `lastName`, `userFk`,`bossFk`, `phone`, `sectorFk`, `labelerFk`) VALUES (1106, 'LGN', 'David Charles', 'Haller', 1106, 19, 432978106, NULL, NULL), @@ -2729,6 +2731,7 @@ INSERT INTO `util`.`notification` (`id`, `name`, `description`) VALUES (1, 'print-email', 'notification fixture one'), (2, 'invoice-electronic', 'A electronic invoice has been generated'), + (3, 'not-main-printer-configured', 'A printer distinct than main has been configured'), (4, 'supplier-pay-method-update', 'A supplier pay method has been updated'); INSERT INTO `util`.`notificationAcl` (`notificationFk`, `roleFk`) 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 c4f091d1f..526afa140 100644 --- a/e2e/paths/01-salix/03_smartTable_searchBar_integrations.spec.js +++ b/e2e/paths/01-salix/03_smartTable_searchBar_integrations.spec.js @@ -64,6 +64,6 @@ describe('SmartTable SearchBar integration', () => { await page.reload({ waitUntil: 'networkidle2' }); - await page.waitForTextInField(selectors.itemFixedPrice.firstItemID, '13'); + await page.waitForTextInField(selectors.itemFixedPrice.firstItemID, '3'); }); }); diff --git a/e2e/paths/04-item/13_fixedPrice.spec.js b/e2e/paths/04-item/13_fixedPrice.spec.js index 37c4401b0..f36138e18 100644 --- a/e2e/paths/04-item/13_fixedPrice.spec.js +++ b/e2e/paths/04-item/13_fixedPrice.spec.js @@ -88,7 +88,8 @@ describe('Item fixed prices path', () => { it('should reload the section and check the created price has the expected ID', async() => { await page.goto(`http://localhost:5000/#!/item/fixed-price`); - + await page.autocompleteSearch($.warehouseFilter, 'Warehouse one'); + await page.click($.chip); const result = await page.waitToGetProperty($.fourthItemID, 'value'); expect(result).toContain('13'); diff --git a/e2e/paths/05-ticket/01-sale/02_edit_sale.spec.js b/e2e/paths/05-ticket/01-sale/02_edit_sale.spec.js index 2c9646708..a87e00543 100644 --- a/e2e/paths/05-ticket/01-sale/02_edit_sale.spec.js +++ b/e2e/paths/05-ticket/01-sale/02_edit_sale.spec.js @@ -316,7 +316,7 @@ describe('Ticket Edit sale path', () => { it('should confirm the transfered quantity is the correct one', async() => { const result = await page.waitToGetProperty(selectors.ticketSales.secondSaleQuantityCell, 'innerText'); - expect(result).toContain('10'); + expect(result).toContain('20'); }); it('should go back to the original ticket sales section', async() => { diff --git a/e2e/paths/05-ticket/21_future.spec.js b/e2e/paths/05-ticket/21_future.spec.js index 82525c1db..c854dcbaf 100644 --- a/e2e/paths/05-ticket/21_future.spec.js +++ b/e2e/paths/05-ticket/21_future.spec.js @@ -1,8 +1,7 @@ import selectors from '../../helpers/selectors.js'; import getBrowser from '../../helpers/puppeteer'; -// 'https:// redmine.verdnatura.es/issues/5642' -xdescribe('Ticket Future path', () => { +describe('Ticket Future path', () => { let browser; let page; let httpRequest; @@ -22,7 +21,7 @@ xdescribe('Ticket Future path', () => { await browser.close(); }); - it('should show errors snackbar because of the required data', async() => { + it('should search with required data, check three last tickets and move to the future', async() => { await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); await page.clearInput(selectors.ticketFuture.warehouseFk); await page.waitToClick(selectors.ticketFuture.submit); @@ -43,69 +42,58 @@ xdescribe('Ticket Future path', () => { message = await page.waitForSnackbar(); expect(message.text).toContain('originDated is a required argument'); + + await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + await page.waitToClick(selectors.ticketFuture.submit); + + expect(httpRequest).toBeDefined(); + + await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + + await page.autocompleteSearch(selectors.ticketFuture.ipt, 'H'); + await page.waitToClick(selectors.ticketFuture.submit); + + expect(httpRequest).toContain('ipt=H'); + + await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + + await page.clearInput(selectors.ticketFuture.ipt); + + await page.autocompleteSearch(selectors.ticketFuture.futureIpt, 'H'); + await page.waitToClick(selectors.ticketFuture.submit); + + expect(httpRequest).toContain('futureIpt=H'); + + await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + + await page.clearInput(selectors.ticketFuture.futureIpt); + + await page.autocompleteSearch(selectors.ticketFuture.state, 'Free'); + await page.waitToClick(selectors.ticketFuture.submit); + + expect(httpRequest).toContain('state=FREE'); + + await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + + await page.clearInput(selectors.ticketFuture.state); + + await page.autocompleteSearch(selectors.ticketFuture.futureState, 'Free'); + await page.waitToClick(selectors.ticketFuture.submit); + + expect(httpRequest).toContain('futureState=FREE'); + + await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + await page.clearInput(selectors.ticketFuture.state); + await page.clearInput(selectors.ticketFuture.futureState); + await page.waitToClick(selectors.ticketFuture.submit); + + await page.waitForNumberOfElements(selectors.ticketFuture.searchResult, 4); + await page.waitToClick(selectors.ticketFuture.multiCheck); + await page.waitToClick(selectors.ticketFuture.firstCheck); + await page.waitToClick(selectors.ticketFuture.moveButton); + await page.waitToClick(selectors.globalItems.acceptButton); + message = await page.waitForSnackbar(); + + expect(message.text).toContain('Tickets moved successfully!'); }); - - // it('should search with the required data', async() => { - // await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); - // await page.waitToClick(selectors.ticketFuture.submit); - - // expect(httpRequest).toBeDefined(); - // }); - - // it('should search with the origin IPT', async() => { - // await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); - - // await page.autocompleteSearch(selectors.ticketFuture.ipt, 'H'); - // await page.waitToClick(selectors.ticketFuture.submit); - - // expect(httpRequest).toContain('ipt=H'); - // }); - - // it('should search with the destination IPT', async() => { - // await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); - - // await page.clearInput(selectors.ticketFuture.ipt); - - // await page.autocompleteSearch(selectors.ticketFuture.futureIpt, 'H'); - // await page.waitToClick(selectors.ticketFuture.submit); - - // expect(httpRequest).toContain('futureIpt=H'); - // }); - - // it('should search with the origin grouped state', async() => { - // await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); - - // await page.clearInput(selectors.ticketFuture.futureIpt); - - // await page.autocompleteSearch(selectors.ticketFuture.state, 'Free'); - // await page.waitToClick(selectors.ticketFuture.submit); - - // expect(httpRequest).toContain('state=FREE'); - // }); - - // it('should search with the destination grouped state', async() => { - // await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); - - // await page.clearInput(selectors.ticketFuture.state); - - // await page.autocompleteSearch(selectors.ticketFuture.futureState, 'Free'); - // await page.waitToClick(selectors.ticketFuture.submit); - - // expect(httpRequest).toContain('futureState=FREE'); - - // await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); - // await page.clearInput(selectors.ticketFuture.futureState); - // await page.waitToClick(selectors.ticketFuture.submit); - // }); - - // it('should check the three last tickets and move to the future', async() => { - // await page.waitForNumberOfElements(selectors.ticketFuture.searchResult, 4); - // await page.waitToClick(selectors.ticketFuture.multiCheck); - // await page.waitToClick(selectors.ticketFuture.firstCheck); - // await page.waitToClick(selectors.ticketFuture.moveButton); - // await page.waitToClick(selectors.globalItems.acceptButton); - // const message = await page.waitForSnackbar(); - - // expect(message.text).toContain('Tickets moved successfully!'); - // }); }); diff --git a/e2e/paths/05-ticket/22_advance.spec.js b/e2e/paths/05-ticket/22_advance.spec.js index f27120b3b..0e5b5e0c3 100644 --- a/e2e/paths/05-ticket/22_advance.spec.js +++ b/e2e/paths/05-ticket/22_advance.spec.js @@ -1,8 +1,7 @@ import selectors from '../../helpers/selectors.js'; import getBrowser from '../../helpers/puppeteer'; -// 'https:// redmine.verdnatura.es/issues/5642' -xdescribe('Ticket Advance path', () => { +describe('Ticket Advance path', () => { let browser; let page; let httpRequest; @@ -22,7 +21,7 @@ xdescribe('Ticket Advance path', () => { await browser.close(); }); - it('should show errors snackbar because of the required data', async() => { + it('should search with the required data, check the first ticket and move to the present', async() => { await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); await page.clearInput(selectors.ticketAdvance.warehouseFk); @@ -44,45 +43,37 @@ xdescribe('Ticket Advance path', () => { message = await page.waitForSnackbar(); expect(message.text).toContain('dateFuture is a required argument'); + + await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); + await page.waitToClick(selectors.ticketAdvance.submit); + + expect(httpRequest).toBeDefined(); + + await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); + await page.autocompleteSearch(selectors.ticketAdvance.futureIpt, 'H'); + await page.waitToClick(selectors.ticketAdvance.submit); + + expect(httpRequest).toContain('futureIpt=H'); + + await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); + await page.clearInput(selectors.ticketAdvance.futureIpt); + await page.waitToClick(selectors.ticketAdvance.submit); + + await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); + await page.autocompleteSearch(selectors.ticketAdvance.ipt, 'H'); + await page.waitToClick(selectors.ticketAdvance.submit); + + expect(httpRequest).toContain('ipt=H'); + + await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); + await page.clearInput(selectors.ticketAdvance.ipt); + await page.waitToClick(selectors.ticketAdvance.submit); + + await page.waitToClick(selectors.ticketAdvance.firstCheck); + await page.waitToClick(selectors.ticketAdvance.moveButton); + await page.waitToClick(selectors.ticketAdvance.acceptButton); + message = await page.waitForSnackbar(); + + expect(message.text).toContain('Tickets moved successfully!'); }); - - // it('should search with the required data', async() => { - // await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); - // await page.waitToClick(selectors.ticketAdvance.submit); - - // expect(httpRequest).toBeDefined(); - // }); - - // it('should search with the origin IPT', async() => { - // await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); - // await page.autocompleteSearch(selectors.ticketAdvance.futureIpt, 'H'); - // await page.waitToClick(selectors.ticketAdvance.submit); - - // expect(httpRequest).toContain('futureIpt=H'); - - // await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); - // await page.clearInput(selectors.ticketAdvance.futureIpt); - // await page.waitToClick(selectors.ticketAdvance.submit); - // }); - - // it('should search with the destination IPT', async() => { - // await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); - // await page.autocompleteSearch(selectors.ticketAdvance.ipt, 'H'); - // await page.waitToClick(selectors.ticketAdvance.submit); - - // expect(httpRequest).toContain('ipt=H'); - - // await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); - // await page.clearInput(selectors.ticketAdvance.ipt); - // await page.waitToClick(selectors.ticketAdvance.submit); - // }); - - // it('should check the first ticket and move to the present', async() => { - // await page.waitToClick(selectors.ticketAdvance.firstCheck); - // await page.waitToClick(selectors.ticketAdvance.moveButton); - // await page.waitToClick(selectors.ticketAdvance.acceptButton); - // const message = await page.waitForSnackbar(); - - // expect(message.text).toContain('Tickets moved successfully!'); - // }); }); diff --git a/front/salix/components/user-popover/index.js b/front/salix/components/user-popover/index.js index 6cc47db7d..1d88137ff 100644 --- a/front/salix/components/user-popover/index.js +++ b/front/salix/components/user-popover/index.js @@ -20,8 +20,6 @@ class Controller { name: config.languages[code] ? config.languages[code] : code }); } - - vnConfig.initialize(); } set lang(value) { diff --git a/front/salix/routes.js b/front/salix/routes.js index f32c143ef..4cc72ec95 100644 --- a/front/salix/routes.js +++ b/front/salix/routes.js @@ -10,6 +10,9 @@ function config($stateProvider, $urlRouterProvider) { .state('layout', { abstract: true, template: '', + resolve: { + config: ['vnConfig', vnConfig => vnConfig.initialize()] + } }) .state('outLayout', { abstract: true, diff --git a/loopback/common/models/vn-model.js b/loopback/common/models/vn-model.js index f469e893a..37328247b 100644 --- a/loopback/common/models/vn-model.js +++ b/loopback/common/models/vn-model.js @@ -1,6 +1,8 @@ const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; const UserError = require('vn-loopback/util/user-error'); +const utils = require('loopback/lib/utils'); +const {util} = require('webpack'); module.exports = function(Self) { Self.ParameterizedSQL = ParameterizedSQL; @@ -164,23 +166,21 @@ module.exports = function(Self) { function rewriteMethod(methodName) { const realMethod = this[methodName]; - return async(data, options, cb) => { - if (options instanceof Function) { - cb = options; - options = null; - } + return function(...args) { + let cb; + const lastArg = args[args.length - 1]; + if (lastArg instanceof Function) { + cb = lastArg; + args.pop(); + } else + cb = utils.createPromiseCallback(); - try { - const result = await realMethod.call(this, data, options); - - if (cb) cb(null, result); - else return result; - } catch (err) { - let myErr = replaceErr(err, replaceErrFunc); - if (cb) cb(myErr); - else - throw myErr; - } + args.push(function(err, res) { + if (err) err = replaceErr(err, replaceErrFunc); + cb(err, res); + }); + realMethod.apply(this, args); + return cb.promise; }; } diff --git a/modules/entry/back/methods/entry/addFromBuy.js b/modules/entry/back/methods/entry/addFromBuy.js index a40dd3412..f7e1b637e 100644 --- a/modules/entry/back/methods/entry/addFromBuy.js +++ b/modules/entry/back/methods/entry/addFromBuy.js @@ -48,7 +48,7 @@ module.exports = Self => { try { let buy = await models.Buy.findOne({where: {entryFk: args.id}}, myOptions); if (buy) - await buy.updateAttribute('printedStickers', args.printedStickers); + await buy.updateAttribute('printedStickers', args.printedStickers, myOptions); else { const userConfig = await models.UserConfig.findById(userId, {fields: ['warehouseFk']}, myOptions); await Self.rawSql( diff --git a/modules/shelving/back/models/sector.json b/modules/shelving/back/models/sector.json index 0dc502cd0..47d66bd8d 100644 --- a/modules/shelving/back/models/sector.json +++ b/modules/shelving/back/models/sector.json @@ -56,7 +56,7 @@ "type": "number", "required": false }, - "printerFk": { + "mainPrinterFk": { "type": "number", "required": false }, @@ -69,4 +69,4 @@ "required": true } } -} \ No newline at end of file +} diff --git a/modules/worker/back/methods/operator/spec/operator.spec.js b/modules/worker/back/methods/operator/spec/operator.spec.js new file mode 100644 index 000000000..1253be474 --- /dev/null +++ b/modules/worker/back/methods/operator/spec/operator.spec.js @@ -0,0 +1,62 @@ +const models = require('vn-loopback/server/server').models; + +describe('Operator', () => { + const authorFk = 9; + const sectorId = 1; + const mainPrinter = 1; + const notificationName = 'not-main-printer-configured'; + const operator = { + workerFk: 1, + trainFk: 1, + itemPackingTypeFk: 'H', + warehouseFk: 1, + sectorFk: sectorId + }; + + async function createOperator(labelerFk, options) { + operator.labelerFk = labelerFk; + await models.Operator.create(operator, options); + return models.NotificationQueue.findOne({ + where: { + notificationFk: notificationName + } + }, options); + } + + it('should create notification when configured a not main printer in the sector', async() => { + const tx = await models.Operator.beginTransaction({}); + + try { + const options = {transaction: tx, accessToken: {userId: authorFk}}; + const notificationQueue = await createOperator(2, options); + const params = JSON.parse(notificationQueue.params); + + expect(notificationQueue.notificationFk).toEqual(notificationName); + expect(notificationQueue.authorFk).toEqual(authorFk); + expect(params.labelerId).toEqual(2); + expect(params.sectorId).toEqual(1); + expect(params.workerId).toEqual(9); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); + + it('should not create notification when configured the main printer in the sector', async() => { + const tx = await models.Operator.beginTransaction({}); + + try { + const options = {transaction: tx, accessToken: {userId: authorFk}}; + const notificationQueue = await createOperator(mainPrinter, options); + + expect(notificationQueue).toEqual(null); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); +}); diff --git a/modules/worker/back/models/operator.js b/modules/worker/back/models/operator.js new file mode 100644 index 000000000..e9b590fa6 --- /dev/null +++ b/modules/worker/back/models/operator.js @@ -0,0 +1,28 @@ +module.exports = function(Self) { + Self.observe('after save', async function(ctx) { + const instance = ctx.instance; + const models = Self.app.models; + const options = ctx.options; + + if (!instance.sectorFk || !instance.labelerFk) return; + + const sector = await models.Sector.findById(instance.sectorFk, { + fields: ['mainPrinterFk'] + }, options); + + if (sector.mainPrinterFk && sector.mainPrinterFk != instance.labelerFk) { + const userId = ctx.options.accessToken.userId; + await models.NotificationQueue.create({ + notificationFk: 'not-main-printer-configured', + authorFk: userId, + params: JSON.stringify( + { + 'labelerId': instance.labelerFk, + 'sectorId': instance.sectorFk, + 'workerId': userId + } + ) + }, options); + } + }); +}; diff --git a/modules/worker/back/models/operator.json b/modules/worker/back/models/operator.json index db8a8c451..9433a0fd5 100644 --- a/modules/worker/back/models/operator.json +++ b/modules/worker/back/models/operator.json @@ -27,10 +27,10 @@ "type": "number", "required": true }, - "sectorFk ": { + "sectorFk": { "type": "number" }, - "labelerFk ": { + "labelerFk": { "type": "number" } }, @@ -41,4 +41,4 @@ "foreignKey": "sectorFk" } } -} \ No newline at end of file +} diff --git a/print/templates/email/not-main-printer-configured/assets/css/import.js b/print/templates/email/not-main-printer-configured/assets/css/import.js new file mode 100644 index 000000000..4b4bb7086 --- /dev/null +++ b/print/templates/email/not-main-printer-configured/assets/css/import.js @@ -0,0 +1,11 @@ +const Stylesheet = require(`vn-print/core/stylesheet`); + +const path = require('path'); +const vnPrintPath = path.resolve('print'); + +module.exports = new Stylesheet([ + `${vnPrintPath}/common/css/spacing.css`, + `${vnPrintPath}/common/css/misc.css`, + `${vnPrintPath}/common/css/layout.css`, + `${vnPrintPath}/common/css/email.css`]) + .mergeStyles(); diff --git a/print/templates/email/not-main-printer-configured/locale/en.yml b/print/templates/email/not-main-printer-configured/locale/en.yml new file mode 100644 index 000000000..2a3051145 --- /dev/null +++ b/print/templates/email/not-main-printer-configured/locale/en.yml @@ -0,0 +1,3 @@ +subject: Not main printer configured +title: Not main printer configured +description: 'Printer #{0} {1} has been configured in sector #{2} {3} (the main printer for that sector is #{4} {5}). Ask the worker {6}.' diff --git a/print/templates/email/not-main-printer-configured/locale/es.yml b/print/templates/email/not-main-printer-configured/locale/es.yml new file mode 100644 index 000000000..b6fe5f9a0 --- /dev/null +++ b/print/templates/email/not-main-printer-configured/locale/es.yml @@ -0,0 +1,3 @@ +subject: Configurada impresora no principal +title: Configurada impresora no principal +description: 'Se ha configurado la impresora #{0} {1} en el sector #{2} {3} (la impresora principal de ese sector es la #{4} {5}). Preguntar al trabajador {6}.' diff --git a/print/templates/email/not-main-printer-configured/not-main-printer-configured.html b/print/templates/email/not-main-printer-configured/not-main-printer-configured.html new file mode 100644 index 000000000..1e9ffed7a --- /dev/null +++ b/print/templates/email/not-main-printer-configured/not-main-printer-configured.html @@ -0,0 +1,8 @@ + +
+
+

{{ $t('title') }}

+

+
+
+
diff --git a/print/templates/email/not-main-printer-configured/not-main-printer-configured.js b/print/templates/email/not-main-printer-configured/not-main-printer-configured.js new file mode 100755 index 000000000..c381991fa --- /dev/null +++ b/print/templates/email/not-main-printer-configured/not-main-printer-configured.js @@ -0,0 +1,33 @@ +const Component = require(`vn-print/core/component`); +const emailBody = new Component('email-body'); + +module.exports = { + name: 'not-main-printer-configured', + async serverPrefetch() { + this.sector = await this.findOneFromDef('sector', [this.sectorId]); + + if (!this.sector) + throw new Error('Something went wrong'); + + this.labeler = await this.findOneFromDef('printer', [this.labelerId]); + this.mainPrinter = await this.findOneFromDef('printer', [this.sector.mainPrinterFk]); + this.worker = await this.findOneFromDef('worker', [this.workerId]); + }, + components: { + 'email-body': emailBody.build(), + }, + props: { + labelerId: { + type: Number, + required: true + }, + sectorId: { + type: Number, + required: true + }, + workerId: { + type: Number, + required: true + } + } +}; diff --git a/print/templates/email/not-main-printer-configured/sql/printer.sql b/print/templates/email/not-main-printer-configured/sql/printer.sql new file mode 100644 index 000000000..265818129 --- /dev/null +++ b/print/templates/email/not-main-printer-configured/sql/printer.sql @@ -0,0 +1,3 @@ +SELECT id, name + FROM vn.printer + WHERE id = ? diff --git a/print/templates/email/not-main-printer-configured/sql/sector.sql b/print/templates/email/not-main-printer-configured/sql/sector.sql new file mode 100644 index 000000000..5d54eeeb9 --- /dev/null +++ b/print/templates/email/not-main-printer-configured/sql/sector.sql @@ -0,0 +1,3 @@ +SELECT id, description, mainPrinterFk + FROM vn.sector + WHERE id = ? diff --git a/print/templates/email/not-main-printer-configured/sql/worker.sql b/print/templates/email/not-main-printer-configured/sql/worker.sql new file mode 100644 index 000000000..0c7327851 --- /dev/null +++ b/print/templates/email/not-main-printer-configured/sql/worker.sql @@ -0,0 +1,3 @@ +SELECT nickname + FROM account.user + WHERE id = ?