Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 5595-modify-loggable-tables-in-procs
gitea/salix/pipeline/head This commit looks good
Details
gitea/salix/pipeline/head This commit looks good
Details
This commit is contained in:
commit
7121b1e516
|
@ -24,13 +24,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
### Added
|
### Added
|
||||||
- (Tickets -> Crear Factura) Al facturar se envia automáticamente el pdf al cliente
|
- (Tickets -> Crear Factura) Al facturar se envia automáticamente el pdf al cliente
|
||||||
- (Artículos -> Histórico) Filtro para mostrar lo anterior al inventario
|
- (Artículos -> Histórico) Filtro para mostrar lo anterior al inventario
|
||||||
|
- (Trabajadores -> Nuevo trabajador) Permite elegir el método de pago
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- (Trabajadores -> Nuevo trabajador) Los clientes se crean sin 'TR' pero se añade tipo de negocio 'Trabajador'
|
- (Trabajadores -> Nuevo trabajador) Los clientes se crean sin 'TR' pero se añade tipo de negocio 'Trabajador'
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- (Tickets -> Líneas) Se permite hacer split de líneas al mismo ticket
|
- (Tickets -> Líneas) Se permite hacer split de líneas al mismo ticket
|
||||||
|
- (Tickets -> Cambiar estado) Ahora muestra la lista completa de todos los estados
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
LOAD DATA LOCAL INFILE ?
|
LOAD DATA LOCAL INFILE ?
|
||||||
INTO TABLE `edi`.`item`
|
INTO TABLE `edi`.`item`
|
||||||
|
CHARACTER SET ascii
|
||||||
FIELDS TERMINATED BY ';'
|
FIELDS TERMINATED BY ';'
|
||||||
LINES TERMINATED BY '\n' (@col1, @col2, @col3, @col4, @col5, @col6, @col7, @col8, @col9, @col10, @col11, @col12)
|
LINES TERMINATED BY '\n' (@col1, @col2, @col3, @col4, @col5, @col6, @col7, @col8, @col9, @col10, @col11, @col12)
|
||||||
SET
|
SET id = @col2,
|
||||||
id = @col2,
|
|
||||||
product_name = @col4,
|
product_name = @col4,
|
||||||
name = @col5,
|
name = @col5,
|
||||||
plant_id = @col7,
|
plant_id = @col7,
|
||||||
|
@ -11,3 +11,4 @@ LOAD DATA LOCAL INFILE ?
|
||||||
entry_date = STR_TO_DATE(@col10, '%Y%m%d'),
|
entry_date = STR_TO_DATE(@col10, '%Y%m%d'),
|
||||||
expiry_date = IFNULL(NULL,STR_TO_DATE(@col11, '%Y%m%d')),
|
expiry_date = IFNULL(NULL,STR_TO_DATE(@col11, '%Y%m%d')),
|
||||||
change_date_time = STR_TO_DATE(@col12, '%Y%m%d%H%i')
|
change_date_time = STR_TO_DATE(@col12, '%Y%m%d%H%i')
|
||||||
|
|
|
@ -53,9 +53,9 @@ module.exports = Self => {
|
||||||
const fileNames = updatableFiles.map(file => file.name);
|
const fileNames = updatableFiles.map(file => file.name);
|
||||||
|
|
||||||
const tables = await Self.rawSql(`
|
const tables = await Self.rawSql(`
|
||||||
SELECT fileName, toTable, file
|
SELECT fileName, toTable, file
|
||||||
FROM edi.tableConfig
|
FROM edi.tableConfig
|
||||||
WHERE file IN (?)`, [fileNames], options);
|
WHERE file IN (?)`, [fileNames], options);
|
||||||
|
|
||||||
for (const table of tables) {
|
for (const table of tables) {
|
||||||
const fileName = table.file;
|
const fileName = table.file;
|
||||||
|
@ -85,9 +85,9 @@ module.exports = Self => {
|
||||||
for (const file of updatableFiles) {
|
for (const file of updatableFiles) {
|
||||||
console.log(`Updating file ${file.name} checksum...`);
|
console.log(`Updating file ${file.name} checksum...`);
|
||||||
await Self.rawSql(`
|
await Self.rawSql(`
|
||||||
UPDATE edi.fileConfig
|
UPDATE edi.fileConfig
|
||||||
SET checksum = ?
|
SET checksum = ?
|
||||||
WHERE name = ?`,
|
WHERE name = ?`,
|
||||||
[file.checksum, file.name], options);
|
[file.checksum, file.name], options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,7 +121,8 @@ module.exports = Self => {
|
||||||
host: ftpConfig.host,
|
host: ftpConfig.host,
|
||||||
username: ftpConfig.user,
|
username: ftpConfig.user,
|
||||||
password: ftpConfig.password,
|
password: ftpConfig.password,
|
||||||
procotol: 'ftp'
|
procotol: 'ftp',
|
||||||
|
additionalLftpCommands: 'set ssl:verify-certificate no'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,7 +133,7 @@ module.exports = Self => {
|
||||||
const ftpClient = await getFtpClient();
|
const ftpClient = await getFtpClient();
|
||||||
console.debug(`Checking checksum for file ${file.name}...`);
|
console.debug(`Checking checksum for file ${file.name}...`);
|
||||||
|
|
||||||
ftpClient.cat(`codes/${file.name}.txt`);
|
ftpClient.cat(`codes/${file.name}.TXT`);
|
||||||
|
|
||||||
const response = await new Promise((resolve, reject) => {
|
const response = await new Promise((resolve, reject) => {
|
||||||
ftpClient.exec((err, response) => {
|
ftpClient.exec((err, response) => {
|
||||||
|
@ -227,10 +228,10 @@ module.exports = Self => {
|
||||||
|
|
||||||
await Self.rawSql(sqlTemplate, [filePath], options);
|
await Self.rawSql(sqlTemplate, [filePath], options);
|
||||||
await Self.rawSql(`
|
await Self.rawSql(`
|
||||||
UPDATE edi.tableConfig
|
UPDATE edi.tableConfig
|
||||||
SET updated = ?
|
SET updated = ?
|
||||||
WHERE fileName = ?
|
WHERE fileName = ?
|
||||||
`, [Date.vnNew(), baseName], options);
|
`, [Date.vnNew(), baseName], options);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`Updated table ${toTable}\n`);
|
console.log(`Updated table ${toTable}\n`);
|
||||||
|
|
|
@ -56,8 +56,6 @@ CREATE TABLE `vn`.`collectionWagonTicket` (
|
||||||
|
|
||||||
ALTER TABLE `vn`.`wagon` ADD `typeFk` int(11) unsigned NOT 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 `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`)
|
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
|
||||||
VALUES
|
VALUES
|
||||||
('WagonType', '*', '*', 'ALLOW', 'ROLE', 'productionAssi'),
|
('WagonType', '*', '*', 'ALLOW', 'ROLE', 'productionAssi'),
|
||||||
|
@ -70,3 +68,4 @@ INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `pri
|
||||||
('WagonType', 'createWagonType', '*', 'ALLOW', 'ROLE', 'productionAssi'),
|
('WagonType', 'createWagonType', '*', 'ALLOW', 'ROLE', 'productionAssi'),
|
||||||
('WagonType', 'deleteWagonType', '*', 'ALLOW', 'ROLE', 'productionAssi'),
|
('WagonType', 'deleteWagonType', '*', 'ALLOW', 'ROLE', 'productionAssi'),
|
||||||
('WagonType', 'editWagonType', '*', 'ALLOW', 'ROLE', 'productionAssi');
|
('WagonType', 'editWagonType', '*', 'ALLOW', 'ROLE', 'productionAssi');
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
ALTER TABLE `vn`.`wagon` ADD CONSTRAINT `wagon_type` FOREIGN KEY (`typeFk`) REFERENCES `wagonType` (`id`) ON UPDATE CASCADE;
|
|
@ -1,7 +1,7 @@
|
||||||
ALTER TABLE `vn`.`workerConfig` ADD payMethodFk tinyint(3) unsigned NULL;
|
ALTER TABLE `vn`.`workerConfig` ADD payMethodFk tinyint(3) unsigned NULL;
|
||||||
ALTER TABLE `vn`.`workerConfig` ADD CONSTRAINT workerConfig_FK FOREIGN KEY (roleFk) REFERENCES account.`role`(id) ON DELETE RESTRICT ON UPDATE CASCADE;
|
ALTER TABLE `vn`.`workerConfig` ADD CONSTRAINT workerConfig_FK FOREIGN KEY (roleFk) REFERENCES account.`role`(id) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
ALTER TABLE `vn`.`workerConfig` ADD CONSTRAINT workerConfig_FK_1 FOREIGN KEY (payMethodFk) REFERENCES `vn`.`payMethod`(id) ON DELETE SET NULL ON UPDATE CASCADE;
|
ALTER TABLE `vn`.`workerConfig` ADD CONSTRAINT workerConfig_FK_1 FOREIGN KEY (payMethodFk) REFERENCES `vn`.`payMethod`(id) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
-- Cuando se apruebe el PR quitar y poner en redmine para hacerse manualmente
|
|
||||||
UPDATE `vn`.`workerConfig`
|
UPDATE `vn`.`workerConfig`
|
||||||
SET payMethodFk = 4
|
SET payMethodFk = 4
|
||||||
WHERE id=1;
|
WHERE id=1;
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
CREATE TABLE `vn`.`buyConfig` (
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`monthsAgo` int(11) NOT NULL DEFAULT 6 COMMENT 'Meses desde la última compra',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||||
|
|
||||||
|
CREATE TABLE `vn`.`travelConfig` (
|
||||||
|
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`warehouseInFk` smallint(6) unsigned NOT NULL DEFAULT 8 COMMENT 'Warehouse de origen',
|
||||||
|
`warehouseOutFk` smallint(6) unsigned NOT NULL DEFAULT 60 COMMENT 'Warehouse destino',
|
||||||
|
`agencyFk` int(11) NOT NULL DEFAULT 1378 COMMENT 'Agencia por defecto',
|
||||||
|
`companyFk` smallint(5) unsigned NOT NULL DEFAULT 442 COMMENT 'Compañía por defecto',
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `travelConfig_FK` (`warehouseInFk`),
|
||||||
|
KEY `travelConfig_FK_1` (`warehouseOutFk`),
|
||||||
|
KEY `travelConfig_FK_2` (`agencyFk`),
|
||||||
|
KEY `travelConfig_FK_3` (`companyFk`),
|
||||||
|
CONSTRAINT `travelConfig_FK` FOREIGN KEY (`warehouseInFk`) REFERENCES `warehouse` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||||
|
CONSTRAINT `travelConfig_FK_1` FOREIGN KEY (`warehouseOutFk`) REFERENCES `warehouse` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||||
|
CONSTRAINT `travelConfig_FK_2` FOREIGN KEY (`agencyFk`) REFERENCES `agencyMode` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||||
|
CONSTRAINT `travelConfig_FK_3` FOREIGN KEY (`companyFk`) REFERENCES `company` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||||
|
|
||||||
|
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
|
||||||
|
VALUES
|
||||||
|
('Entry', 'addFromPackaging', 'WRITE', 'ALLOW', 'ROLE', 'production'),
|
||||||
|
('Entry', 'addFromBuy', 'WRITE', 'ALLOW', 'ROLE', 'production'),
|
||||||
|
('Supplier', 'getItemsPackaging', 'READ', 'ALLOW', 'ROLE', 'production');
|
|
@ -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;
|
|
@ -179,6 +179,8 @@ INSERT INTO `vn`.`printer` (`id`, `name`, `path`, `isLabeler`, `sectorFk`, `ipAd
|
||||||
(2, 'printer2', 'path2', 1, 1 , NULL),
|
(2, 'printer2', 'path2', 1, 1 , NULL),
|
||||||
(4, 'printer4', 'path4', 0, NULL, '10.1.10.4');
|
(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`)
|
INSERT INTO `vn`.`worker`(`id`, `code`, `firstName`, `lastName`, `userFk`,`bossFk`, `phone`, `sectorFk`, `labelerFk`)
|
||||||
VALUES
|
VALUES
|
||||||
(1106, 'LGN', 'David Charles', 'Haller', 1106, 19, 432978106, NULL, NULL),
|
(1106, 'LGN', 'David Charles', 'Haller', 1106, 19, 432978106, NULL, NULL),
|
||||||
|
@ -905,7 +907,7 @@ INSERT INTO `vn`.`itemFamily`(`code`, `description`)
|
||||||
INSERT INTO `vn`.`item`(`id`, `typeFk`, `size`, `inkFk`, `stems`, `originFk`, `description`, `producerFk`, `intrastatFk`, `expenceFk`,
|
INSERT INTO `vn`.`item`(`id`, `typeFk`, `size`, `inkFk`, `stems`, `originFk`, `description`, `producerFk`, `intrastatFk`, `expenceFk`,
|
||||||
`comment`, `relevancy`, `image`, `subName`, `minPrice`, `stars`, `family`, `isFloramondo`, `genericFk`, `itemPackingTypeFk`, `hasMinPrice`, `packingShelve`, `weightByPiece`)
|
`comment`, `relevancy`, `image`, `subName`, `minPrice`, `stars`, `family`, `isFloramondo`, `genericFk`, `itemPackingTypeFk`, `hasMinPrice`, `packingShelve`, `weightByPiece`)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 2, 70, 'YEL', 1, 1, NULL, 1, 06021010, 2000000000, NULL, 0, '1', NULL, 0, 1, 'VT', 0, NULL, 'V', 0, 15,3),
|
(1, 2, 70, 'YEL', 1, 1, NULL, 1, 06021010, 2000000000, NULL, 0, '1', NULL, 0, 1, 'EMB', 0, NULL, 'V', 0, 15,3),
|
||||||
(2, 2, 70, 'BLU', 1, 2, NULL, 1, 06021010, 2000000000, NULL, 0, '2', NULL, 0, 2, 'VT', 0, NULL, 'H', 0, 10,2),
|
(2, 2, 70, 'BLU', 1, 2, NULL, 1, 06021010, 2000000000, NULL, 0, '2', NULL, 0, 2, 'VT', 0, NULL, 'H', 0, 10,2),
|
||||||
(3, 1, 60, 'YEL', 1, 3, NULL, 1, 05080000, 4751000000, NULL, 0, '3', NULL, 0, 5, 'VT', 0, NULL, NULL, 0, 5,5),
|
(3, 1, 60, 'YEL', 1, 3, NULL, 1, 05080000, 4751000000, NULL, 0, '3', NULL, 0, 5, 'VT', 0, NULL, NULL, 0, 5,5),
|
||||||
(4, 1, 60, 'YEL', 1, 1, 'Increases block', 1, 05080000, 4751000000, NULL, 0, '4', NULL, 0, 3, 'VT', 0, NULL, NULL, 0, NULL,NULL),
|
(4, 1, 60, 'YEL', 1, 1, 'Increases block', 1, 05080000, 4751000000, NULL, 0, '4', NULL, 0, 3, 'VT', 0, NULL, NULL, 0, NULL,NULL),
|
||||||
|
@ -2729,6 +2731,7 @@ INSERT INTO `util`.`notification` (`id`, `name`, `description`)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 'print-email', 'notification fixture one'),
|
(1, 'print-email', 'notification fixture one'),
|
||||||
(2, 'invoice-electronic', 'A electronic invoice has been generated'),
|
(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');
|
(4, 'supplier-pay-method-update', 'A supplier pay method has been updated');
|
||||||
|
|
||||||
INSERT INTO `util`.`notificationAcl` (`notificationFk`, `roleFk`)
|
INSERT INTO `util`.`notificationAcl` (`notificationFk`, `roleFk`)
|
||||||
|
@ -2886,6 +2889,10 @@ INSERT INTO `vn`.`wagonTypeTray` (`id`, `typeFk`, `height`, `colorFk`)
|
||||||
(2, 1, 50, 2),
|
(2, 1, 50, 2),
|
||||||
(3, 1, 0, 3);
|
(3, 1, 0, 3);
|
||||||
|
|
||||||
|
INSERT INTO `vn`.`travelConfig` (`id`, `warehouseInFk`, `warehouseOutFk`, `agencyFk`, `companyFk`)
|
||||||
|
VALUES
|
||||||
|
(1, 1, 1, 1, 442);
|
||||||
|
|
||||||
|
INSERT INTO `vn`.`buyConfig` (`id`, `monthsAgo`)
|
||||||
|
VALUES
|
||||||
|
(1, 6);
|
||||||
|
|
|
@ -61950,7 +61950,6 @@ BEGIN
|
||||||
* @vWarehouseFk almacen donde buscar
|
* @vWarehouseFk almacen donde buscar
|
||||||
* @vDate Si la fecha es null, muestra el histórico desde el inventario. Si la fecha no es null, muestra histórico desde la fecha pasada.
|
* @vDate Si la fecha es null, muestra el histórico desde el inventario. Si la fecha no es null, muestra histórico desde la fecha pasada.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DECLARE vDateInventory DATETIME;
|
DECLARE vDateInventory DATETIME;
|
||||||
DECLARE vInvCalculated INT;
|
DECLARE vInvCalculated INT;
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ services:
|
||||||
- node.role == worker
|
- node.role == worker
|
||||||
resources:
|
resources:
|
||||||
limits:
|
limits:
|
||||||
memory: 4G
|
memory: 8G
|
||||||
configs:
|
configs:
|
||||||
datasources:
|
datasources:
|
||||||
external: true
|
external: true
|
||||||
|
|
|
@ -22,7 +22,8 @@ export async function getBrowser() {
|
||||||
env.E2E_SHOW = true;
|
env.E2E_SHOW = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const headless = !env.E2E_SHOW;
|
const headless = env.E2E_SHOW ? false : 'new';
|
||||||
|
|
||||||
const browser = await Puppeteer.launch({
|
const browser = await Puppeteer.launch({
|
||||||
args,
|
args,
|
||||||
defaultViewport: null,
|
defaultViewport: null,
|
||||||
|
|
|
@ -64,6 +64,6 @@ describe('SmartTable SearchBar integration', () => {
|
||||||
await page.reload({
|
await page.reload({
|
||||||
waitUntil: 'networkidle2'
|
waitUntil: 'networkidle2'
|
||||||
});
|
});
|
||||||
await page.waitForTextInField(selectors.itemFixedPrice.firstItemID, '13');
|
await page.waitForTextInField(selectors.itemFixedPrice.firstItemID, '3');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -88,7 +88,8 @@ describe('Item fixed prices path', () => {
|
||||||
|
|
||||||
it('should reload the section and check the created price has the expected ID', async() => {
|
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.goto(`http://localhost:5000/#!/item/fixed-price`);
|
||||||
|
await page.autocompleteSearch($.warehouseFilter, 'Warehouse one');
|
||||||
|
await page.click($.chip);
|
||||||
const result = await page.waitToGetProperty($.fourthItemID, 'value');
|
const result = await page.waitToGetProperty($.fourthItemID, 'value');
|
||||||
|
|
||||||
expect(result).toContain('13');
|
expect(result).toContain('13');
|
||||||
|
|
|
@ -316,7 +316,7 @@ describe('Ticket Edit sale path', () => {
|
||||||
it('should confirm the transfered quantity is the correct one', async() => {
|
it('should confirm the transfered quantity is the correct one', async() => {
|
||||||
const result = await page.waitToGetProperty(selectors.ticketSales.secondSaleQuantityCell, 'innerText');
|
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() => {
|
it('should go back to the original ticket sales section', async() => {
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import selectors from '../../helpers/selectors.js';
|
import selectors from '../../helpers/selectors.js';
|
||||||
import getBrowser from '../../helpers/puppeteer';
|
import getBrowser from '../../helpers/puppeteer';
|
||||||
|
|
||||||
// 'https:// redmine.verdnatura.es/issues/5642'
|
describe('Ticket Future path', () => {
|
||||||
xdescribe('Ticket Future path', () => {
|
|
||||||
let browser;
|
let browser;
|
||||||
let page;
|
let page;
|
||||||
let httpRequest;
|
let httpRequest;
|
||||||
|
@ -22,7 +21,7 @@ xdescribe('Ticket Future path', () => {
|
||||||
await browser.close();
|
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.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
||||||
await page.clearInput(selectors.ticketFuture.warehouseFk);
|
await page.clearInput(selectors.ticketFuture.warehouseFk);
|
||||||
await page.waitToClick(selectors.ticketFuture.submit);
|
await page.waitToClick(selectors.ticketFuture.submit);
|
||||||
|
@ -43,69 +42,58 @@ xdescribe('Ticket Future path', () => {
|
||||||
message = await page.waitForSnackbar();
|
message = await page.waitForSnackbar();
|
||||||
|
|
||||||
expect(message.text).toContain('originDated is a required argument');
|
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!');
|
|
||||||
// });
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import selectors from '../../helpers/selectors.js';
|
import selectors from '../../helpers/selectors.js';
|
||||||
import getBrowser from '../../helpers/puppeteer';
|
import getBrowser from '../../helpers/puppeteer';
|
||||||
|
|
||||||
// 'https:// redmine.verdnatura.es/issues/5642'
|
describe('Ticket Advance path', () => {
|
||||||
xdescribe('Ticket Advance path', () => {
|
|
||||||
let browser;
|
let browser;
|
||||||
let page;
|
let page;
|
||||||
let httpRequest;
|
let httpRequest;
|
||||||
|
@ -22,7 +21,7 @@ xdescribe('Ticket Advance path', () => {
|
||||||
await browser.close();
|
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.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
|
||||||
await page.clearInput(selectors.ticketAdvance.warehouseFk);
|
await page.clearInput(selectors.ticketAdvance.warehouseFk);
|
||||||
|
|
||||||
|
@ -44,45 +43,37 @@ xdescribe('Ticket Advance path', () => {
|
||||||
message = await page.waitForSnackbar();
|
message = await page.waitForSnackbar();
|
||||||
|
|
||||||
expect(message.text).toContain('dateFuture is a required argument');
|
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!');
|
|
||||||
// });
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -150,10 +150,10 @@ export default class Controller extends Section {
|
||||||
if (value == null || value == '') return null;
|
if (value == null || value == '') return null;
|
||||||
switch (prop) {
|
switch (prop) {
|
||||||
case 'search':
|
case 'search':
|
||||||
const or = [{changedModelId: value}];
|
if (/^[0-9]+$/.test(value))
|
||||||
if (!/^[0-9]+$/.test(value))
|
return {changedModelId: value};
|
||||||
or.push({changedModelValue: {like: `%${value}%`}});
|
else
|
||||||
return {or};
|
return {changedModelValue: {like: `%${value}%`}};
|
||||||
case 'changes':
|
case 'changes':
|
||||||
return {or: [
|
return {or: [
|
||||||
{oldInstance: {like: `%${value}%`}},
|
{oldInstance: {like: `%${value}%`}},
|
||||||
|
|
|
@ -20,8 +20,6 @@ class Controller {
|
||||||
name: config.languages[code] ? config.languages[code] : code
|
name: config.languages[code] ? config.languages[code] : code
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
vnConfig.initialize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
set lang(value) {
|
set lang(value) {
|
||||||
|
|
|
@ -10,6 +10,9 @@ function config($stateProvider, $urlRouterProvider) {
|
||||||
.state('layout', {
|
.state('layout', {
|
||||||
abstract: true,
|
abstract: true,
|
||||||
template: '<vn-layout></vn-layout>',
|
template: '<vn-layout></vn-layout>',
|
||||||
|
resolve: {
|
||||||
|
config: ['vnConfig', vnConfig => vnConfig.initialize()]
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.state('outLayout', {
|
.state('outLayout', {
|
||||||
abstract: true,
|
abstract: true,
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
|
|
||||||
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
|
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
|
||||||
const UserError = require('vn-loopback/util/user-error');
|
const UserError = require('vn-loopback/util/user-error');
|
||||||
|
const utils = require('loopback/lib/utils');
|
||||||
|
const {util} = require('webpack');
|
||||||
|
|
||||||
module.exports = function(Self) {
|
module.exports = function(Self) {
|
||||||
Self.ParameterizedSQL = ParameterizedSQL;
|
Self.ParameterizedSQL = ParameterizedSQL;
|
||||||
|
@ -164,23 +166,21 @@ module.exports = function(Self) {
|
||||||
|
|
||||||
function rewriteMethod(methodName) {
|
function rewriteMethod(methodName) {
|
||||||
const realMethod = this[methodName];
|
const realMethod = this[methodName];
|
||||||
return async(data, options, cb) => {
|
return function(...args) {
|
||||||
if (options instanceof Function) {
|
let cb;
|
||||||
cb = options;
|
const lastArg = args[args.length - 1];
|
||||||
options = null;
|
if (lastArg instanceof Function) {
|
||||||
}
|
cb = lastArg;
|
||||||
|
args.pop();
|
||||||
|
} else
|
||||||
|
cb = utils.createPromiseCallback();
|
||||||
|
|
||||||
try {
|
args.push(function(err, res) {
|
||||||
const result = await realMethod.call(this, data, options);
|
if (err) err = replaceErr(err, replaceErrFunc);
|
||||||
|
cb(err, res);
|
||||||
if (cb) cb(null, result);
|
});
|
||||||
else return result;
|
realMethod.apply(this, args);
|
||||||
} catch (err) {
|
return cb.promise;
|
||||||
let myErr = replaceErr(err, replaceErrFunc);
|
|
||||||
if (cb) cb(myErr);
|
|
||||||
else
|
|
||||||
throw myErr;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,3 +15,7 @@ columns:
|
||||||
image: image
|
image: image
|
||||||
hasGrant: has grant
|
hasGrant: has grant
|
||||||
userFk: user
|
userFk: user
|
||||||
|
recoverPass: recover password
|
||||||
|
role: role
|
||||||
|
sync: pending sync
|
||||||
|
lastPassChange: password changed
|
||||||
|
|
|
@ -15,3 +15,7 @@ columns:
|
||||||
image: imagen
|
image: imagen
|
||||||
hasGrant: puede delegar
|
hasGrant: puede delegar
|
||||||
userFk: usuario
|
userFk: usuario
|
||||||
|
recoverPass: recuperar contraseña
|
||||||
|
role: rol
|
||||||
|
sync: Pendiente de sincronizar
|
||||||
|
lastPassChange: contraseña modificada
|
||||||
|
|
|
@ -59,6 +59,12 @@ module.exports = function(Self) {
|
||||||
fields: ['id', 'name']
|
fields: ['id', 'name']
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
relation: 'businessType',
|
||||||
|
scope: {
|
||||||
|
fields: ['description']
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
relation: 'account',
|
relation: 'account',
|
||||||
scope: {
|
scope: {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
"base": "VnModel",
|
"base": "VnModel",
|
||||||
"options": {
|
"options": {
|
||||||
"mysql": {
|
"mysql": {
|
||||||
"table": "payMethod"
|
"table": "payMethod"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
|
@ -43,6 +43,10 @@
|
||||||
{{$ctrl.client.salesPersonUser.name}}
|
{{$ctrl.client.salesPersonUser.name}}
|
||||||
</span>
|
</span>
|
||||||
</vn-label-value>
|
</vn-label-value>
|
||||||
|
<vn-label-value
|
||||||
|
label="Business type"
|
||||||
|
value="{{$ctrl.client.businessType.description}}">
|
||||||
|
</vn-label-value>
|
||||||
</div>
|
</div>
|
||||||
<div class="icons">
|
<div class="icons">
|
||||||
<vn-icon
|
<vn-icon
|
||||||
|
|
|
@ -8,3 +8,4 @@ Client invoices list: Listado de facturas del cliente
|
||||||
Pay method: Forma de pago
|
Pay method: Forma de pago
|
||||||
Unpaid Dated: "Fecha: {{dated | date:'dd/MM/yyyy'}}"
|
Unpaid Dated: "Fecha: {{dated | date:'dd/MM/yyyy'}}"
|
||||||
Unpaid Amount: "Importe: {{amount | currency: 'EUR':2}}"
|
Unpaid Amount: "Importe: {{amount | currency: 'EUR':2}}"
|
||||||
|
Business type: Tipo de negocio
|
|
@ -0,0 +1,107 @@
|
||||||
|
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethodCtx('addFromBuy', {
|
||||||
|
description: 'Modify a field of a buy or creates a new one with default values',
|
||||||
|
accessType: 'WRITE',
|
||||||
|
accepts: [{
|
||||||
|
arg: 'id',
|
||||||
|
type: 'number',
|
||||||
|
required: true,
|
||||||
|
description: 'The entry id',
|
||||||
|
http: {source: 'path'}
|
||||||
|
}, {
|
||||||
|
arg: 'item',
|
||||||
|
type: 'number',
|
||||||
|
required: true,
|
||||||
|
description: 'The item id',
|
||||||
|
}, {
|
||||||
|
arg: 'printedStickers',
|
||||||
|
type: 'number',
|
||||||
|
required: true,
|
||||||
|
description: 'The field to modify',
|
||||||
|
}],
|
||||||
|
returns: {
|
||||||
|
type: 'object',
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/:id/addFromBuy`,
|
||||||
|
verb: 'POST'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.addFromBuy = async(ctx, options) => {
|
||||||
|
const args = ctx.args;
|
||||||
|
const models = Self.app.models;
|
||||||
|
const userId = ctx.req.accessToken.userId;
|
||||||
|
const myOptions = {userId};
|
||||||
|
let tx;
|
||||||
|
|
||||||
|
if (typeof options == 'object')
|
||||||
|
Object.assign(myOptions, options);
|
||||||
|
|
||||||
|
if (!myOptions.transaction) {
|
||||||
|
tx = await Self.beginTransaction({});
|
||||||
|
myOptions.transaction = tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
let buy = await models.Buy.findOne({where: {entryFk: args.id}}, myOptions);
|
||||||
|
if (buy)
|
||||||
|
await buy.updateAttribute('printedStickers', args.printedStickers, myOptions);
|
||||||
|
else {
|
||||||
|
const userConfig = await models.UserConfig.findById(userId, {fields: ['warehouseFk']}, myOptions);
|
||||||
|
await Self.rawSql(
|
||||||
|
'CALL vn.buyUltimate(?,?)',
|
||||||
|
[userConfig.warehouseFk, null],
|
||||||
|
myOptions
|
||||||
|
);
|
||||||
|
let buyUltimate = await Self.rawSql(
|
||||||
|
`SELECT buyFk
|
||||||
|
FROM tmp.buyUltimate
|
||||||
|
WHERE itemFk = ?`,
|
||||||
|
[args.item],
|
||||||
|
myOptions
|
||||||
|
);
|
||||||
|
buyUltimate = await models.Buy.findById(buyUltimate[0].buyFk, null, myOptions);
|
||||||
|
buy = await models.Buy.create({
|
||||||
|
entryFk: args.id,
|
||||||
|
itemFk: args.item,
|
||||||
|
quantity: 0,
|
||||||
|
dispatched: buyUltimate.dispatched,
|
||||||
|
buyingValue: buyUltimate.buyingValue,
|
||||||
|
freightValue: buyUltimate.freightValue,
|
||||||
|
isIgnored: buyUltimate.isIgnored,
|
||||||
|
stickers: buyUltimate.stickers,
|
||||||
|
packing: buyUltimate.packing,
|
||||||
|
grouping: buyUltimate.grouping,
|
||||||
|
groupingMode: buyUltimate.groupingMode,
|
||||||
|
containerFk: buyUltimate.containerFk,
|
||||||
|
comissionValue: buyUltimate.comissionValue,
|
||||||
|
packageValue: buyUltimate.packageValue,
|
||||||
|
location: buyUltimate.location,
|
||||||
|
packageFk: buyUltimate.packageFk,
|
||||||
|
price1: buyUltimate.price1,
|
||||||
|
price2: buyUltimate.price2,
|
||||||
|
price3: buyUltimate.price3,
|
||||||
|
minPrice: buyUltimate.minPrice,
|
||||||
|
printedStickers: args.printedStickers,
|
||||||
|
workerFk: buyUltimate.workerFk,
|
||||||
|
isChecked: buyUltimate.isChecked,
|
||||||
|
isPickedOff: buyUltimate.isPickedOff,
|
||||||
|
created: buyUltimate.created,
|
||||||
|
ektFk: buyUltimate.ektFk,
|
||||||
|
weight: buyUltimate.weight,
|
||||||
|
deliveryFk: buyUltimate.deliveryFk,
|
||||||
|
itemOriginalFk: buyUltimate.itemOriginalFk
|
||||||
|
}, myOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tx) await tx.commit();
|
||||||
|
return buy;
|
||||||
|
} catch (e) {
|
||||||
|
if (tx) await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,72 @@
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethodCtx('addFromPackaging', {
|
||||||
|
description: 'Create a receipt or return entry for a supplier with a specific travel',
|
||||||
|
accessType: 'WRITE',
|
||||||
|
accepts: [{
|
||||||
|
arg: 'supplier',
|
||||||
|
type: 'number',
|
||||||
|
required: true,
|
||||||
|
description: 'The supplier id',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'isTravelReception',
|
||||||
|
type: 'boolean',
|
||||||
|
required: true,
|
||||||
|
description: 'Indicates if the travel associated with the entry is a return or receipt travel'
|
||||||
|
}],
|
||||||
|
returns: {
|
||||||
|
type: 'object',
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/addFromPackaging`,
|
||||||
|
verb: 'POST'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.addFromPackaging = async(ctx, options) => {
|
||||||
|
const args = ctx.args;
|
||||||
|
const models = Self.app.models;
|
||||||
|
let tx;
|
||||||
|
const myOptions = {};
|
||||||
|
|
||||||
|
if (typeof options == 'object')
|
||||||
|
Object.assign(myOptions, options);
|
||||||
|
|
||||||
|
if (!myOptions.transaction) {
|
||||||
|
tx = await Self.beginTransaction({});
|
||||||
|
myOptions.transaction = tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const travelConfig = await models.TravelConfig.findOne({}, myOptions);
|
||||||
|
|
||||||
|
const today = new Date();
|
||||||
|
const yesterday = new Date(today);
|
||||||
|
yesterday.setDate(today.getDate() - 1);
|
||||||
|
const tomorrow = new Date(today);
|
||||||
|
tomorrow.setDate(today.getDate() + 1);
|
||||||
|
|
||||||
|
const travel = await models.Travel.create({
|
||||||
|
shipped: args.isTravelReception ? yesterday : today,
|
||||||
|
landed: args.isTravelReception ? today : tomorrow,
|
||||||
|
agencyModeFk: travelConfig.agencyFk,
|
||||||
|
warehouseInFk: travelConfig.warehouseOutFk,
|
||||||
|
warehouseOutFk: travelConfig.warehouseInFk
|
||||||
|
}, myOptions);
|
||||||
|
|
||||||
|
const entry = await models.Entry.create({
|
||||||
|
supplierFk: args.supplier,
|
||||||
|
travelFk: travel.id,
|
||||||
|
companyFk: travelConfig.companyFk
|
||||||
|
}, myOptions);
|
||||||
|
|
||||||
|
if (tx) await tx.commit();
|
||||||
|
|
||||||
|
return entry;
|
||||||
|
} catch (e) {
|
||||||
|
if (tx) await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,51 @@
|
||||||
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
|
||||||
|
describe('entry addFromBuy()', () => {
|
||||||
|
const ctx = {req: {accessToken: {userId: 18}}};
|
||||||
|
|
||||||
|
it('should change the printedStickers of an existent buy', async() => {
|
||||||
|
const id = 1;
|
||||||
|
const item = 1;
|
||||||
|
const buy = 1;
|
||||||
|
|
||||||
|
const tx = await models.Entry.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
try {
|
||||||
|
const currentBuy = await models.Buy.findById(buy, {fields: ['printedStickers']}, options);
|
||||||
|
const printedStickers = currentBuy.printedStickers + 10;
|
||||||
|
ctx.args = {id, item, printedStickers};
|
||||||
|
const newBuy = await models.Entry.addFromBuy(ctx, options);
|
||||||
|
|
||||||
|
expect(newBuy.printedStickers).toEqual(printedStickers);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create for an entry without a concrete item a new buy', async() => {
|
||||||
|
const id = 8;
|
||||||
|
const item = 1;
|
||||||
|
const printedStickers = 10;
|
||||||
|
|
||||||
|
const tx = await models.Entry.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
try {
|
||||||
|
const emptyBuy = await models.Buy.findOne({where: {entryFk: id}}, options);
|
||||||
|
ctx.args = {id, item, printedStickers};
|
||||||
|
const newBuy = await models.Entry.addFromBuy(ctx, options);
|
||||||
|
|
||||||
|
expect(emptyBuy).toEqual(null);
|
||||||
|
expect(newBuy.entryFk).toEqual(id);
|
||||||
|
expect(newBuy.printedStickers).toEqual(printedStickers);
|
||||||
|
expect(newBuy.itemFk).toEqual(item);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,49 @@
|
||||||
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
|
describe('entry addFromPackaging()', () => {
|
||||||
|
const supplier = 442;
|
||||||
|
const today = new Date();
|
||||||
|
const yesterday = new Date(today);
|
||||||
|
yesterday.setDate(today.getDate() - 1);
|
||||||
|
|
||||||
|
beforeAll(async() => {
|
||||||
|
const activeCtx = {
|
||||||
|
accessToken: {userId: 49},
|
||||||
|
http: {
|
||||||
|
req: {
|
||||||
|
headers: {origin: 'http://localhost'},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||||
|
active: activeCtx,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create an incoming travel', async() => {
|
||||||
|
const ctx = {args: {isTravelReception: true, supplier}};
|
||||||
|
const tx = await models.Entry.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const entry = await models.Entry.addFromPackaging(ctx, options);
|
||||||
|
const travelConfig = await models.TravelConfig.findOne({}, options);
|
||||||
|
const travel = await models.Travel.findOne({order: 'id DESC'}, options);
|
||||||
|
|
||||||
|
expect(new Date(travel.shipped).getDate()).toEqual(yesterday.getDate());
|
||||||
|
expect(new Date(travel.landed).getDate()).toEqual(today.getDate());
|
||||||
|
expect(travel.agencyModeFk).toEqual(travelConfig.agencyFk);
|
||||||
|
expect(travel.warehouseInFk).toEqual(travelConfig.warehouseOutFk);
|
||||||
|
expect(travel.warehouseOutFk).toEqual(travelConfig.warehouseInFk);
|
||||||
|
expect(entry.supplierFk).toEqual(supplier);
|
||||||
|
expect(entry.travelFk).toEqual(travel.id);
|
||||||
|
expect(entry.companyFk).toEqual(travelConfig.companyFk);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
|
@ -5,6 +5,9 @@
|
||||||
"Buy": {
|
"Buy": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
"BuyConfig": {
|
||||||
|
"dataSource": "vn"
|
||||||
|
},
|
||||||
"ItemMatchProperties": {
|
"ItemMatchProperties": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"name": "BuyConfig",
|
||||||
|
"base": "VnModel",
|
||||||
|
"options": {
|
||||||
|
"mysql": {
|
||||||
|
"table": "buyConfig"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "number",
|
||||||
|
"id": true
|
||||||
|
},
|
||||||
|
"showLastBuy": {
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -39,6 +39,9 @@
|
||||||
"packageValue": {
|
"packageValue": {
|
||||||
"type": "number"
|
"type": "number"
|
||||||
},
|
},
|
||||||
|
"price1": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
"price2": {
|
"price2": {
|
||||||
"type": "number"
|
"type": "number"
|
||||||
},
|
},
|
||||||
|
@ -47,7 +50,44 @@
|
||||||
},
|
},
|
||||||
"weight": {
|
"weight": {
|
||||||
"type": "number"
|
"type": "number"
|
||||||
|
},
|
||||||
|
"printedStickers": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"dispatched": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"isIgnored": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"containerFk": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"location": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"minPrice": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"isChecked": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"isPickedOff": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"created": {
|
||||||
|
"type": "date"
|
||||||
|
},
|
||||||
|
"ektFk": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"itemOriginalFk": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"editorFk": {
|
||||||
|
"type": "number"
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
"relations": {
|
"relations": {
|
||||||
"entry": {
|
"entry": {
|
||||||
|
@ -64,6 +104,16 @@
|
||||||
"type": "belongsTo",
|
"type": "belongsTo",
|
||||||
"model": "Packaging",
|
"model": "Packaging",
|
||||||
"foreignKey": "packageFk"
|
"foreignKey": "packageFk"
|
||||||
|
},
|
||||||
|
"worker": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "Worker",
|
||||||
|
"foreignKey": "workerFk"
|
||||||
|
},
|
||||||
|
"delivery": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "Delivery",
|
||||||
|
"foreignKey": "deliveryFk"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,8 @@ module.exports = Self => {
|
||||||
require('../methods/entry/importBuysPreview')(Self);
|
require('../methods/entry/importBuysPreview')(Self);
|
||||||
require('../methods/entry/lastItemBuys')(Self);
|
require('../methods/entry/lastItemBuys')(Self);
|
||||||
require('../methods/entry/entryOrderPdf')(Self);
|
require('../methods/entry/entryOrderPdf')(Self);
|
||||||
|
require('../methods/entry/addFromPackaging')(Self);
|
||||||
|
require('../methods/entry/addFromBuy')(Self);
|
||||||
|
|
||||||
Self.observe('before save', async function(ctx, options) {
|
Self.observe('before save', async function(ctx, options) {
|
||||||
if (ctx.isNewInstance) return;
|
if (ctx.isNewInstance) return;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
name: botanical
|
name: botanical data
|
||||||
columns:
|
columns:
|
||||||
itemFk: item
|
itemFk: item
|
||||||
genusFk: genus
|
genusFk: genus
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
name: botánico
|
name: datos botánicos
|
||||||
columns:
|
columns:
|
||||||
itemFk: artículo
|
itemFk: artículo
|
||||||
genusFk: género
|
genusFk: género
|
||||||
|
|
|
@ -35,7 +35,7 @@ columns:
|
||||||
packingOut: packing out
|
packingOut: packing out
|
||||||
hasMinPrice: has min price
|
hasMinPrice: has min price
|
||||||
isFragile: fragile
|
isFragile: fragile
|
||||||
isFloramondo: is floramondo
|
isFloramondo: floramondo
|
||||||
packingShelve: packing shelve
|
packingShelve: packing shelve
|
||||||
isLaid: laid
|
isLaid: laid
|
||||||
inkFk: ink
|
inkFk: ink
|
||||||
|
|
|
@ -35,7 +35,7 @@ columns:
|
||||||
packingOut: empaquetar
|
packingOut: empaquetar
|
||||||
hasMinPrice: tiene precio mínimo
|
hasMinPrice: tiene precio mínimo
|
||||||
isFragile: frágil
|
isFragile: frágil
|
||||||
isFloramondo: es floramondo
|
isFloramondo: floramondo
|
||||||
packingShelve: estantería embalaje
|
packingShelve: estantería embalaje
|
||||||
isLaid: puesto
|
isLaid: puesto
|
||||||
inkFk: tinta
|
inkFk: tinta
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
ng-model="filter.agencyModeFk">
|
ng-model="filter.agencyModeFk">
|
||||||
</vn-autocomplete>
|
</vn-autocomplete>
|
||||||
<vn-autocomplete vn-one
|
<vn-autocomplete vn-one
|
||||||
url="Agencies"
|
data="agencies"
|
||||||
label="Agency Agreement"
|
label="Agency Agreement"
|
||||||
show-field="name"
|
show-field="name"
|
||||||
value-field="id"
|
value-field="id"
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
name: shelving
|
||||||
|
columns:
|
||||||
|
id: id
|
||||||
|
code: code
|
||||||
|
parkingFk: parking
|
||||||
|
isPrinted: printed
|
||||||
|
priority: priority
|
||||||
|
parked: parked
|
||||||
|
userFk: user
|
||||||
|
isSpam: SPAM
|
||||||
|
isRecyclable: recyclable
|
|
@ -0,0 +1,11 @@
|
||||||
|
name: estantería
|
||||||
|
columns:
|
||||||
|
id: id
|
||||||
|
code: código
|
||||||
|
parkingFk: parking
|
||||||
|
isPrinted: impreso
|
||||||
|
priority: prioridad
|
||||||
|
parked: aparcado
|
||||||
|
userFk: usuario
|
||||||
|
isSpam: SPAM
|
||||||
|
isRecyclable: reciclable
|
|
@ -56,7 +56,7 @@
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"required": false
|
"required": false
|
||||||
},
|
},
|
||||||
"printerFk": {
|
"mainPrinterFk": {
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"required": false
|
"required": false
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethod('getItemsPackaging', {
|
||||||
|
description: 'Returns the list of items from the supplier of type packing',
|
||||||
|
accessType: 'READ',
|
||||||
|
accepts: [{
|
||||||
|
arg: 'id',
|
||||||
|
type: 'number',
|
||||||
|
required: true,
|
||||||
|
description: 'The supplier id',
|
||||||
|
http: {source: 'path'}
|
||||||
|
}, {
|
||||||
|
arg: 'entry',
|
||||||
|
type: 'number',
|
||||||
|
required: true,
|
||||||
|
description: 'The entry id',
|
||||||
|
}],
|
||||||
|
returns: {
|
||||||
|
type: 'object',
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/:id/getItemsPackaging`,
|
||||||
|
verb: 'GET'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Self.getItemsPackaging = async(id, entry) => {
|
||||||
|
return Self.rawSql(`
|
||||||
|
WITH entryTmp AS (
|
||||||
|
SELECT i.id, SUM(b.quantity) quantity
|
||||||
|
FROM vn.entry e
|
||||||
|
JOIN vn.buy b ON b.entryFk = e.id
|
||||||
|
JOIN vn.supplier s ON s.id = e.supplierFk
|
||||||
|
JOIN vn.item i ON i.id = b.itemFk
|
||||||
|
WHERE e.id = ? AND e.supplierFk = ?
|
||||||
|
GROUP BY i.id
|
||||||
|
) SELECT i.id, i.name, et.quantity, SUM(b.quantity) quantityTotal
|
||||||
|
FROM vn.buy b
|
||||||
|
JOIN vn.item i ON i.id = b.itemFk
|
||||||
|
JOIN vn.entry e ON e.id = b.entryFk
|
||||||
|
JOIN vn.supplier s ON s.id = e.supplierFk
|
||||||
|
JOIN vn.buyConfig bc ON bc.monthsAgo
|
||||||
|
JOIN vn.travel t ON t.id = e.travelFk
|
||||||
|
LEFT JOIN entryTmp et ON et.id = i.id
|
||||||
|
WHERE e.supplierFk = ?
|
||||||
|
AND i.family IN ('EMB', 'CONT')
|
||||||
|
AND b.created > (util.VN_CURDATE() - INTERVAL bc.monthsAgo MONTH)
|
||||||
|
GROUP BY b.itemFk
|
||||||
|
ORDER BY et.quantity DESC, quantityTotal DESC`, [entry, id, id]);
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,12 @@
|
||||||
|
const app = require('vn-loopback/server/server');
|
||||||
|
|
||||||
|
describe('Supplier getItemsPackaging()', () => {
|
||||||
|
it('should return a summary of the list of items from a specific supplier', async() => {
|
||||||
|
const [item] = await app.models.Supplier.getItemsPackaging(1, 1);
|
||||||
|
|
||||||
|
expect(item.id).toEqual(1);
|
||||||
|
expect(item.name).toEqual('Ranged weapon longbow 2m');
|
||||||
|
expect(item.quantity).toEqual(5000);
|
||||||
|
expect(item.quantityTotal).toEqual(5100);
|
||||||
|
});
|
||||||
|
});
|
|
@ -11,6 +11,7 @@ module.exports = Self => {
|
||||||
require('../methods/supplier/campaignMetricsPdf')(Self);
|
require('../methods/supplier/campaignMetricsPdf')(Self);
|
||||||
require('../methods/supplier/campaignMetricsEmail')(Self);
|
require('../methods/supplier/campaignMetricsEmail')(Self);
|
||||||
require('../methods/supplier/newSupplier')(Self);
|
require('../methods/supplier/newSupplier')(Self);
|
||||||
|
require('../methods/supplier/getItemsPackaging')(Self);
|
||||||
|
|
||||||
Self.validatesPresenceOf('name', {
|
Self.validatesPresenceOf('name', {
|
||||||
message: 'The social name cannot be empty'
|
message: 'The social name cannot be empty'
|
||||||
|
|
|
@ -12,3 +12,5 @@ columns:
|
||||||
hostFk: PC
|
hostFk: PC
|
||||||
isBox: box
|
isBox: box
|
||||||
itemPackingTypeFk: packing type
|
itemPackingTypeFk: packing type
|
||||||
|
externalId: external id
|
||||||
|
stateTypeFk: status
|
||||||
|
|
|
@ -12,3 +12,5 @@ columns:
|
||||||
hostFk: PC
|
hostFk: PC
|
||||||
isBox: caja
|
isBox: caja
|
||||||
itemPackingTypeFk: tipo empaquetado
|
itemPackingTypeFk: tipo empaquetado
|
||||||
|
externalId: id externo
|
||||||
|
stateTypeFk: estado
|
||||||
|
|
|
@ -14,6 +14,9 @@
|
||||||
"TravelThermograph": {
|
"TravelThermograph": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
"TravelConfig": {
|
||||||
|
"dataSource": "vn"
|
||||||
|
},
|
||||||
"Temperature": {
|
"Temperature": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
{
|
||||||
|
"name": "TravelConfig",
|
||||||
|
"base": "VnModel",
|
||||||
|
"options": {
|
||||||
|
"mysql": {
|
||||||
|
"table": "travelConfig"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "number",
|
||||||
|
"id": true
|
||||||
|
},
|
||||||
|
"warehouseInFk": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"warehouseOutFk": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"agencyFk": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"companyFk": {
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"relations": {
|
||||||
|
"warehouseIn": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "Warehouse",
|
||||||
|
"foreignKey": "warehouseInFk"
|
||||||
|
},
|
||||||
|
"warehouseOut": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "Warehouse",
|
||||||
|
"foreignKey": "warehouseOutFk"
|
||||||
|
},
|
||||||
|
"agency": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "AgencyMode",
|
||||||
|
"foreignKey": "agencyFk"
|
||||||
|
},
|
||||||
|
"company": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "Company",
|
||||||
|
"foreignKey": "companyFk"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,9 +4,20 @@ columns:
|
||||||
companyCodeFk: company
|
companyCodeFk: company
|
||||||
started: started
|
started: started
|
||||||
ended: ended
|
ended: ended
|
||||||
|
workerBusiness: business
|
||||||
|
reasonEndFk: ending reason
|
||||||
payedHolidays: payed holidays
|
payedHolidays: payed holidays
|
||||||
|
occupationCodeFk: occupation
|
||||||
workerFk: worker
|
workerFk: worker
|
||||||
|
notes: notes
|
||||||
|
departmentFk: department
|
||||||
|
workerBusinessProfessionalCategoryFk: professional category
|
||||||
calendarTypeFk: calendar type
|
calendarTypeFk: calendar type
|
||||||
isHourlyLabor: hourly labor
|
isHourlyLabor: hourly labor
|
||||||
workcenterFk: workcenter
|
workcenterFk: workcenter
|
||||||
|
rate: rate
|
||||||
|
workerBusinessCategoryFk: category
|
||||||
|
workerBusinessTypeFk: type
|
||||||
amount: amount
|
amount: amount
|
||||||
|
workerBusinessAgreementFk: agreement
|
||||||
|
basicSalary: salary
|
||||||
|
|
|
@ -4,9 +4,20 @@ columns:
|
||||||
companyCodeFk: empresa
|
companyCodeFk: empresa
|
||||||
started: iniciado
|
started: iniciado
|
||||||
ended: finalizado
|
ended: finalizado
|
||||||
|
workerBusiness: negocio
|
||||||
|
reasonEndFk: motivo finalización
|
||||||
payedHolidays: vacaciones pagadas
|
payedHolidays: vacaciones pagadas
|
||||||
|
occupationCodeFk: ocupación
|
||||||
workerFk: trabajador
|
workerFk: trabajador
|
||||||
|
notes: notas
|
||||||
|
departmentFk: departamento
|
||||||
|
workerBusinessProfessionalCategoryFk: categoría profesional
|
||||||
calendarTypeFk: tipo calendario
|
calendarTypeFk: tipo calendario
|
||||||
isHourlyLabor: horario laboral
|
isHourlyLabor: horario laboral
|
||||||
workcenterFk: centro de trabajo
|
workcenterFk: centro de trabajo
|
||||||
|
rate: tarifa
|
||||||
|
workerBusinessCategoryFk: categoría
|
||||||
|
workerBusinessTypeFk: tipo
|
||||||
amount: salario
|
amount: salario
|
||||||
|
workerBusinessAgreementFk: acuerdo
|
||||||
|
basicSalary: salario base
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
name: document
|
name: document
|
||||||
columns:
|
columns:
|
||||||
id: id
|
id: id
|
||||||
dmsFk: dms
|
worker: worker
|
||||||
workerFk: worker
|
document: document
|
||||||
isReadableByWorker: readable by worker
|
isReadableByWorker: readable by worker
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
name: documento
|
name: documento
|
||||||
columns:
|
columns:
|
||||||
id: id
|
id: id
|
||||||
dmsFk: dms
|
worker: trabajador
|
||||||
workerFk: trabajador
|
document: documento
|
||||||
isReadableByWorker: legible por trabajador
|
isReadableByWorker: accesible por trabajador
|
||||||
|
|
|
@ -1,20 +1,32 @@
|
||||||
name: worker
|
name: worker
|
||||||
columns:
|
columns:
|
||||||
id: id
|
id: id
|
||||||
|
code: code
|
||||||
firstName: first name
|
firstName: first name
|
||||||
lastName: last name
|
lastName: last name
|
||||||
|
sub: buyer number
|
||||||
|
photo: photo
|
||||||
phone: phone
|
phone: phone
|
||||||
|
mobileExtension: mobile extension
|
||||||
userFk: user
|
userFk: user
|
||||||
bossFk: boss
|
bossFk: boss
|
||||||
|
fiDueDate: FI due date
|
||||||
|
hasMachineryAuthorized: machinery authorized
|
||||||
|
seniority: seniority
|
||||||
|
isTodayRelative: today relative
|
||||||
|
isF11Allowed: F11 allowed
|
||||||
|
sectorFk: sector
|
||||||
maritalStatus: marital status
|
maritalStatus: marital status
|
||||||
|
labelerFk: labeler
|
||||||
originCountryFk: origin country
|
originCountryFk: origin country
|
||||||
educationLevelFk: education level
|
educationLevelFk: education level
|
||||||
SSN: SSN
|
SSN: SSN
|
||||||
labelerFk: labeler
|
fi: fiscal identifier
|
||||||
mobileExtension: mobile extension
|
birth: birth date
|
||||||
code: code
|
isDisable: disabled
|
||||||
|
isFreelance: freelance
|
||||||
|
isSsDiscounted: SS discounted
|
||||||
|
sex: sex
|
||||||
|
businessFk: current contract
|
||||||
|
balance: balance
|
||||||
locker: locker
|
locker: locker
|
||||||
workerFk: worker
|
|
||||||
sectorFk: sector
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,32 @@
|
||||||
name: trabajador
|
name: trabajador
|
||||||
columns:
|
columns:
|
||||||
id: id
|
id: id
|
||||||
|
code: código
|
||||||
firstName: nombre
|
firstName: nombre
|
||||||
lastName: apellido
|
lastName: apellido
|
||||||
|
sub: número comprador
|
||||||
|
photo: foto
|
||||||
phone: teléfono
|
phone: teléfono
|
||||||
|
mobileExtension: extensión móvil
|
||||||
userFk: usuario
|
userFk: usuario
|
||||||
bossFk: jefe
|
bossFk: jefe
|
||||||
|
fiDueDate: caducidad DNI
|
||||||
|
hasMachineryAuthorized: maquinaria autorizada
|
||||||
|
seniority: antigüedad
|
||||||
|
isTodayRelative: relativo hoy
|
||||||
|
isF11Allowed: F11 autorizado
|
||||||
|
sectorFk: sector
|
||||||
maritalStatus: estado civil
|
maritalStatus: estado civil
|
||||||
|
labelerFk: etiquetadora
|
||||||
originCountryFk: país origen
|
originCountryFk: país origen
|
||||||
educationLevelFk: nivel educativo
|
educationLevelFk: nivel educativo
|
||||||
SSN: SSN
|
SSN: SSN
|
||||||
labelerFk: etiquetadora
|
fi: identificador fiscal
|
||||||
mobileExtension: extensión móvil
|
birth: nacimiento
|
||||||
code: código
|
isDisable: deshabilitado
|
||||||
locker: casillero
|
isFreelance: autónomo
|
||||||
workerFk: trabajador
|
isSsDiscounted: descuento SS
|
||||||
sectorFk: sector
|
sex: sexo
|
||||||
|
businessFk: contrato actual
|
||||||
|
balance: saldo
|
||||||
|
locker: taquilla
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
|
@ -230,21 +230,21 @@ module.exports = Self => {
|
||||||
}, myOptions);
|
}, myOptions);
|
||||||
} else {
|
} else {
|
||||||
const weekDay = day.dated.getDay();
|
const weekDay = day.dated.getDay();
|
||||||
const journeys = await models.Journey.find({
|
const journeys = await models.BusinessSchedule.find({
|
||||||
where: {
|
where: {
|
||||||
business_id: day.businessFk,
|
businessFk: day.businessFk,
|
||||||
day_id: weekDay
|
weekday: weekDay
|
||||||
}
|
}
|
||||||
}, myOptions);
|
}, myOptions);
|
||||||
|
|
||||||
let timeTableDecimalInSeconds = 0;
|
let timeTableDecimalInSeconds = 0;
|
||||||
for (let journey of journeys) {
|
for (let journey of journeys) {
|
||||||
const start = Date.vnNew();
|
const start = Date.vnNew();
|
||||||
const [startHours, startMinutes, startSeconds] = getTime(journey.start);
|
const [startHours, startMinutes, startSeconds] = getTime(journey.started);
|
||||||
start.setHours(startHours, startMinutes, startSeconds, 0);
|
start.setHours(startHours, startMinutes, startSeconds, 0);
|
||||||
|
|
||||||
const end = Date.vnNew();
|
const end = Date.vnNew();
|
||||||
const [endHours, endMinutes, endSeconds] = getTime(journey.end);
|
const [endHours, endMinutes, endSeconds] = getTime(journey.ended);
|
||||||
end.setHours(endHours, endMinutes, endSeconds, 0);
|
end.setHours(endHours, endMinutes, endSeconds, 0);
|
||||||
|
|
||||||
const result = (end - start) / 1000;
|
const result = (end - start) / 1000;
|
||||||
|
@ -255,7 +255,7 @@ module.exports = Self => {
|
||||||
const timeTableDecimal = timeTableDecimalInSeconds / 3600;
|
const timeTableDecimal = timeTableDecimalInSeconds / 3600;
|
||||||
if (day.timeWorkDecimal == timeTableDecimal) {
|
if (day.timeWorkDecimal == timeTableDecimal) {
|
||||||
const timed = new Date(day.dated);
|
const timed = new Date(day.dated);
|
||||||
const [startHours, startMinutes, startSeconds] = getTime(journey.start);
|
const [startHours, startMinutes, startSeconds] = getTime(journey.started);
|
||||||
await models.WorkerTimeControl.create({
|
await models.WorkerTimeControl.create({
|
||||||
userFk: day.workerFk,
|
userFk: day.workerFk,
|
||||||
timed: timed.setHours(startHours, startMinutes, startSeconds),
|
timed: timed.setHours(startHours, startMinutes, startSeconds),
|
||||||
|
@ -263,7 +263,7 @@ module.exports = Self => {
|
||||||
isSendMail: true
|
isSendMail: true
|
||||||
}, myOptions);
|
}, myOptions);
|
||||||
|
|
||||||
const [endHours, endMinutes, endSeconds] = getTime(journey.end);
|
const [endHours, endMinutes, endSeconds] = getTime(journey.ended);
|
||||||
await models.WorkerTimeControl.create({
|
await models.WorkerTimeControl.create({
|
||||||
userFk: day.workerFk,
|
userFk: day.workerFk,
|
||||||
timed: timed.setHours(endHours, endMinutes, endSeconds),
|
timed: timed.setHours(endHours, endMinutes, endSeconds),
|
||||||
|
@ -276,7 +276,7 @@ module.exports = Self => {
|
||||||
});
|
});
|
||||||
if (journey == minStart) {
|
if (journey == minStart) {
|
||||||
const timed = new Date(day.dated);
|
const timed = new Date(day.dated);
|
||||||
const [startHours, startMinutes, startSeconds] = getTime(journey.start);
|
const [startHours, startMinutes, startSeconds] = getTime(journey.started);
|
||||||
await models.WorkerTimeControl.create({
|
await models.WorkerTimeControl.create({
|
||||||
userFk: day.workerFk,
|
userFk: day.workerFk,
|
||||||
timed: timed.setHours(startHours, startMinutes, startSeconds),
|
timed: timed.setHours(startHours, startMinutes, startSeconds),
|
||||||
|
@ -304,7 +304,7 @@ module.exports = Self => {
|
||||||
});
|
});
|
||||||
if (journey == minStart) {
|
if (journey == minStart) {
|
||||||
const timed = new Date(day.dated);
|
const timed = new Date(day.dated);
|
||||||
const [startHours, startMinutes, startSeconds] = getTime(journey.start);
|
const [startHours, startMinutes, startSeconds] = getTime(journey.started);
|
||||||
await models.WorkerTimeControl.create({
|
await models.WorkerTimeControl.create({
|
||||||
userFk: day.workerFk,
|
userFk: day.workerFk,
|
||||||
timed: timed.setHours(startHours + 1, startMinutes, startSeconds),
|
timed: timed.setHours(startHours + 1, startMinutes, startSeconds),
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
"AbsenceType": {
|
"AbsenceType": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
"BusinessSchedule": {
|
||||||
|
"dataSource": "vn"
|
||||||
|
},
|
||||||
"Calendar": {
|
"Calendar": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
@ -38,9 +41,6 @@
|
||||||
"EducationLevel": {
|
"EducationLevel": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
"Journey": {
|
|
||||||
"dataSource": "vn"
|
|
||||||
},
|
|
||||||
"ProfileType":{
|
"ProfileType":{
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,26 +1,26 @@
|
||||||
{
|
{
|
||||||
"name": "Journey",
|
"name": "BusinessSchedule",
|
||||||
"base": "VnModel",
|
"base": "VnModel",
|
||||||
"options": {
|
"options": {
|
||||||
"mysql": {
|
"mysql": {
|
||||||
"table": "postgresql.journey"
|
"table": "businessSchedule"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"properties": {
|
"properties": {
|
||||||
"journey_id": {
|
"id": {
|
||||||
"id": true,
|
"id": true,
|
||||||
"type": "number"
|
"type": "number"
|
||||||
},
|
},
|
||||||
"day_id": {
|
"weekday": {
|
||||||
"type": "number"
|
"type": "number"
|
||||||
},
|
},
|
||||||
"start": {
|
"started": {
|
||||||
"type": "date"
|
"type": "date"
|
||||||
},
|
},
|
||||||
"end": {
|
"ended": {
|
||||||
"type": "date"
|
"type": "date"
|
||||||
},
|
},
|
||||||
"business_id": {
|
"businessFk": {
|
||||||
"type": "number"
|
"type": "number"
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
|
@ -27,10 +27,10 @@
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"required": true
|
"required": true
|
||||||
},
|
},
|
||||||
"sectorFk ": {
|
"sectorFk": {
|
||||||
"type": "number"
|
"type": "number"
|
||||||
},
|
},
|
||||||
"labelerFk ": {
|
"labelerFk": {
|
||||||
"type": "number"
|
"type": "number"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
<vn-autocomplete vn-one
|
<vn-autocomplete vn-one
|
||||||
label="Warehouse"
|
label="Warehouse"
|
||||||
ng-model="$ctrl.dms.warehouseId"
|
ng-model="$ctrl.dms.warehouseId"
|
||||||
url="Warehouses"
|
data="warehouses"
|
||||||
show-field="name"
|
show-field="name"
|
||||||
value-field="id">
|
value-field="id">
|
||||||
</vn-autocomplete>
|
</vn-autocomplete>
|
||||||
|
|
|
@ -72,7 +72,7 @@
|
||||||
"state": "worker.card.workerLog",
|
"state": "worker.card.workerLog",
|
||||||
"component": "vn-worker-log",
|
"component": "vn-worker-log",
|
||||||
"description": "Log",
|
"description": "Log",
|
||||||
"acl": ["salesAssistant"]
|
"acl": ["hr"]
|
||||||
}, {
|
}, {
|
||||||
"url": "/note",
|
"url": "/note",
|
||||||
"state": "worker.card.note",
|
"state": "worker.card.note",
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
34
package.json
34
package.json
|
@ -9,7 +9,7 @@
|
||||||
"url": "https://gitea.verdnatura.es/verdnatura/salix"
|
"url": "https://gitea.verdnatura.es/verdnatura/salix"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14"
|
"node": ">=20"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.2.2",
|
"axios": "^1.2.2",
|
||||||
|
@ -33,19 +33,20 @@
|
||||||
"loopback-boot": "3.3.1",
|
"loopback-boot": "3.3.1",
|
||||||
"loopback-component-explorer": "^6.5.0",
|
"loopback-component-explorer": "^6.5.0",
|
||||||
"loopback-component-storage": "3.6.1",
|
"loopback-component-storage": "3.6.1",
|
||||||
"loopback-connector-mysql": "^5.4.3",
|
"loopback-connector-mysql": "^6.2.0",
|
||||||
"loopback-connector-remote": "^3.4.1",
|
"loopback-connector-remote": "^3.4.1",
|
||||||
"loopback-context": "^3.4.0",
|
"loopback-context": "^3.5.2",
|
||||||
"mailparser": "^2.8.0",
|
"mailparser": "^2.8.0",
|
||||||
"md5": "^2.2.1",
|
"md5": "^2.2.1",
|
||||||
"node-ssh": "^11.0.0",
|
"node-ssh": "^11.0.0",
|
||||||
"object-diff": "0.0.4",
|
"object-diff": "0.0.4",
|
||||||
"object.pick": "^1.3.0",
|
"object.pick": "^1.3.0",
|
||||||
"puppeteer": "^18.0.5",
|
"puppeteer": "^20.3.0",
|
||||||
"read-chunk": "^3.2.0",
|
"read-chunk": "^3.2.0",
|
||||||
"require-yaml": "0.0.1",
|
"require-yaml": "0.0.1",
|
||||||
"smbhash": "0.0.1",
|
"smbhash": "0.0.1",
|
||||||
"strong-error-handler": "^2.3.2",
|
"strong-error-handler": "^2.3.2",
|
||||||
|
"url-loader": "^4.1.1",
|
||||||
"uuid": "^3.3.3",
|
"uuid": "^3.3.3",
|
||||||
"vn-loopback": "file:./loopback",
|
"vn-loopback": "file:./loopback",
|
||||||
"vn-print": "file:./print",
|
"vn-print": "file:./print",
|
||||||
|
@ -58,15 +59,15 @@
|
||||||
"@babel/register": "^7.7.7",
|
"@babel/register": "^7.7.7",
|
||||||
"angular-mocks": "^1.7.9",
|
"angular-mocks": "^1.7.9",
|
||||||
"babel-jest": "^26.0.1",
|
"babel-jest": "^26.0.1",
|
||||||
"babel-loader": "^8.0.6",
|
"babel-loader": "^8.2.4",
|
||||||
"core-js": "^3.9.1",
|
"core-js": "^3.30.1",
|
||||||
"css-loader": "^2.1.0",
|
"css-loader": "^6.7.4",
|
||||||
"del": "^2.2.2",
|
"del": "^2.2.2",
|
||||||
"eslint": "^7.11.0",
|
"eslint": "^7.11.0",
|
||||||
"eslint-config-google": "^0.11.0",
|
"eslint-config-google": "^0.11.0",
|
||||||
"eslint-plugin-jasmine": "^2.10.1",
|
"eslint-plugin-jasmine": "^2.10.1",
|
||||||
"fancy-log": "^1.3.2",
|
"fancy-log": "^1.3.2",
|
||||||
"file-loader": "^1.1.11",
|
"file-loader": "^6.2.0",
|
||||||
"gulp": "^4.0.2",
|
"gulp": "^4.0.2",
|
||||||
"gulp-concat": "^2.6.1",
|
"gulp-concat": "^2.6.1",
|
||||||
"gulp-env": "^0.4.0",
|
"gulp-env": "^0.4.0",
|
||||||
|
@ -79,9 +80,9 @@
|
||||||
"gulp-yaml": "^1.0.1",
|
"gulp-yaml": "^1.0.1",
|
||||||
"html-loader": "^0.4.5",
|
"html-loader": "^0.4.5",
|
||||||
"html-loader-jest": "^0.2.1",
|
"html-loader-jest": "^0.2.1",
|
||||||
"html-webpack-plugin": "^4.0.0-beta.11",
|
"html-webpack-plugin": "^5.5.1",
|
||||||
"identity-obj-proxy": "^3.0.0",
|
"identity-obj-proxy": "^3.0.0",
|
||||||
"jasmine": "^4.5.0",
|
"jasmine": "^5.0.0",
|
||||||
"jasmine-reporters": "^2.4.0",
|
"jasmine-reporters": "^2.4.0",
|
||||||
"jasmine-spec-reporter": "^7.0.0",
|
"jasmine-spec-reporter": "^7.0.0",
|
||||||
"jest": "^26.0.1",
|
"jest": "^26.0.1",
|
||||||
|
@ -90,15 +91,16 @@
|
||||||
"merge-stream": "^1.0.1",
|
"merge-stream": "^1.0.1",
|
||||||
"minimist": "^1.2.5",
|
"minimist": "^1.2.5",
|
||||||
"mysql2": "^1.7.0",
|
"mysql2": "^1.7.0",
|
||||||
"node-sass": "^4.14.1",
|
"node-sass": "^9.0.0",
|
||||||
"nodemon": "^2.0.16",
|
"nodemon": "^2.0.16",
|
||||||
"plugin-error": "^1.0.1",
|
"plugin-error": "^1.0.1",
|
||||||
"raw-loader": "^1.0.0",
|
"raw-loader": "^4.0.2",
|
||||||
"regenerator-runtime": "^0.13.7",
|
"regenerator-runtime": "^0.13.7",
|
||||||
"sass-loader": "^7.3.1",
|
"sass": "^1.62.1",
|
||||||
"style-loader": "^0.23.1",
|
"sass-loader": "^13.3.0",
|
||||||
"webpack": "^4.41.5",
|
"style-loader": "^3.3.3",
|
||||||
"webpack-cli": "^3.3.10",
|
"webpack": "^5.83.1",
|
||||||
|
"webpack-cli": "^5.1.1",
|
||||||
"webpack-dev-server": "^3.11.0",
|
"webpack-dev-server": "^3.11.0",
|
||||||
"webpack-merge": "^4.2.2",
|
"webpack-merge": "^4.2.2",
|
||||||
"yaml-loader": "^0.5.0"
|
"yaml-loader": "^0.5.0"
|
||||||
|
|
|
@ -9,7 +9,7 @@ module.exports = {
|
||||||
concurrency: Cluster.CONCURRENCY_CONTEXT,
|
concurrency: Cluster.CONCURRENCY_CONTEXT,
|
||||||
maxConcurrency: cpus().length,
|
maxConcurrency: cpus().length,
|
||||||
puppeteerOptions: {
|
puppeteerOptions: {
|
||||||
headless: true,
|
headless: 'new',
|
||||||
args: [
|
args: [
|
||||||
'--no-sandbox',
|
'--no-sandbox',
|
||||||
'--disable-setuid-sandbox',
|
'--disable-setuid-sandbox',
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
"name": "vn-print",
|
"name": "vn-print",
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"description": "Print service",
|
"description": "Print service",
|
||||||
"main": "server/server.js",
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node server/server.js",
|
"start": "node server/server.js",
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
|
|
@ -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();
|
|
@ -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}.'
|
|
@ -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}.'
|
|
@ -0,0 +1,8 @@
|
||||||
|
<email-body v-bind="$props">
|
||||||
|
<div class="grid-row">
|
||||||
|
<div class="grid-block vn-pa-ml">
|
||||||
|
<h1>{{ $t('title') }}</h1>
|
||||||
|
<p v-html="$t('description', [labeler.id, labeler.name, sector.id, sector.description, mainPrinter.id, mainPrinter.name, worker.nickname])"></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</email-body>
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,3 @@
|
||||||
|
SELECT id, name
|
||||||
|
FROM vn.printer
|
||||||
|
WHERE id = ?
|
|
@ -0,0 +1,3 @@
|
||||||
|
SELECT id, description, mainPrinterFk
|
||||||
|
FROM vn.sector
|
||||||
|
WHERE id = ?
|
|
@ -0,0 +1,3 @@
|
||||||
|
SELECT nickname
|
||||||
|
FROM account.user
|
||||||
|
WHERE id = ?
|
|
@ -20,13 +20,13 @@ let baseConfig = {
|
||||||
test: /\.js$/,
|
test: /\.js$/,
|
||||||
loader: 'babel-loader',
|
loader: 'babel-loader',
|
||||||
exclude: /node_modules/,
|
exclude: /node_modules/,
|
||||||
query: {
|
options: {
|
||||||
presets: ['@babel/preset-env'],
|
presets: ['@babel/preset-env'],
|
||||||
plugins: ['@babel/plugin-syntax-dynamic-import']
|
plugins: ['@babel/plugin-syntax-dynamic-import']
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
test: /\.yml$/,
|
test: /\.yml$/,
|
||||||
loader: 'json-loader!yaml-loader'
|
use: ['json-loader!yaml-loader']
|
||||||
}, {
|
}, {
|
||||||
test: /\.html$/,
|
test: /\.html$/,
|
||||||
loader: 'html-loader',
|
loader: 'html-loader',
|
||||||
|
@ -38,39 +38,34 @@ let baseConfig = {
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
test: /\.css$/,
|
test: /\.css$/,
|
||||||
use: [
|
use: ['style-loader', 'css-loader']
|
||||||
{
|
|
||||||
loader: 'style-loader'
|
|
||||||
}, {
|
|
||||||
loader: 'css-loader'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}, {
|
}, {
|
||||||
test: /\.scss$/,
|
test: /\.scss$/,
|
||||||
use: [
|
use: [
|
||||||
{
|
'style-loader', 'css-loader', {
|
||||||
loader: 'style-loader'
|
|
||||||
}, {
|
|
||||||
loader: 'css-loader'
|
|
||||||
}, {
|
|
||||||
loader: 'sass-loader',
|
loader: 'sass-loader',
|
||||||
options: {
|
options: {
|
||||||
// XXX: Don't work in Firefox
|
// XXX: Don't work in Firefox
|
||||||
// https://github.com/webpack-contrib/style-loader/issues/303
|
// https://github.com/webpack-contrib/style-loader/issues/303
|
||||||
// sourceMap: true,
|
// sourceMap: true,
|
||||||
includePaths: [
|
sassOptions: {
|
||||||
path.resolve(__dirname, 'front/core/styles')
|
includePaths: [
|
||||||
]
|
path.resolve(__dirname, 'front/core/styles/')
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}, {
|
}, {
|
||||||
test: /\.(svg|png|ttf|woff|woff2)$/,
|
test: /\.(woff(2)?|ttf|eot|svg|png)(\?v=\d+\.\d+\.\d+)?$/,
|
||||||
loader: 'file-loader'
|
type: 'asset/resource',
|
||||||
}, {
|
}, {
|
||||||
test: /manifest\.json$/,
|
test: /manifest\.json$/,
|
||||||
type: 'javascript/auto',
|
type: 'javascript/auto',
|
||||||
loader: 'file-loader'
|
loader: 'file-loader',
|
||||||
|
options: {
|
||||||
|
esModule: false,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -105,7 +100,7 @@ let baseConfig = {
|
||||||
chunks: ['salix']
|
chunks: ['salix']
|
||||||
}),
|
}),
|
||||||
new webpack.DefinePlugin({
|
new webpack.DefinePlugin({
|
||||||
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
|
'process.env.NODE_ENV': JSON.stringify(env)
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
devtool: 'source-map',
|
devtool: 'source-map',
|
||||||
|
@ -124,7 +119,7 @@ let prodConfig = {
|
||||||
chunkFilename: '[id].[chunkhash].js'
|
chunkFilename: '[id].[chunkhash].js'
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
new webpack.HashedModuleIdsPlugin()
|
new webpack.ids.HashedModuleIdsPlugin()
|
||||||
],
|
],
|
||||||
performance: {
|
performance: {
|
||||||
maxEntrypointSize: 2000000,
|
maxEntrypointSize: 2000000,
|
||||||
|
|
Loading…
Reference in New Issue