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 @@
+
+
+
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 = ?