diff --git a/back/methods/chat/sendCheckingPresence.js b/back/methods/chat/sendCheckingPresence.js
index 3bc022429..075591969 100644
--- a/back/methods/chat/sendCheckingPresence.js
+++ b/back/methods/chat/sendCheckingPresence.js
@@ -43,6 +43,9 @@ module.exports = Self => {
if (!recipient)
throw new Error(`Could not send message "${message}" to worker id ${recipientId} from user ${userId}`);
+ if (process.env.NODE_ENV == 'test')
+ message = `[Test:Environment to user ${userId}] ` + message;
+
await models.Chat.create({
senderFk: sender.id,
recipient: `@${recipient.name}`,
diff --git a/db/changes/224702/00-notificationProc.sql b/db/changes/224702/00-notificationProc.sql
index 475b2e389..2cf11b4f1 100644
--- a/db/changes/224702/00-notificationProc.sql
+++ b/db/changes/224702/00-notificationProc.sql
@@ -12,14 +12,9 @@ BEGIN
* @param vAuthorFk The notification author or %NULL if there is no author
* @return The notification id
*/
- DECLARE vNotificationFk INT;
-
- SELECT id INTO vNotificationFk
- FROM `notification`
- WHERE `name` = vNotificationName;
INSERT INTO notificationQueue
- SET notificationFk = vNotificationFk,
+ SET notificationFk = vNotificationName,
params = vParams,
authorFk = vAuthorFk;
diff --git a/db/changes/225001/.gitkeep b/db/changes/225001/.gitkeep
new file mode 100644
index 000000000..e69de29bb
diff --git a/db/changes/225001/00-entryDeleteRef.sql b/db/changes/225201/00-entryDeleteRef.sql
similarity index 100%
rename from db/changes/225001/00-entryDeleteRef.sql
rename to db/changes/225201/00-entryDeleteRef.sql
diff --git a/db/changes/225201/00-invoiceInConfig.sql b/db/changes/225201/00-invoiceInConfig.sql
new file mode 100644
index 000000000..a27b59440
--- /dev/null
+++ b/db/changes/225201/00-invoiceInConfig.sql
@@ -0,0 +1,12 @@
+CREATE TABLE `vn`.`invoiceInConfig` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `retentionRate` int(3) NOT NULL,
+ `retentionName` varchar(25) NOT NULL,
+ `sageWithholdingFk` smallint(6) NOT NULL,
+ PRIMARY KEY (`id`),
+ CONSTRAINT `invoiceInConfig_sageWithholdingFk` FOREIGN KEY (`sageWithholdingFk`) REFERENCES `sage`.`TiposRetencion`(`CodigoRetencion`) ON DELETE CASCADE ON UPDATE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
+
+INSERT INTO `vn`.`invoiceInConfig` (`id`, `retentionRate`, `retentionName`, `sageWithholdingFk`)
+ VALUES
+ (1, -2, 'Retención 2%', 2);
diff --git a/db/changes/225201/00-supplier_beforeUpdate.sql b/db/changes/225201/00-supplier_beforeUpdate.sql
new file mode 100644
index 000000000..08af8666b
--- /dev/null
+++ b/db/changes/225201/00-supplier_beforeUpdate.sql
@@ -0,0 +1,46 @@
+DROP TRIGGER IF EXISTS `vn`.`supplier_beforeUpdate`;
+USE `vn`;
+
+DELIMITER $$
+$$
+CREATE DEFINER=`root`@`localhost` TRIGGER `vn`.`supplier_beforeUpdate`
+ BEFORE UPDATE ON `supplier`
+ FOR EACH ROW
+BEGIN
+ DECLARE vHasChange BOOL;
+ DECLARE vPayMethodChanged BOOL;
+ DECLARE vPayMethodHasVerified BOOL;
+ DECLARE vParams JSON;
+ DECLARE vOldPayMethodName VARCHAR(20);
+ DECLARE vNewPayMethodName VARCHAR(20);
+
+ SELECT hasVerified INTO vPayMethodHasVerified
+ FROM payMethod
+ WHERE id = NEW.payMethodFk;
+
+ SET vPayMethodChanged = NOT(NEW.payMethodFk <=> OLD.payMethodFk);
+
+ IF vPayMethodChanged THEN
+ SELECT name INTO vOldPayMethodName
+ FROM payMethod
+ WHERE id = OLD.payMethodFk;
+ SELECT name INTO vNewPayMethodName
+ FROM payMethod
+ WHERE id = NEW.payMethodFk;
+
+ SET vParams = JSON_OBJECT(
+ 'name', NEW.name,
+ 'oldPayMethod', vOldPayMethodName,
+ 'newPayMethod', vNewPayMethodName
+ );
+ SELECT util.notification_send('supplier-pay-method-update', vParams, NULL) INTO @id;
+ END IF;
+
+ SET vHasChange = NOT(NEW.payDemFk <=> OLD.payDemFk AND NEW.payDay <=> OLD.payDay) OR vPayMethodChanged;
+
+ IF vHasChange AND vPayMethodHasVerified THEN
+ SET NEW.isPayMethodChecked = FALSE;
+ END IF;
+
+END$$
+DELIMITER ;
diff --git a/db/changes/225201/00-ticket_canbePostponed.sql b/db/changes/225201/00-ticket_canbePostponed.sql
new file mode 100644
index 000000000..572824b4b
--- /dev/null
+++ b/db/changes/225201/00-ticket_canbePostponed.sql
@@ -0,0 +1,73 @@
+DROP PROCEDURE IF EXISTS `vn`.`ticket_canbePostponed`;
+
+DELIMITER $$
+$$
+CREATE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticket_canbePostponed`(vOriginDated DATE, vFutureDated DATE, vWarehouseFk INT)
+BEGIN
+/**
+ * Devuelve un listado de tickets susceptibles de fusionarse con otros tickets en el futuro
+ *
+ * @param vOriginDated Fecha en cuestión
+ * @param vFutureDated Fecha en el futuro a sondear
+ * @param vWarehouseFk Identificador de vn.warehouse
+ */
+ DROP TEMPORARY TABLE IF EXISTS tmp.filter;
+ CREATE TEMPORARY TABLE tmp.filter
+ (INDEX (id))
+ SELECT sv.ticketFk id,
+ sub2.id futureId,
+ GROUP_CONCAT(DISTINCT i.itemPackingTypeFk ORDER BY i.itemPackingTypeFk) ipt,
+ CAST(sum(litros) AS DECIMAL(10,0)) liters,
+ CAST(count(*) AS DECIMAL(10,0)) `lines`,
+ st.name state,
+ sub2.iptd futureIpt,
+ sub2.state futureState,
+ t.clientFk,
+ t.warehouseFk,
+ ts.alertLevel,
+ t.shipped,
+ sub2.shipped futureShipped,
+ t.workerFk,
+ st.code stateCode,
+ sub2.code futureStateCode
+ FROM vn.saleVolume sv
+ JOIN vn.sale s ON s.id = sv.saleFk
+ JOIN vn.item i ON i.id = s.itemFk
+ JOIN vn.ticket t ON t.id = sv.ticketFk
+ JOIN vn.address a ON a.id = t.addressFk
+ JOIN vn.province p ON p.id = a.provinceFk
+ JOIN vn.country c ON c.id = p.countryFk
+ JOIN vn.ticketState ts ON ts.ticketFk = t.id
+ JOIN vn.state st ON st.id = ts.stateFk
+ JOIN vn.alertLevel al ON al.id = ts.alertLevel
+ LEFT JOIN vn.ticketParking tp ON tp.ticketFk = t.id
+ LEFT JOIN (
+ SELECT *
+ FROM (
+ SELECT
+ t.addressFk,
+ t.id,
+ t.shipped,
+ st.name state,
+ st.code code,
+ GROUP_CONCAT(DISTINCT i.itemPackingTypeFk ORDER BY i.itemPackingTypeFk) iptd
+ FROM vn.ticket t
+ JOIN vn.ticketState ts ON ts.ticketFk = t.id
+ JOIN vn.state st ON st.id = ts.stateFk
+ JOIN vn.sale s ON s.ticketFk = t.id
+ JOIN vn.item i ON i.id = s.itemFk
+ WHERE t.shipped BETWEEN vFutureDated
+ AND util.dayend(vFutureDated)
+ AND t.warehouseFk = vWarehouseFk
+ GROUP BY t.id
+ ) sub
+ GROUP BY sub.addressFk
+ ) sub2 ON sub2.addressFk = t.addressFk AND t.id != sub2.id
+ WHERE t.shipped BETWEEN vOriginDated AND util.dayend(vOriginDated)
+ AND t.warehouseFk = vWarehouseFk
+ AND al.code = 'FREE'
+ AND tp.ticketFk IS NULL
+ GROUP BY sv.ticketFk
+ HAVING futureId;
+END$$
+DELIMITER ;
diff --git a/db/changes/225001/01-modules.sql b/db/changes/225201/01-modules.sql
similarity index 100%
rename from db/changes/225001/01-modules.sql
rename to db/changes/225201/01-modules.sql
diff --git a/db/changes/225001/02-starredModule.sql b/db/changes/225201/02-starredModule.sql
similarity index 100%
rename from db/changes/225001/02-starredModule.sql
rename to db/changes/225201/02-starredModule.sql
diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql
index bd291cbab..14f858ac8 100644
--- a/db/dump/fixtures.sql
+++ b/db/dump/fixtures.sql
@@ -2689,7 +2689,8 @@ INSERT INTO `util`.`notificationConfig`
INSERT INTO `util`.`notification` (`id`, `name`, `description`)
VALUES
- (1, 'print-email', 'notification fixture one');
+ (1, 'print-email', 'notification fixture one'),
+ (3, 'supplier-pay-method-update', 'A supplier pay method has been updated');
INSERT INTO `util`.`notificationAcl` (`notificationFk`, `roleFk`)
VALUES
@@ -2746,3 +2747,4 @@ INSERT INTO `salix`.`url` (`appName`, `environment`, `url`)
INSERT INTO `vn`.`payDemDetail` (`id`, `detail`)
VALUES
(1, 1);
+
diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js
index f550e3a9d..dba94dd22 100644
--- a/e2e/helpers/selectors.js
+++ b/e2e/helpers/selectors.js
@@ -735,18 +735,16 @@ export default {
},
ticketFuture: {
openAdvancedSearchButton: 'vn-searchbar .append vn-icon[icon="arrow_drop_down"]',
- originDated: 'vn-date-picker[label="Origin ETD"]',
- futureDated: 'vn-date-picker[label="Destination ETD"]',
- shipped: 'vn-date-picker[label="Origin date"]',
- tfShipped: 'vn-date-picker[label="Destination date"]',
+ originDated: 'vn-date-picker[label="Origin date"]',
+ futureDated: 'vn-date-picker[label="Destination date"]',
linesMax: 'vn-textfield[label="Max Lines"]',
litersMax: 'vn-textfield[label="Max Liters"]',
ipt: 'vn-autocomplete[label="Origin IPT"]',
- tfIpt: 'vn-autocomplete[label="Destination IPT"]',
+ futureIpt: 'vn-autocomplete[label="Destination IPT"]',
tableIpt: 'vn-autocomplete[name="ipt"]',
- tableTfIpt: 'vn-autocomplete[name="tfIpt"]',
+ tableFutureIpt: 'vn-autocomplete[name="futureIpt"]',
state: 'vn-autocomplete[label="Origin Grouped State"]',
- tfState: 'vn-autocomplete[label="Destination Grouped State"]',
+ futureState: 'vn-autocomplete[label="Destination Grouped State"]',
warehouseFk: 'vn-autocomplete[label="Warehouse"]',
problems: 'vn-check[label="With problems"]',
tableButtonSearch: 'vn-button[vn-tooltip="Search"]',
@@ -755,9 +753,9 @@ export default {
firstCheck: 'tbody > tr:nth-child(1) > td > vn-check',
multiCheck: 'vn-multi-check',
tableId: 'vn-textfield[name="id"]',
- tableTfId: 'vn-textfield[name="ticketFuture"]',
- tableLiters: 'vn-textfield[name="litersMax"]',
- tableLines: 'vn-textfield[name="linesMax"]',
+ tableFutureId: 'vn-textfield[name="futureId"]',
+ tableLiters: 'vn-textfield[name="liters"]',
+ tableLines: 'vn-textfield[name="lines"]',
submit: 'vn-submit[label="Search"]',
table: 'tbody > tr:not(.empty-rows)'
},
diff --git a/e2e/paths/01-salix/04_recoverPassword.spec.js b/e2e/paths/01-salix/04_recoverPassword.spec.js
index 80ef32cb5..67e6362d3 100644
--- a/e2e/paths/01-salix/04_recoverPassword.spec.js
+++ b/e2e/paths/01-salix/04_recoverPassword.spec.js
@@ -1,7 +1,8 @@
import selectors from '../../helpers/selectors';
import getBrowser from '../../helpers/puppeteer';
-describe('Login path', async() => {
+// https://redmine.verdnatura.es/issues/4995 fix login
+xdescribe('RecoverPassword path', async() => {
let browser;
let page;
diff --git a/e2e/paths/05-ticket/20_future.spec.js b/e2e/paths/05-ticket/21_future.spec.js
similarity index 71%
rename from e2e/paths/05-ticket/20_future.spec.js
rename to e2e/paths/05-ticket/21_future.spec.js
index 6db2bf4f0..45c39de86 100644
--- a/e2e/paths/05-ticket/20_future.spec.js
+++ b/e2e/paths/05-ticket/21_future.spec.js
@@ -16,9 +16,6 @@ describe('Ticket Future path', () => {
await browser.close();
});
- const now = new Date();
- const tomorrow = new Date(now.getDate() + 1);
-
it('should show errors snackbar because of the required data', async() => {
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
await page.clearInput(selectors.ticketFuture.warehouseFk);
@@ -27,20 +24,6 @@ describe('Ticket Future path', () => {
expect(message.text).toContain('warehouseFk is a required argument');
- await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
- await page.clearInput(selectors.ticketFuture.litersMax);
- await page.waitToClick(selectors.ticketFuture.submit);
- message = await page.waitForSnackbar();
-
- expect(message.text).toContain('litersMax is a required argument');
-
- await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
- await page.clearInput(selectors.ticketFuture.linesMax);
- await page.waitToClick(selectors.ticketFuture.submit);
- message = await page.waitForSnackbar();
-
- expect(message.text).toContain('linesMax is a required argument');
-
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
await page.clearInput(selectors.ticketFuture.futureDated);
await page.waitToClick(selectors.ticketFuture.submit);
@@ -62,44 +45,13 @@ describe('Ticket Future path', () => {
await page.waitForNumberOfElements(selectors.ticketFuture.table, 4);
});
- it('should search with the origin shipped today', async() => {
- await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
- await page.pickDate(selectors.ticketFuture.shipped, now);
- await page.waitToClick(selectors.ticketFuture.submit);
- await page.waitForNumberOfElements(selectors.ticketFuture.table, 4);
- });
-
- it('should search with the origin shipped tomorrow', async() => {
- await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
- await page.pickDate(selectors.ticketFuture.shipped, tomorrow);
- await page.waitToClick(selectors.ticketFuture.submit);
- await page.waitForNumberOfElements(selectors.ticketFuture.table, 0);
- });
-
- it('should search with the destination shipped today', async() => {
- await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
- await page.clearInput(selectors.ticketFuture.shipped);
- await page.pickDate(selectors.ticketFuture.tfShipped, now);
- await page.waitToClick(selectors.ticketFuture.submit);
- await page.waitForNumberOfElements(selectors.ticketFuture.table, 4);
- });
-
- it('should search with the destination shipped tomorrow', async() => {
- await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
- await page.pickDate(selectors.ticketFuture.tfShipped, tomorrow);
- await page.waitToClick(selectors.ticketFuture.submit);
- await page.waitForNumberOfElements(selectors.ticketFuture.table, 0);
- });
-
it('should search with the origin IPT', async() => {
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
- await page.clearInput(selectors.ticketFuture.shipped);
- await page.clearInput(selectors.ticketFuture.tfShipped);
await page.clearInput(selectors.ticketFuture.ipt);
- await page.clearInput(selectors.ticketFuture.tfIpt);
+ await page.clearInput(selectors.ticketFuture.futureIpt);
await page.clearInput(selectors.ticketFuture.state);
- await page.clearInput(selectors.ticketFuture.tfState);
+ await page.clearInput(selectors.ticketFuture.futureState);
await page.autocompleteSearch(selectors.ticketFuture.ipt, 'Horizontal');
await page.waitToClick(selectors.ticketFuture.submit);
@@ -109,14 +61,12 @@ describe('Ticket Future path', () => {
it('should search with the destination IPT', async() => {
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
- await page.clearInput(selectors.ticketFuture.shipped);
- await page.clearInput(selectors.ticketFuture.tfShipped);
await page.clearInput(selectors.ticketFuture.ipt);
- await page.clearInput(selectors.ticketFuture.tfIpt);
+ await page.clearInput(selectors.ticketFuture.futureIpt);
await page.clearInput(selectors.ticketFuture.state);
- await page.clearInput(selectors.ticketFuture.tfState);
+ await page.clearInput(selectors.ticketFuture.futureState);
- await page.autocompleteSearch(selectors.ticketFuture.tfIpt, 'Horizontal');
+ await page.autocompleteSearch(selectors.ticketFuture.futureIpt, 'Horizontal');
await page.waitToClick(selectors.ticketFuture.submit);
await page.waitForNumberOfElements(selectors.ticketFuture.table, 0);
});
@@ -124,12 +74,10 @@ describe('Ticket Future path', () => {
it('should search with the origin grouped state', async() => {
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
- await page.clearInput(selectors.ticketFuture.shipped);
- await page.clearInput(selectors.ticketFuture.tfShipped);
await page.clearInput(selectors.ticketFuture.ipt);
- await page.clearInput(selectors.ticketFuture.tfIpt);
+ await page.clearInput(selectors.ticketFuture.futureIpt);
await page.clearInput(selectors.ticketFuture.state);
- await page.clearInput(selectors.ticketFuture.tfState);
+ await page.clearInput(selectors.ticketFuture.futureState);
await page.autocompleteSearch(selectors.ticketFuture.state, 'Free');
await page.waitToClick(selectors.ticketFuture.submit);
@@ -139,24 +87,20 @@ describe('Ticket Future path', () => {
it('should search with the destination grouped state', async() => {
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
- await page.clearInput(selectors.ticketFuture.shipped);
- await page.clearInput(selectors.ticketFuture.tfShipped);
await page.clearInput(selectors.ticketFuture.ipt);
- await page.clearInput(selectors.ticketFuture.tfIpt);
+ await page.clearInput(selectors.ticketFuture.futureIpt);
await page.clearInput(selectors.ticketFuture.state);
- await page.clearInput(selectors.ticketFuture.tfState);
+ await page.clearInput(selectors.ticketFuture.futureState);
- await page.autocompleteSearch(selectors.ticketFuture.tfState, 'Free');
+ await page.autocompleteSearch(selectors.ticketFuture.futureState, 'Free');
await page.waitToClick(selectors.ticketFuture.submit);
await page.waitForNumberOfElements(selectors.ticketFuture.table, 0);
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
- await page.clearInput(selectors.ticketFuture.shipped);
- await page.clearInput(selectors.ticketFuture.tfShipped);
await page.clearInput(selectors.ticketFuture.ipt);
- await page.clearInput(selectors.ticketFuture.tfIpt);
+ await page.clearInput(selectors.ticketFuture.futureIpt);
await page.clearInput(selectors.ticketFuture.state);
- await page.clearInput(selectors.ticketFuture.tfState);
+ await page.clearInput(selectors.ticketFuture.futureState);
await page.waitToClick(selectors.ticketFuture.submit);
await page.waitForNumberOfElements(selectors.ticketFuture.table, 4);
@@ -176,7 +120,7 @@ describe('Ticket Future path', () => {
it('should search in smart-table with an ID Destination', async() => {
await page.waitToClick(selectors.ticketFuture.tableButtonSearch);
- await page.write(selectors.ticketFuture.tableTfId, '12');
+ await page.write(selectors.ticketFuture.tableFutureId, '12');
await page.keyboard.press('Enter');
await page.waitForNumberOfElements(selectors.ticketFuture.table, 5);
@@ -199,7 +143,7 @@ describe('Ticket Future path', () => {
it('should search in smart-table with an IPT Destination', async() => {
await page.waitToClick(selectors.ticketFuture.tableButtonSearch);
- await page.autocompleteSearch(selectors.ticketFuture.tableTfIpt, 'Vertical');
+ await page.autocompleteSearch(selectors.ticketFuture.tableFutureIpt, 'Vertical');
await page.waitForNumberOfElements(selectors.ticketFuture.table, 1);
await page.waitToClick(selectors.ticketFuture.tableButtonSearch);
diff --git a/front/core/components/smart-table/index.js b/front/core/components/smart-table/index.js
index 8d2c3c153..770dcdf32 100644
--- a/front/core/components/smart-table/index.js
+++ b/front/core/components/smart-table/index.js
@@ -147,7 +147,7 @@ export default class SmartTable extends Component {
for (const column of this.columns) {
if (viewConfig.configuration[column.field] == false) {
const baseSelector = `smart-table[view-config-id="${this.viewConfigId}"] table`;
- selectors.push(`${baseSelector} thead > tr > th:nth-child(${column.index + 1})`);
+ selectors.push(`${baseSelector} thead > tr:not([second-header]) > th:nth-child(${column.index + 1})`);
selectors.push(`${baseSelector} tbody > tr > td:nth-child(${column.index + 1})`);
}
}
@@ -235,7 +235,7 @@ export default class SmartTable extends Component {
}
registerColumns() {
- const header = this.element.querySelector('thead > tr');
+ const header = this.element.querySelector('thead > tr:not([second-header])');
if (!header) return;
const columns = header.querySelectorAll('th');
@@ -254,7 +254,7 @@ export default class SmartTable extends Component {
}
emptyDataRows() {
- const header = this.element.querySelector('thead > tr');
+ const header = this.element.querySelector('thead > tr:not([second-header])');
const columns = header.querySelectorAll('th');
const tbody = this.element.querySelector('tbody');
if (tbody) {
@@ -333,7 +333,7 @@ export default class SmartTable extends Component {
}
displaySearch() {
- const header = this.element.querySelector('thead > tr');
+ const header = this.element.querySelector('thead > tr:not([second-header])');
if (!header) return;
const tbody = this.element.querySelector('tbody');
diff --git a/front/core/components/smart-table/table.scss b/front/core/components/smart-table/table.scss
index c38c149ca..996c41a74 100644
--- a/front/core/components/smart-table/table.scss
+++ b/front/core/components/smart-table/table.scss
@@ -8,6 +8,16 @@ smart-table table {
& > thead {
border-bottom: $border;
+ & > tr[second-header] {
+ & > th
+ {
+ text-align: center;
+ border-bottom-style: groove;
+ font-weight: bold;
+ text-transform: uppercase;
+ }
+ }
+
& > * > th {
font-weight: normal;
}
@@ -60,6 +70,9 @@ smart-table table {
vertical-align: middle;
}
}
+ &[separator]{
+ border-left-style: groove;
+ }
vn-icon.bright, i.bright {
color: #f7931e;
}
@@ -108,4 +121,4 @@ smart-table table {
font-size: 1.375rem;
text-align: center;
}
-}
\ No newline at end of file
+}
diff --git a/front/salix/components/app/app.html b/front/salix/components/app/app.html
index f14fab2dd..d32c9f68b 100644
--- a/front/salix/components/app/app.html
+++ b/front/salix/components/app/app.html
@@ -1,8 +1,9 @@
-
-
+
diff --git a/front/salix/components/app/app.js b/front/salix/components/app/app.js
index 20f0ad969..91a8d2215 100644
--- a/front/salix/components/app/app.js
+++ b/front/salix/components/app/app.js
@@ -21,7 +21,7 @@ export default class App extends Component {
get showLayout() {
const state = this.$state.current.name || this.$location.$$path.substring(1).replace('/', '.');
- const outLayout = ['login', 'recoverPassword', 'resetPassword'];
+ const outLayout = ['login', 'recoverPassword', 'resetPassword', 'reset-password'];
return state && !outLayout.some(ol => ol == state);
}
diff --git a/front/salix/components/index.js b/front/salix/components/index.js
index dbe9fe81a..3bd24d32f 100644
--- a/front/salix/components/index.js
+++ b/front/salix/components/index.js
@@ -19,3 +19,4 @@ import './user-popover';
import './upload-photo';
import './bank-entity';
import './log';
+import './sendSms';
diff --git a/front/salix/components/login/login.html b/front/salix/components/login/login.html
index a078fa0af..807e4b284 100644
--- a/front/salix/components/login/login.html
+++ b/front/salix/components/login/login.html
@@ -1,27 +1,32 @@
-
-
-
-
-
-
-
-
-
+
diff --git a/modules/client/front/descriptor/index.js b/modules/client/front/descriptor/index.js
index 4a0d1cd2a..4d8d70edf 100644
--- a/modules/client/front/descriptor/index.js
+++ b/modules/client/front/descriptor/index.js
@@ -39,6 +39,11 @@ class Controller extends Descriptor {
};
this.$.sms.open();
}
+
+ onSmsSend(sms) {
+ return this.$http.post(`Clients/${this.id}/sendSms`, sms)
+ .then(() => this.vnApp.showSuccess(this.$t('SMS sent')));
+ }
}
ngModule.vnComponent('vnClientDescriptor', {
diff --git a/modules/client/front/index.js b/modules/client/front/index.js
index a5782c789..ff767bc9e 100644
--- a/modules/client/front/index.js
+++ b/modules/client/front/index.js
@@ -35,7 +35,6 @@ import './sample/index';
import './sample/create';
import './web-payment';
import './log';
-import './sms';
import './postcode';
import './postcode/province';
import './postcode/city';
diff --git a/modules/client/front/sms/index.js b/modules/client/front/sms/index.js
deleted file mode 100644
index 701ee39af..000000000
--- a/modules/client/front/sms/index.js
+++ /dev/null
@@ -1,49 +0,0 @@
-import ngModule from '../module';
-import Section from 'salix/components/section';
-import './style.scss';
-
-class Controller extends Section {
- open() {
- this.$.SMSDialog.show();
- }
-
- charactersRemaining() {
- const element = this.$.message;
- const value = element.input.value;
-
- const maxLength = 160;
- const textAreaLength = new Blob([value]).size;
- return maxLength - textAreaLength;
- }
-
- onResponse() {
- try {
- if (!this.sms.destination)
- throw new Error(`The destination can't be empty`);
- if (!this.sms.message)
- throw new Error(`The message can't be empty`);
- if (this.charactersRemaining() < 0)
- throw new Error(`The message it's too long`);
-
- this.$http.post(`Clients/${this.$params.id}/sendSms`, this.sms).then(res => {
- this.vnApp.showMessage(this.$t('SMS sent!'));
-
- if (res.data) this.emit('send', {response: res.data});
- });
- } catch (e) {
- this.vnApp.showError(this.$t(e.message));
- return false;
- }
- return true;
- }
-}
-
-Controller.$inject = ['$element', '$scope', '$http', '$translate', 'vnApp'];
-
-ngModule.vnComponent('vnClientSms', {
- template: require('./index.html'),
- controller: Controller,
- bindings: {
- sms: '<',
- }
-});
diff --git a/modules/client/front/sms/index.spec.js b/modules/client/front/sms/index.spec.js
deleted file mode 100644
index 793c80d6e..000000000
--- a/modules/client/front/sms/index.spec.js
+++ /dev/null
@@ -1,74 +0,0 @@
-import './index';
-
-describe('Client', () => {
- describe('Component vnClientSms', () => {
- let controller;
- let $httpBackend;
- let $element;
-
- beforeEach(ngModule('client'));
-
- beforeEach(inject(($componentController, $rootScope, _$httpBackend_) => {
- $httpBackend = _$httpBackend_;
- let $scope = $rootScope.$new();
- $element = angular.element(' ');
- controller = $componentController('vnClientSms', {$element, $scope});
- controller.client = {id: 1101};
- controller.$params = {id: 1101};
- controller.$.message = {
- input: {
- value: 'My SMS'
- }
- };
- }));
-
- describe('onResponse()', () => {
- it('should perform a POST query and show a success snackbar', () => {
- let params = {destinationFk: 1101, destination: 111111111, message: 'My SMS'};
- controller.sms = {destinationFk: 1101, destination: 111111111, message: 'My SMS'};
-
- jest.spyOn(controller.vnApp, 'showMessage');
- $httpBackend.expect('POST', `Clients/1101/sendSms`, params).respond(200, params);
-
- controller.onResponse();
- $httpBackend.flush();
-
- expect(controller.vnApp.showMessage).toHaveBeenCalledWith('SMS sent!');
- });
-
- it('should call onResponse without the destination and show an error snackbar', () => {
- controller.sms = {destinationFk: 1101, message: 'My SMS'};
-
- jest.spyOn(controller.vnApp, 'showError');
-
- controller.onResponse('accept');
-
- expect(controller.vnApp.showError).toHaveBeenCalledWith(`The destination can't be empty`);
- });
-
- it('should call onResponse without the message and show an error snackbar', () => {
- controller.sms = {destinationFk: 1101, destination: 222222222};
-
- jest.spyOn(controller.vnApp, 'showError');
-
- controller.onResponse('accept');
-
- expect(controller.vnApp.showError).toHaveBeenCalledWith(`The message can't be empty`);
- });
- });
-
- describe('charactersRemaining()', () => {
- it('should return the characters remaining in a element', () => {
- controller.$.message = {
- input: {
- value: 'My message 0€'
- }
- };
-
- let result = controller.charactersRemaining();
-
- expect(result).toEqual(145);
- });
- });
- });
-});
diff --git a/modules/invoiceIn/back/model-config.json b/modules/invoiceIn/back/model-config.json
index 6765ae81c..bd37b3bf1 100644
--- a/modules/invoiceIn/back/model-config.json
+++ b/modules/invoiceIn/back/model-config.json
@@ -2,7 +2,7 @@
"InvoiceIn": {
"dataSource": "vn"
},
- "InvoiceInTax": {
+ "InvoiceInConfig": {
"dataSource": "vn"
},
"InvoiceInDueDay": {
@@ -13,5 +13,8 @@
},
"InvoiceInLog": {
"dataSource": "vn"
+ },
+ "InvoiceInTax": {
+ "dataSource": "vn"
}
}
diff --git a/modules/invoiceIn/back/models/invoice-in-config.json b/modules/invoiceIn/back/models/invoice-in-config.json
new file mode 100644
index 000000000..5cf0ed64c
--- /dev/null
+++ b/modules/invoiceIn/back/models/invoice-in-config.json
@@ -0,0 +1,35 @@
+{
+ "name": "InvoiceInConfig",
+ "base": "VnModel",
+ "options": {
+ "mysql": {
+ "table": "invoiceInConfig"
+ }
+ },
+ "properties": {
+ "id": {
+ "id": true,
+ "type": "number",
+ "description": "Identifier"
+ },
+ "retentionRate": {
+ "type": "number"
+ },
+ "retentionName": {
+ "type": "string"
+ }
+ },
+ "relations": {
+ "sageWithholding": {
+ "type": "belongsTo",
+ "model": "SageWithholding",
+ "foreignKey": "sageWithholdingFk"
+ }
+ },
+ "acls": [{
+ "accessType": "READ",
+ "principalType": "ROLE",
+ "principalId": "$everyone",
+ "permission": "ALLOW"
+ }]
+}
diff --git a/modules/invoiceIn/front/descriptor/index.html b/modules/invoiceIn/front/descriptor/index.html
index a2b48b5cd..40f7dec18 100644
--- a/modules/invoiceIn/front/descriptor/index.html
+++ b/modules/invoiceIn/front/descriptor/index.html
@@ -1,3 +1,10 @@
+
+
Show agricultural invoice as PDF
Send agricultural invoice as PDF
diff --git a/modules/invoiceIn/front/descriptor/index.js b/modules/invoiceIn/front/descriptor/index.js
index 5cd00d743..4dc89a459 100644
--- a/modules/invoiceIn/front/descriptor/index.js
+++ b/modules/invoiceIn/front/descriptor/index.js
@@ -110,6 +110,10 @@ class Controller extends Descriptor {
recipientId: this.entity.supplier.id
});
}
+
+ isAgricultural() {
+ return this.invoiceIn.supplier.sageWithholdingFk == this.config[0].sageWithholdingFk;
+ }
}
ngModule.vnComponent('vnInvoiceInDescriptor', {
diff --git a/modules/invoiceOut/back/methods/invoiceOut/specs/downloadZip.spec.js b/modules/invoiceOut/back/methods/invoiceOut/specs/downloadZip.spec.js
index 536fa07a0..e458ad9ff 100644
--- a/modules/invoiceOut/back/methods/invoiceOut/specs/downloadZip.spec.js
+++ b/modules/invoiceOut/back/methods/invoiceOut/specs/downloadZip.spec.js
@@ -13,6 +13,7 @@ describe('InvoiceOut downloadZip()', () => {
};
it('should return part of link to dowloand the zip', async() => {
+ pending('https://redmine.verdnatura.es/issues/4875');
const tx = await models.InvoiceOut.beginTransaction({});
try {
@@ -30,7 +31,6 @@ describe('InvoiceOut downloadZip()', () => {
});
it('should return an error if the size of the files is too large', async() => {
- pending('https://redmine.verdnatura.es/issues/4875');
const tx = await models.InvoiceOut.beginTransaction({});
let error;
diff --git a/modules/supplier/back/models/specs/supplier.spec.js b/modules/supplier/back/models/specs/supplier.spec.js
index 3140981c3..f317f1fb9 100644
--- a/modules/supplier/back/models/specs/supplier.spec.js
+++ b/modules/supplier/back/models/specs/supplier.spec.js
@@ -8,7 +8,6 @@ describe('loopback model Supplier', () => {
beforeAll(async() => {
supplierOne = await models.Supplier.findById(1);
supplierTwo = await models.Supplier.findById(442);
-
const activeCtx = {
accessToken: {userId: 9},
http: {
@@ -23,71 +22,106 @@ describe('loopback model Supplier', () => {
});
});
- afterAll(async() => {
- await supplierOne.updateAttribute('payMethodFk', supplierOne.payMethodFk);
- await supplierTwo.updateAttribute('payMethodFk', supplierTwo.payMethodFk);
- });
-
describe('payMethodFk', () => {
it('should throw an error when attempting to set an invalid payMethod id in the supplier', async() => {
- let error;
- const expectedError = 'You can not select this payment method without a registered bankery account';
- const supplier = await models.Supplier.findById(1);
+ const tx = await models.Supplier.beginTransaction({});
+ const options = {transaction: tx};
- await supplier.updateAttribute('payMethodFk', 8)
- .catch(e => {
- error = e;
+ try {
+ let error;
+ const expectedError = 'You can not select this payment method without a registered bankery account';
- expect(error.message).toContain(expectedError);
- });
+ await supplierOne.updateAttribute('payMethodFk', 8, options)
+ .catch(e => {
+ error = e;
- expect(error).toBeDefined();
+ expect(error.message).toContain(expectedError);
+ });
+
+ expect(error).toBeDefined();
+ await tx.rollback();
+ } catch (e) {
+ await tx.rollback();
+ throw e;
+ }
});
it('should not throw if the payMethod id is valid', async() => {
- let error;
- const supplier = await models.Supplier.findById(442);
- await supplier.updateAttribute('payMethodFk', 4)
- .catch(e => {
- error = e;
- });
+ const tx = await models.Supplier.beginTransaction({});
+ const options = {transaction: tx};
- expect(error).not.toBeDefined();
+ try {
+ let error;
+ await supplierTwo.updateAttribute('payMethodFk', 4, options)
+ .catch(e => {
+ error = e;
+ });
+
+ expect(error).not.toBeDefined();
+ await tx.rollback();
+ } catch (e) {
+ await tx.rollback();
+ throw e;
+ }
});
it('should have checked isPayMethodChecked for payMethod hasVerfified is false', async() => {
- const supplier = await models.Supplier.findById(442);
- await supplier.updateAttribute('isPayMethodChecked', true);
- await supplier.updateAttribute('payMethodFk', 5);
+ const tx = await models.Supplier.beginTransaction({});
+ const options = {transaction: tx};
- const result = await models.Supplier.findById(442);
+ try {
+ await supplierTwo.updateAttribute('isPayMethodChecked', true, options);
+ await supplierTwo.updateAttribute('payMethodFk', 5, options);
- expect(result.isPayMethodChecked).toEqual(true);
+ const result = await models.Supplier.findById(442, null, options);
+
+ expect(result.isPayMethodChecked).toEqual(true);
+ await tx.rollback();
+ } catch (e) {
+ await tx.rollback();
+ throw e;
+ }
});
it('should have unchecked isPayMethodChecked for payMethod hasVerfified is true', async() => {
- const supplier = await models.Supplier.findById(442);
- await supplier.updateAttribute('isPayMethodChecked', true);
- await supplier.updateAttribute('payMethodFk', 2);
+ const tx = await models.Supplier.beginTransaction({});
+ const options = {transaction: tx};
- const result = await models.Supplier.findById(442);
+ try {
+ await supplierTwo.updateAttribute('isPayMethodChecked', true, options);
+ await supplierTwo.updateAttribute('payMethodFk', 2, options);
- expect(result.isPayMethodChecked).toEqual(false);
+ const result = await models.Supplier.findById(442, null, options);
+
+ expect(result.isPayMethodChecked).toEqual(false);
+ await tx.rollback();
+ } catch (e) {
+ await tx.rollback();
+ throw e;
+ }
});
it('should have unchecked isPayMethodChecked for payDay and peyDemFk', async() => {
- const supplier = await models.Supplier.findById(442);
+ const tx = await models.Supplier.beginTransaction({});
+ const options = {transaction: tx};
- await supplier.updateAttribute('isPayMethodChecked', true);
- await supplier.updateAttribute('payDay', 5);
- const firstResult = await models.Supplier.findById(442);
+ try {
+ await supplierTwo.updateAttribute('payMethodFk', 2, options);
+ await supplierTwo.updateAttribute('isPayMethodChecked', true, options);
+ await supplierTwo.updateAttribute('payDay', 5, options);
+ const firstResult = await models.Supplier.findById(442, null, options);
- await supplier.updateAttribute('isPayMethodChecked', true);
- await supplier.updateAttribute('payDemFk', 1);
- const secondResult = await models.Supplier.findById(442);
+ await supplierTwo.updateAttribute('isPayMethodChecked', true, options);
+ await supplierTwo.updateAttribute('payDemFk', 1, options);
+ const secondResult = await models.Supplier.findById(442, null, options);
- expect(firstResult.isPayMethodChecked).toEqual(false);
- expect(secondResult.isPayMethodChecked).toEqual(false);
+ expect(firstResult.isPayMethodChecked).toEqual(false);
+ expect(secondResult.isPayMethodChecked).toEqual(false);
+ await tx.rollback();
+ } catch (e) {
+ await tx.rollback();
+ throw e;
+ }
});
});
});
diff --git a/modules/ticket/back/locale/ticket/en.yml b/modules/ticket/back/locale/ticket/en.yml
index 4e97f5d8c..c4ad84232 100644
--- a/modules/ticket/back/locale/ticket/en.yml
+++ b/modules/ticket/back/locale/ticket/en.yml
@@ -20,3 +20,4 @@ routeFk: route
companyFk: company
agencyModeFk: agency
ticketFk: ticket
+mergedTicket: merged ticket
diff --git a/modules/ticket/back/locale/ticket/es.yml b/modules/ticket/back/locale/ticket/es.yml
index a570f1f11..2c524a74f 100644
--- a/modules/ticket/back/locale/ticket/es.yml
+++ b/modules/ticket/back/locale/ticket/es.yml
@@ -20,3 +20,4 @@ routeFk: ruta
companyFk: empresa
agencyModeFk: agencia
ticketFk: ticket
+mergedTicket: ticket fusionado
diff --git a/modules/ticket/back/methods/ticket-future/getTicketsFuture.js b/modules/ticket/back/methods/ticket/getTicketsFuture.js
similarity index 69%
rename from modules/ticket/back/methods/ticket-future/getTicketsFuture.js
rename to modules/ticket/back/methods/ticket/getTicketsFuture.js
index 0fcc21182..6798df513 100644
--- a/modules/ticket/back/methods/ticket-future/getTicketsFuture.js
+++ b/modules/ticket/back/methods/ticket/getTicketsFuture.js
@@ -20,18 +20,6 @@ module.exports = Self => {
description: 'The date to probe',
required: true
},
- {
- arg: 'litersMax',
- type: 'number',
- description: 'Maximum volume of tickets to catapult',
- required: true
- },
- {
- arg: 'linesMax',
- type: 'number',
- description: 'Maximum number of lines of tickets to catapult',
- required: true
- },
{
arg: 'warehouseFk',
type: 'number',
@@ -39,15 +27,15 @@ module.exports = Self => {
required: true
},
{
- arg: 'shipped',
- type: 'date',
- description: 'Origin shipped',
+ arg: 'litersMax',
+ type: 'number',
+ description: 'Maximum volume of tickets to catapult',
required: false
},
{
- arg: 'tfShipped',
- type: 'date',
- description: 'Destination shipped',
+ arg: 'linesMax',
+ type: 'number',
+ description: 'Maximum number of lines of tickets to catapult',
required: false
},
{
@@ -57,7 +45,7 @@ module.exports = Self => {
required: false
},
{
- arg: 'tfIpt',
+ arg: 'futureIpt',
type: 'string',
description: 'Destination Item Packaging Type',
required: false
@@ -69,7 +57,7 @@ module.exports = Self => {
required: false
},
{
- arg: 'tfId',
+ arg: 'futureId',
type: 'number',
description: 'Destination id',
required: false
@@ -81,7 +69,7 @@ module.exports = Self => {
required: false
},
{
- arg: 'tfState',
+ arg: 'futureState',
type: 'string',
description: 'Destination state',
required: false
@@ -108,7 +96,7 @@ module.exports = Self => {
}
});
- Self.getTicketsFuture = async (ctx, options) => {
+ Self.getTicketsFuture = async(ctx, options) => {
const args = ctx.args;
const conn = Self.dataSource.connector;
const myOptions = {};
@@ -118,32 +106,32 @@ module.exports = Self => {
const where = buildFilter(ctx.args, (param, value) => {
switch (param) {
- case 'id':
- return { 'f.id': value };
- case 'tfId':
- return { 'f.ticketFuture': value };
- case 'shipped':
- return { 'f.shipped': value };
- case 'tfShipped':
- return { 'f.tfShipped': value };
- case 'ipt':
- return { 'f.ipt': value };
- case 'tfIpt':
- return { 'f.tfIpt': value };
- case 'state':
- return { 'f.code': { like: `%${value}%` } };
- case 'tfState':
- return { 'f.tfCode': { like: `%${value}%` } };
+ case 'id':
+ return {'f.id': value};
+ case 'lines':
+ return {'f.lines': {lte: value}};
+ case 'liters':
+ return {'f.liters': {lte: value}};
+ case 'futureId':
+ return {'f.futureId': value};
+ case 'ipt':
+ return {'f.ipt': value};
+ case 'futureIpt':
+ return {'f.futureIpt': value};
+ case 'state':
+ return {'f.stateCode': {like: `%${value}%`}};
+ case 'futureState':
+ return {'f.futureStateCode': {like: `%${value}%`}};
}
});
- let filter = mergeFilters(ctx.args.filter, { where });
+ let filter = mergeFilters(ctx.args.filter, {where});
const stmts = [];
let stmt;
stmt = new ParameterizedSQL(
- `CALL vn.ticket_canbePostponed(?,?,?,?,?)`,
- [args.originDated, args.futureDated, args.litersMax, args.linesMax, args.warehouseFk]);
+ `CALL vn.ticket_canbePostponed(?,?,?)`,
+ [args.originDated, args.futureDated, args.warehouseFk]);
stmts.push(stmt);
@@ -153,7 +141,7 @@ module.exports = Self => {
CREATE TEMPORARY TABLE tmp.sale_getProblems
(INDEX (ticketFk))
ENGINE = MEMORY
- SELECT f.id ticketFk, f.clientFk, f.warehouseFk, f.shipped
+ SELECT f.id ticketFk, f.clientFk, f.warehouseFk, f.shipped, f.lines, f.liters
FROM tmp.filter f
LEFT JOIN alertLevel al ON al.id = f.alertLevel
WHERE (al.code = 'FREE' OR f.alertLevel IS NULL)`);
@@ -174,35 +162,34 @@ module.exports = Self => {
let range;
let hasWhere;
switch (args.problems) {
- case true:
- condition = `or`;
- hasProblem = true;
- range = { neq: null };
- hasWhere = true;
- break;
+ case true:
+ condition = `or`;
+ hasProblem = true;
+ range = {neq: null};
+ hasWhere = true;
+ break;
- case false:
- condition = `and`;
- hasProblem = null;
- range = null;
- hasWhere = true;
- break;
+ case false:
+ condition = `and`;
+ hasProblem = null;
+ range = null;
+ hasWhere = true;
+ break;
}
const problems = {
[condition]: [
- { 'tp.isFreezed': hasProblem },
- { 'tp.risk': hasProblem },
- { 'tp.hasTicketRequest': hasProblem },
- { 'tp.itemShortage': range },
- { 'tp.hasComponentLack': hasProblem },
- { 'tp.isTooLittle': hasProblem }
+ {'tp.isFreezed': hasProblem},
+ {'tp.risk': hasProblem},
+ {'tp.hasTicketRequest': hasProblem},
+ {'tp.itemShortage': range},
+ {'tp.hasComponentLack': hasProblem},
+ {'tp.isTooLittle': hasProblem}
]
};
- if (hasWhere) {
- filter = mergeFilters(filter, { where: problems });
- }
+ if (hasWhere)
+ filter = mergeFilters(filter, {where: problems});
stmt.merge(conn.makeWhere(filter.where));
stmt.merge(conn.makeOrderBy(filter.order));
diff --git a/modules/ticket/back/methods/ticket/merge.js b/modules/ticket/back/methods/ticket/merge.js
index 04f8d83af..8aaca1085 100644
--- a/modules/ticket/back/methods/ticket/merge.js
+++ b/modules/ticket/back/methods/ticket/merge.js
@@ -40,19 +40,32 @@ module.exports = Self => {
try {
for (let ticket of tickets) {
- const fullPath = `${origin}/#!/ticket/${ticket.id}/summary`;
- const fullPathFuture = `${origin}/#!/ticket/${ticket.ticketFuture}/summary`;
+ const originFullPath = `${origin}/#!/ticket/${ticket.originId}/summary`;
+ const destinationFullPath = `${origin}/#!/ticket/${ticket.destinationId}/summary`;
const message = $t('Ticket merged', {
- originDated: dateUtil.toString(new Date(ticket.originETD)),
- futureDated: dateUtil.toString(new Date(ticket.destETD)),
- id: ticket.id,
- tfId: ticket.ticketFuture,
- fullPath,
- fullPathFuture
+ originDated: dateUtil.toString(new Date(ticket.originShipped)),
+ destinationDated: dateUtil.toString(new Date(ticket.destinationShipped)),
+ originId: ticket.originId,
+ destinationId: ticket.destinationId,
+ originFullPath,
+ destinationFullPath
});
- if (!ticket.id || !ticket.ticketFuture) continue;
- await models.Sale.updateAll({ticketFk: ticket.id}, {ticketFk: ticket.ticketFuture}, myOptions);
- await models.Ticket.setDeleted(ctx, ticket.id, myOptions);
+ if (!ticket.originId || !ticket.destinationId) continue;
+
+ const ticketDestinationLogRecord = {
+ originFk: ticket.destinationId,
+ userFk: ctx.req.accessToken.userId,
+ action: 'update',
+ changedModel: 'Ticket',
+ changedModelId: ticket.destinationId,
+ changedModelValue: ticket.destinationId,
+ oldInstance: {},
+ newInstance: {mergedTicket: ticket.originId}
+ };
+
+ await models.TicketLog.create(ticketDestinationLogRecord, myOptions);
+ await models.Sale.updateAll({ticketFk: ticket.originId}, {ticketFk: ticket.destinationId}, myOptions);
+ await models.Ticket.setDeleted(ctx, ticket.originId, myOptions);
await models.Chat.sendCheckingPresence(ctx, ticket.workerFk, message);
}
if (tx)
diff --git a/modules/ticket/back/methods/ticket-future/spec/getTicketsFuture.spec.js b/modules/ticket/back/methods/ticket/specs/getTicketsFuture.spec.js
similarity index 53%
rename from modules/ticket/back/methods/ticket-future/spec/getTicketsFuture.spec.js
rename to modules/ticket/back/methods/ticket/specs/getTicketsFuture.spec.js
index 502ea3074..c05ba764d 100644
--- a/modules/ticket/back/methods/ticket-future/spec/getTicketsFuture.spec.js
+++ b/modules/ticket/back/methods/ticket/specs/getTicketsFuture.spec.js
@@ -1,25 +1,22 @@
const models = require('vn-loopback/server/server').models;
-describe('TicketFuture getTicketsFuture()', () => {
+describe('ticket getTicketsFuture()', () => {
const today = new Date();
today.setHours(0, 0, 0, 0);
- const tomorrow = new Date(today.getDate() + 1);
- it('should return the tickets passing the required data', async () => {
+ it('should return the tickets passing the required data', async() => {
const tx = await models.Ticket.beginTransaction({});
try {
- const options = { transaction: tx };
+ const options = {transaction: tx};
const args = {
originDated: today,
futureDated: today,
- litersMax: 9999,
- linesMax: 9999,
warehouseFk: 1,
};
- const ctx = { req: { accessToken: { userId: 9 } }, args };
+ const ctx = {req: {accessToken: {userId: 9}}, args};
const result = await models.Ticket.getTicketsFuture(ctx, options);
expect(result.length).toEqual(4);
@@ -30,22 +27,20 @@ describe('TicketFuture getTicketsFuture()', () => {
}
});
- it('should return the tickets matching the problems on true', async () => {
+ it('should return the tickets matching the problems on true', async() => {
const tx = await models.Ticket.beginTransaction({});
try {
- const options = { transaction: tx };
+ const options = {transaction: tx};
const args = {
originDated: today,
futureDated: today,
- litersMax: 9999,
- linesMax: 9999,
warehouseFk: 1,
problems: true
};
- const ctx = { req: { accessToken: { userId: 9 } }, args };
+ const ctx = {req: {accessToken: {userId: 9}}, args};
const result = await models.Ticket.getTicketsFuture(ctx, options);
expect(result.length).toEqual(4);
@@ -57,22 +52,20 @@ describe('TicketFuture getTicketsFuture()', () => {
}
});
- it('should return the tickets matching the problems on false', async () => {
+ it('should return the tickets matching the problems on false', async() => {
const tx = await models.Ticket.beginTransaction({});
try {
- const options = { transaction: tx };
+ const options = {transaction: tx};
const args = {
originDated: today,
futureDated: today,
- litersMax: 9999,
- linesMax: 9999,
warehouseFk: 1,
problems: false
};
- const ctx = { req: { accessToken: { userId: 9 } }, args };
+ const ctx = {req: {accessToken: {userId: 9}}, args};
const result = await models.Ticket.getTicketsFuture(ctx, options);
expect(result.length).toEqual(0);
@@ -84,22 +77,20 @@ describe('TicketFuture getTicketsFuture()', () => {
}
});
- it('should return the tickets matching the problems on null', async () => {
+ it('should return the tickets matching the problems on null', async() => {
const tx = await models.Ticket.beginTransaction({});
try {
- const options = { transaction: tx };
+ const options = {transaction: tx};
const args = {
originDated: today,
futureDated: today,
- litersMax: 9999,
- linesMax: 9999,
warehouseFk: 1,
problems: null
};
- const ctx = { req: { accessToken: { userId: 9 } }, args };
+ const ctx = {req: {accessToken: {userId: 9}}, args};
const result = await models.Ticket.getTicketsFuture(ctx, options);
expect(result.length).toEqual(4);
@@ -111,130 +102,20 @@ describe('TicketFuture getTicketsFuture()', () => {
}
});
- it('should return the tickets matching the correct origin shipped', async () => {
+ it('should return the tickets matching the OK State in origin date', async() => {
const tx = await models.Ticket.beginTransaction({});
try {
- const options = { transaction: tx };
+ const options = {transaction: tx};
const args = {
originDated: today,
futureDated: today,
- litersMax: 9999,
- linesMax: 9999,
warehouseFk: 1,
- shipped: today
+ state: 'OK'
};
- const ctx = { req: { accessToken: { userId: 9 } }, args };
- const result = await models.Ticket.getTicketsFuture(ctx, options);
-
- expect(result.length).toEqual(4);
-
- await tx.rollback();
- } catch (e) {
- await tx.rollback();
- throw e;
- }
- });
-
- it('should return the tickets matching the an incorrect origin shipped', async () => {
- const tx = await models.Ticket.beginTransaction({});
-
- try {
- const options = { transaction: tx };
-
- const args = {
- originDated: today,
- futureDated: today,
- litersMax: 9999,
- linesMax: 9999,
- warehouseFk: 1,
- shipped: tomorrow
- };
-
- const ctx = { req: { accessToken: { userId: 9 } }, args };
- const result = await models.Ticket.getTicketsFuture(ctx, options);
-
- expect(result.length).toEqual(0);
-
- await tx.rollback();
- } catch (e) {
- await tx.rollback();
- throw e;
- }
- });
-
- it('should return the tickets matching the correct destination shipped', async () => {
- const tx = await models.Ticket.beginTransaction({});
-
- try {
- const options = { transaction: tx };
-
- const args = {
- originDated: today,
- futureDated: today,
- litersMax: 9999,
- linesMax: 9999,
- warehouseFk: 1,
- tfShipped: today
- };
-
- const ctx = { req: { accessToken: { userId: 9 } }, args };
- const result = await models.Ticket.getTicketsFuture(ctx, options);
-
- expect(result.length).toEqual(4);
-
- await tx.rollback();
- } catch (e) {
- await tx.rollback();
- throw e;
- }
- });
-
- it('should return the tickets matching the an incorrect destination shipped', async () => {
- const tx = await models.Ticket.beginTransaction({});
-
- try {
- const options = { transaction: tx };
-
- const args = {
- originDated: today,
- futureDated: today,
- litersMax: 9999,
- linesMax: 9999,
- warehouseFk: 1,
- tfShipped: tomorrow
- };
-
- const ctx = { req: { accessToken: { userId: 9 } }, args };
- const result = await models.Ticket.getTicketsFuture(ctx, options);
-
- expect(result.length).toEqual(0);
-
- await tx.rollback();
- } catch (e) {
- await tx.rollback();
- throw e;
- }
- });
-
- it('should return the tickets matching the OK State in origin date', async () => {
- const tx = await models.Ticket.beginTransaction({});
-
- try {
- const options = { transaction: tx };
-
- const args = {
- originDated: today,
- futureDated: today,
- litersMax: 9999,
- linesMax: 9999,
- warehouseFk: 1,
- state: "OK"
- };
-
- const ctx = { req: { accessToken: { userId: 9 } }, args };
+ const ctx = {req: {accessToken: {userId: 9}}, args};
const result = await models.Ticket.getTicketsFuture(ctx, options);
expect(result.length).toEqual(1);
@@ -246,22 +127,20 @@ describe('TicketFuture getTicketsFuture()', () => {
}
});
- it('should return the tickets matching the OK State in destination date', async () => {
+ it('should return the tickets matching the OK State in destination date', async() => {
const tx = await models.Ticket.beginTransaction({});
try {
- const options = { transaction: tx };
+ const options = {transaction: tx};
const args = {
originDated: today,
futureDated: today,
- litersMax: 9999,
- linesMax: 9999,
warehouseFk: 1,
- tfState: "OK"
+ futureState: 'OK'
};
- const ctx = { req: { accessToken: { userId: 9 } }, args };
+ const ctx = {req: {accessToken: {userId: 9}}, args};
const result = await models.Ticket.getTicketsFuture(ctx, options);
expect(result.length).toEqual(4);
@@ -273,22 +152,20 @@ describe('TicketFuture getTicketsFuture()', () => {
}
});
- it('should return the tickets matching the correct IPT in origin date', async () => {
+ it('should return the tickets matching the correct IPT in origin date', async() => {
const tx = await models.Ticket.beginTransaction({});
try {
- const options = { transaction: tx };
+ const options = {transaction: tx};
const args = {
originDated: today,
futureDated: today,
- litersMax: 9999,
- linesMax: 9999,
warehouseFk: 1,
ipt: null
};
- const ctx = { req: { accessToken: { userId: 9 } }, args };
+ const ctx = {req: {accessToken: {userId: 9}}, args};
const result = await models.Ticket.getTicketsFuture(ctx, options);
expect(result.length).toEqual(4);
@@ -300,22 +177,20 @@ describe('TicketFuture getTicketsFuture()', () => {
}
});
- it('should return the tickets matching the incorrect IPT in origin date', async () => {
+ it('should return the tickets matching the incorrect IPT in origin date', async() => {
const tx = await models.Ticket.beginTransaction({});
try {
- const options = { transaction: tx };
+ const options = {transaction: tx};
const args = {
originDated: today,
futureDated: today,
- litersMax: 9999,
- linesMax: 9999,
warehouseFk: 1,
ipt: 0
};
- const ctx = { req: { accessToken: { userId: 9 } }, args };
+ const ctx = {req: {accessToken: {userId: 9}}, args};
const result = await models.Ticket.getTicketsFuture(ctx, options);
expect(result.length).toEqual(0);
@@ -327,22 +202,20 @@ describe('TicketFuture getTicketsFuture()', () => {
}
});
- it('should return the tickets matching the correct IPT in destination date', async () => {
+ it('should return the tickets matching the correct IPT in destination date', async() => {
const tx = await models.Ticket.beginTransaction({});
try {
- const options = { transaction: tx };
+ const options = {transaction: tx};
const args = {
originDated: today,
futureDated: today,
- litersMax: 9999,
- linesMax: 9999,
warehouseFk: 1,
- tfIpt: null
+ futureIpt: null
};
- const ctx = { req: { accessToken: { userId: 9 } }, args };
+ const ctx = {req: {accessToken: {userId: 9}}, args};
const result = await models.Ticket.getTicketsFuture(ctx, options);
expect(result.length).toEqual(4);
@@ -354,22 +227,20 @@ describe('TicketFuture getTicketsFuture()', () => {
}
});
- it('should return the tickets matching the incorrect IPT in destination date', async () => {
+ it('should return the tickets matching the incorrect IPT in destination date', async() => {
const tx = await models.Ticket.beginTransaction({});
try {
- const options = { transaction: tx };
+ const options = {transaction: tx};
const args = {
originDated: today,
futureDated: today,
- litersMax: 9999,
- linesMax: 9999,
warehouseFk: 1,
- tfIpt: 0
+ futureIpt: 0
};
- const ctx = { req: { accessToken: { userId: 9 } }, args };
+ const ctx = {req: {accessToken: {userId: 9}}, args};
const result = await models.Ticket.getTicketsFuture(ctx, options);
expect(result.length).toEqual(0);
@@ -381,22 +252,20 @@ describe('TicketFuture getTicketsFuture()', () => {
}
});
- it('should return the tickets matching the ID in origin date', async () => {
+ it('should return the tickets matching the ID in origin date', async() => {
const tx = await models.Ticket.beginTransaction({});
try {
- const options = { transaction: tx };
+ const options = {transaction: tx};
const args = {
originDated: today,
futureDated: today,
- litersMax: 9999,
- linesMax: 9999,
warehouseFk: 1,
id: 13
};
- const ctx = { req: { accessToken: { userId: 9 } }, args };
+ const ctx = {req: {accessToken: {userId: 9}}, args};
const result = await models.Ticket.getTicketsFuture(ctx, options);
expect(result.length).toEqual(1);
@@ -408,22 +277,20 @@ describe('TicketFuture getTicketsFuture()', () => {
}
});
- it('should return the tickets matching the ID in destination date', async () => {
+ it('should return the tickets matching the ID in destination date', async() => {
const tx = await models.Ticket.beginTransaction({});
try {
- const options = { transaction: tx };
+ const options = {transaction: tx};
const args = {
originDated: today,
futureDated: today,
- litersMax: 9999,
- linesMax: 9999,
warehouseFk: 1,
- tfId: 12
+ futureId: 12
};
- const ctx = { req: { accessToken: { userId: 9 } }, args };
+ const ctx = {req: {accessToken: {userId: 9}}, args};
const result = await models.Ticket.getTicketsFuture(ctx, options);
expect(result.length).toEqual(4);
@@ -434,5 +301,4 @@ describe('TicketFuture getTicketsFuture()', () => {
throw e;
}
});
-
});
diff --git a/modules/ticket/back/methods/ticket/specs/merge.spec.js b/modules/ticket/back/methods/ticket/specs/merge.spec.js
index 713f86ad6..275484f67 100644
--- a/modules/ticket/back/methods/ticket/specs/merge.spec.js
+++ b/modules/ticket/back/methods/ticket/specs/merge.spec.js
@@ -3,15 +3,15 @@ const LoopBackContext = require('loopback-context');
describe('ticket merge()', () => {
const tickets = [{
- id: 13,
- ticketFuture: 12,
- workerFk: 1,
- originETD: new Date(),
- destETD: new Date()
+ originId: 13,
+ destinationId: 12,
+ originShipped: new Date(),
+ destinationShipped: new Date(),
+ workerFk: 1
}];
const activeCtx = {
- accessToken: { userId: 9 },
+ accessToken: {userId: 9},
};
beforeEach(() => {
@@ -22,26 +22,26 @@ describe('ticket merge()', () => {
const ctx = {
req: {
- accessToken: { userId: 9 },
- headers: { origin: 'http://localhost:5000' },
+ accessToken: {userId: 9},
+ headers: {origin: 'http://localhost:5000'},
}
};
ctx.req.__ = value => {
return value;
};
- it('should merge two tickets', async () => {
+ it('should merge two tickets', async() => {
const tx = await models.Ticket.beginTransaction({});
try {
- const options = { transaction: tx };
+ const options = {transaction: tx};
const chatNotificationBeforeMerge = await models.Chat.find();
await models.Ticket.merge(ctx, tickets, options);
- const createdTicketLog = await models.TicketLog.find({ where: { originFk: tickets[0].id } }, options);
- const deletedTicket = await models.Ticket.findOne({ where: { id: tickets[0].id } }, options);
- const salesTicketFuture = await models.Sale.find({ where: { ticketFk: tickets[0].ticketFuture } }, options);
+ const createdTicketLog = await models.TicketLog.find({where: {originFk: tickets[0].originId}}, options);
+ const deletedTicket = await models.Ticket.findOne({where: {id: tickets[0].originId}}, options);
+ const salesTicketFuture = await models.Sale.find({where: {ticketFk: tickets[0].destinationId}}, options);
const chatNotificationAfterMerge = await models.Chat.find();
expect(createdTicketLog.length).toEqual(1);
diff --git a/modules/ticket/back/model-config.json b/modules/ticket/back/model-config.json
index baaca595e..17bd72949 100644
--- a/modules/ticket/back/model-config.json
+++ b/modules/ticket/back/model-config.json
@@ -94,8 +94,5 @@
},
"TicketConfig": {
"dataSource": "vn"
- },
- "TicketFuture": {
- "dataSource": "vn"
}
}
diff --git a/modules/ticket/back/models/ticket-future.json b/modules/ticket/back/models/ticket-future.json
deleted file mode 100644
index 00277ab8a..000000000
--- a/modules/ticket/back/models/ticket-future.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "name": "TicketFuture",
- "base": "PersistedModel",
- "acls": [
- {
- "accessType": "READ",
- "principalType": "ROLE",
- "principalId": "employee",
- "permission": "ALLOW"
- }
- ]
- }
diff --git a/modules/ticket/back/models/ticket-methods.js b/modules/ticket/back/models/ticket-methods.js
index 8fd74d35c..fe60cde8e 100644
--- a/modules/ticket/back/models/ticket-methods.js
+++ b/modules/ticket/back/models/ticket-methods.js
@@ -33,7 +33,7 @@ module.exports = function(Self) {
require('../methods/ticket/closeByTicket')(Self);
require('../methods/ticket/closeByAgency')(Self);
require('../methods/ticket/closeByRoute')(Self);
- require('../methods/ticket-future/getTicketsFuture')(Self);
+ require('../methods/ticket/getTicketsFuture')(Self);
require('../methods/ticket/merge')(Self);
require('../methods/ticket/isRoleAdvanced')(Self);
require('../methods/ticket/collectionLabel')(Self);
diff --git a/modules/ticket/front/descriptor-menu/index.html b/modules/ticket/front/descriptor-menu/index.html
index 0c04b42fb..1f0ae8362 100644
--- a/modules/ticket/front/descriptor-menu/index.html
+++ b/modules/ticket/front/descriptor-menu/index.html
@@ -280,10 +280,11 @@
-
-
+
{
+ }).then(() => {
this.vnApp.showSuccess(this.$t('Invoice sent'));
});
}
@@ -294,6 +295,11 @@ class Controller extends Section {
this.$state.go('ticket.card.sale', {id: refundTicket.id});
});
}
+
+ onSmsSend(sms) {
+ return this.$http.post(`Tickets/${this.id}/sendSms`, sms)
+ .then(() => this.vnApp.showSuccess(this.$t('SMS sent')));
+ }
}
Controller.$inject = ['$element', '$scope', 'vnReport', 'vnEmail'];
diff --git a/modules/ticket/front/descriptor-menu/index.spec.js b/modules/ticket/front/descriptor-menu/index.spec.js
index 1716e36f6..f3d8ea3b3 100644
--- a/modules/ticket/front/descriptor-menu/index.spec.js
+++ b/modules/ticket/front/descriptor-menu/index.spec.js
@@ -261,11 +261,8 @@ describe('Ticket Component vnTicketDescriptorMenu', () => {
describe('showSMSDialog()', () => {
it('should set the destionationFk and destination properties and then call the sms open() method', () => {
controller.$.sms = {open: () => {}};
- jest.spyOn(controller.$.sms, 'open');
-
controller.showSMSDialog();
- expect(controller.$.sms.open).toHaveBeenCalledWith();
expect(controller.newSMS).toEqual({
destinationFk: ticket.clientFk,
destination: ticket.address.mobile,
diff --git a/modules/ticket/front/future-search-panel/index.html b/modules/ticket/front/future-search-panel/index.html
index 1b3ae453e..18b574f2a 100644
--- a/modules/ticket/front/future-search-panel/index.html
+++ b/modules/ticket/front/future-search-panel/index.html
@@ -4,43 +4,26 @@
+ ng-model="filter.originDated"
+ required="true">
-
-
-
-
-
-
+ required="true">
-
-
+ ng-model="filter.litersMax">
+
+
@@ -48,22 +31,22 @@
data="$ctrl.itemPackingTypes"
label="Origin IPT"
value-field="code"
- show-field="name"
+ show-field="description"
ng-model="filter.ipt"
info="IPT">
- {{name}}
+ {{description}}
- {{name}}
+ {{description}}
@@ -83,7 +66,7 @@
label="Destination Grouped State"
value-field="code"
show-field="name"
- ng-model="filter.tfState">
+ ng-model="filter.futureState">
{{name}}
diff --git a/modules/ticket/front/future-search-panel/index.js b/modules/ticket/front/future-search-panel/index.js
index 1a1f0e4c5..d7e7b3a5e 100644
--- a/modules/ticket/front/future-search-panel/index.js
+++ b/modules/ticket/front/future-search-panel/index.js
@@ -28,9 +28,8 @@ class Controller extends SearchPanel {
this.$http.get('ItemPackingTypes').then(res => {
for (let ipt of res.data) {
itemPackingTypes.push({
- id: ipt.id,
+ description: this.$t(ipt.description),
code: ipt.code,
- name: this.$t(ipt.code)
});
}
this.itemPackingTypes = itemPackingTypes;
diff --git a/modules/ticket/front/future-search-panel/locale/en.yml b/modules/ticket/front/future-search-panel/locale/en.yml
index fe71865cb..767c20152 100644
--- a/modules/ticket/front/future-search-panel/locale/en.yml
+++ b/modules/ticket/front/future-search-panel/locale/en.yml
@@ -1,9 +1 @@
Future tickets: Tickets a futuro
-FREE: Free
-DELIVERED: Delivered
-ON_PREPARATION: On preparation
-PACKED: Packed
-F: Fruits and vegetables
-V: Vertical
-H: Horizontal
-P: Feed
diff --git a/modules/ticket/front/future-search-panel/locale/es.yml b/modules/ticket/front/future-search-panel/locale/es.yml
index 82deba538..9d72c5b06 100644
--- a/modules/ticket/front/future-search-panel/locale/es.yml
+++ b/modules/ticket/front/future-search-panel/locale/es.yml
@@ -11,13 +11,4 @@ With problems: Con problemas
Warehouse: Almacén
Origin Grouped State: Estado agrupado origen
Destination Grouped State: Estado agrupado destino
-FREE: Libre
-DELIVERED: Servido
-ON_PREPARATION: En preparacion
-PACKED: Encajado
-F: Frutas y verduras
-V: Vertical
-H: Horizontal
-P: Pienso
-ETD: Tiempo estimado de entrega
IPT: Encajado
diff --git a/modules/ticket/front/future/index.html b/modules/ticket/front/future/index.html
index d30cbaf19..1af1fb9ba 100644
--- a/modules/ticket/front/future/index.html
+++ b/modules/ticket/front/future/index.html
@@ -1,7 +1,7 @@
+ auto-load="false">
+
+
+ Origin
+ Destination
+
-
+
Problems
- Origin ID
+ ID
-
- Origin ETD
+
+ Date
+
+
+ IPT
- Origin State
+ State
-
- IPT
-
-
+
Liters
-
+
Available Lines
-
- Destination ID
+
+ ID
-
- Destination ETD
+
+ Date
-
- Destination State
-
-
+
IPT
+
+ State
+
@@ -125,38 +130,38 @@
{{::ticket.id}}
-
- {{::ticket.originETD | date: 'dd/MM/yyyy'}}
+
+ {{::ticket.shipped | date: 'dd/MM/yyyy'}}
+ {{::ticket.ipt}}
{{::ticket.state}}
- {{::ticket.ipt}}
{{::ticket.liters}}
{{::ticket.lines}}
- {{::ticket.ticketFuture}}
+ {{::ticket.futureId}}
-
- {{::ticket.destETD | date: 'dd/MM/yyyy'}}
+
+ {{::ticket.futureShipped | date: 'dd/MM/yyyy'}}
+ {{::ticket.futureIpt}}
- {{::ticket.tfState}}
+ class="chip {{$ctrl.stateColor(ticket.futureState)}}">
+ {{::ticket.futureState}}
- {{::ticket.tfIpt}}
diff --git a/modules/ticket/front/future/index.js b/modules/ticket/front/future/index.js
index 311b9c307..56ba1608e 100644
--- a/modules/ticket/front/future/index.js
+++ b/modules/ticket/front/future/index.js
@@ -11,15 +11,15 @@ export default class Controller extends Section {
search: true,
},
columns: [{
- field: 'problems',
+ field: 'totalProblems',
+ searchable: false,
+ },
+ {
+ field: 'shipped',
searchable: false
},
{
- field: 'originETD',
- searchable: false
- },
- {
- field: 'destETD',
+ field: 'futureShipped',
searchable: false
},
{
@@ -27,7 +27,7 @@ export default class Controller extends Section {
searchable: false
},
{
- field: 'tfState',
+ field: 'futureState',
searchable: false
},
{
@@ -39,7 +39,7 @@ export default class Controller extends Section {
}
},
{
- field: 'tfIpt',
+ field: 'futureIpt',
autocomplete: {
url: 'ItemPackingTypes',
showField: 'description',
@@ -48,6 +48,9 @@ export default class Controller extends Section {
},
]
};
+ }
+
+ $postLink() {
this.setDefaultFilter();
}
@@ -57,10 +60,9 @@ export default class Controller extends Section {
this.filterParams = {
originDated: today,
futureDated: today,
- linesMax: '9999',
- litersMax: '9999',
- warehouseFk: 1
+ warehouseFk: this.vnConfig.warehouseFk
};
+ this.$.model.applyFilter(null, this.filterParams);
}
compareDate(date) {
@@ -113,7 +115,17 @@ export default class Controller extends Section {
}
moveTicketsFuture() {
- let params = { tickets: this.checked };
+ let ticketsToMove = [];
+ this.checked.forEach(ticket => {
+ ticketsToMove.push({
+ originId: ticket.id,
+ destinationId: ticket.futureId,
+ originShipped: ticket.shipped,
+ destinationShipped: ticket.futureShipped,
+ workerFk: ticket.workerFk
+ });
+ });
+ let params = {tickets: ticketsToMove};
return this.$http.post('Tickets/merge', params)
.then(() => {
this.$.model.refresh();
@@ -123,18 +135,18 @@ export default class Controller extends Section {
exprBuilder(param, value) {
switch (param) {
- case 'id':
- return { 'id': value };
- case 'ticketFuture':
- return { 'ticketFuture': value };
- case 'litersMax':
- return { 'liters': value };
- case 'linesMax':
- return { 'lines': value };
- case 'ipt':
- return { 'ipt': value };
- case 'tfIpt':
- return { 'tfIpt': value };
+ case 'id':
+ return {'id': value};
+ case 'futureId':
+ return {'futureId': value};
+ case 'liters':
+ return {'liters': value};
+ case 'lines':
+ return {'lines': value};
+ case 'ipt':
+ return {'ipt': value};
+ case 'futureIpt':
+ return {'futureIpt': value};
}
}
}
diff --git a/modules/ticket/front/future/index.spec.js b/modules/ticket/front/future/index.spec.js
index 63deebc4f..c609a4891 100644
--- a/modules/ticket/front/future/index.spec.js
+++ b/modules/ticket/front/future/index.spec.js
@@ -2,33 +2,30 @@ import './index.js';
import crudModel from 'core/mocks/crud-model';
describe('Component vnTicketFuture', () => {
+ const today = new Date();
let controller;
let $httpBackend;
- let $window;
- beforeEach(ngModule('ticket')
- );
+ beforeEach(ngModule('ticket'));
- beforeEach(inject(($componentController, _$window_, _$httpBackend_) => {
+ beforeEach(inject(($componentController, _$httpBackend_) => {
$httpBackend = _$httpBackend_;
- $window = _$window_;
const $element = angular.element(' ');
- controller = $componentController('vnTicketFuture', { $element });
+ controller = $componentController('vnTicketFuture', {$element});
controller.$.model = crudModel;
controller.$.model.data = [{
id: 1,
checked: true,
- state: "OK"
+ state: 'OK'
}, {
id: 2,
checked: true,
- state: "Libre"
+ state: 'Libre'
}];
}));
describe('compareDate()', () => {
it('should return warning when the date is the present', () => {
- let today = new Date();
let result = controller.compareDate(today);
expect(result).toEqual('warning');
@@ -67,6 +64,7 @@ describe('Component vnTicketFuture', () => {
it('should return success to the OK tickets', () => {
const ok = controller.stateColor(controller.$.model.data[0].state);
const notOk = controller.stateColor(controller.$.model.data[1].state);
+
expect(ok).toEqual('success');
expect(notOk).not.toEqual('success');
});
@@ -74,6 +72,7 @@ describe('Component vnTicketFuture', () => {
it('should return success to the FREE tickets', () => {
const notFree = controller.stateColor(controller.$.model.data[0].state);
const free = controller.stateColor(controller.$.model.data[1].state);
+
expect(free).toEqual('notice');
expect(notFree).not.toEqual('notice');
});
@@ -81,18 +80,14 @@ describe('Component vnTicketFuture', () => {
describe('dateRange()', () => {
it('should return two dates with the hours at the start and end of the given date', () => {
- const now = new Date();
-
- const today = now.getDate();
-
- const dateRange = controller.dateRange(now);
+ const dateRange = controller.dateRange(today);
const start = dateRange[0].toString();
const end = dateRange[1].toString();
- expect(start).toContain(today);
+ expect(start).toContain(today.getDate());
expect(start).toContain('00:00:00');
- expect(end).toContain(today);
+ expect(end).toContain(today.getDate());
expect(end).toContain('23:59:59');
});
});
diff --git a/modules/ticket/front/future/locale/en.yml b/modules/ticket/front/future/locale/en.yml
index 66d3ce269..4400e6992 100644
--- a/modules/ticket/front/future/locale/en.yml
+++ b/modules/ticket/front/future/locale/en.yml
@@ -1,6 +1,2 @@
Move confirmation: Do you want to move {{checked}} tickets to the future?
-FREE: Free
-DELIVERED: Delivered
-ON_PREPARATION: On preparation
-PACKED: Packed
Success: Tickets moved successfully!
diff --git a/modules/ticket/front/future/locale/es.yml b/modules/ticket/front/future/locale/es.yml
index 9be0be6a4..9fceea111 100644
--- a/modules/ticket/front/future/locale/es.yml
+++ b/modules/ticket/front/future/locale/es.yml
@@ -3,20 +3,14 @@ Search tickets: Buscar tickets
Search future tickets by date: Buscar tickets por fecha
Problems: Problemas
Origin ID: ID origen
-Closing: Cierre
Origin State: Estado origen
Destination State: Estado destino
Liters: Litros
Available Lines: Líneas disponibles
Destination ID: ID destino
-Destination ETD: ETD Destino
-Origin ETD: ETD Origen
Move tickets: Mover tickets
Move confirmation: ¿Desea mover {{checked}} tickets hacia el futuro?
Success: Tickets movidos correctamente
-ETD: Tiempo estimado de entrega
IPT: Encajado
-FREE: Libre
-DELIVERED: Servido
-ON_PREPARATION: En preparacion
-PACKED: Encajado
+Origin Date: Fecha origen
+Destination Date: Fecha destino
diff --git a/modules/ticket/front/index.js b/modules/ticket/front/index.js
index 6106a22eb..b49c6d49b 100644
--- a/modules/ticket/front/index.js
+++ b/modules/ticket/front/index.js
@@ -32,7 +32,6 @@ import './weekly';
import './dms/index';
import './dms/create';
import './dms/edit';
-import './sms';
import './boxing';
import './future';
import './future-search-panel';
diff --git a/modules/ticket/front/sms/index.html b/modules/ticket/front/sms/index.html
deleted file mode 100644
index 97bdfef14..000000000
--- a/modules/ticket/front/sms/index.html
+++ /dev/null
@@ -1,45 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{'Characters remaining' | translate}}:
-
- {{$ctrl.charactersRemaining()}}
-
-
-
-
-
-
-
- Send
-
-
\ No newline at end of file
diff --git a/modules/ticket/front/sms/index.spec.js b/modules/ticket/front/sms/index.spec.js
deleted file mode 100644
index b133db04d..000000000
--- a/modules/ticket/front/sms/index.spec.js
+++ /dev/null
@@ -1,71 +0,0 @@
-import './index';
-
-describe('Ticket', () => {
- describe('Component vnTicketSms', () => {
- let controller;
- let $httpBackend;
-
- beforeEach(ngModule('ticket'));
-
- beforeEach(inject(($componentController, $rootScope, _$httpBackend_) => {
- $httpBackend = _$httpBackend_;
- let $scope = $rootScope.$new();
- const $element = angular.element(' ');
- controller = $componentController('vnTicketSms', {$element, $scope});
- controller.$.message = {
- input: {
- value: 'My SMS'
- }
- };
- }));
-
- describe('onResponse()', () => {
- it('should perform a POST query and show a success snackbar', () => {
- let params = {ticketId: 11, destinationFk: 1101, destination: 111111111, message: 'My SMS'};
- controller.sms = {ticketId: 11, destinationFk: 1101, destination: 111111111, message: 'My SMS'};
-
- jest.spyOn(controller.vnApp, 'showMessage');
- $httpBackend.expect('POST', `Tickets/11/sendSms`, params).respond(200, params);
-
- controller.onResponse();
- $httpBackend.flush();
-
- expect(controller.vnApp.showMessage).toHaveBeenCalledWith('SMS sent!');
- });
-
- it('should call onResponse without the destination and show an error snackbar', () => {
- controller.sms = {destinationFk: 1101, message: 'My SMS'};
-
- jest.spyOn(controller.vnApp, 'showError');
-
- controller.onResponse();
-
- expect(controller.vnApp.showError).toHaveBeenCalledWith(`The destination can't be empty`);
- });
-
- it('should call onResponse without the message and show an error snackbar', () => {
- controller.sms = {destinationFk: 1101, destination: 222222222};
-
- jest.spyOn(controller.vnApp, 'showError');
-
- controller.onResponse();
-
- expect(controller.vnApp.showError).toHaveBeenCalledWith(`The message can't be empty`);
- });
- });
-
- describe('charactersRemaining()', () => {
- it('should return the characters remaining in a element', () => {
- controller.$.message = {
- input: {
- value: 'My message 0€'
- }
- };
-
- let result = controller.charactersRemaining();
-
- expect(result).toEqual(145);
- });
- });
- });
-});
diff --git a/modules/ticket/front/sms/locale/es.yml b/modules/ticket/front/sms/locale/es.yml
deleted file mode 100644
index 64c3fcca6..000000000
--- a/modules/ticket/front/sms/locale/es.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-Send SMS: Enviar SMS
-Destination: Destinatario
-Message: Mensaje
-SMS sent!: ¡SMS enviado!
-Characters remaining: Carácteres restantes
-The destination can't be empty: El destinatario no puede estar vacio
-The message can't be empty: El mensaje no puede estar vacio
-The message it's too long: El mensaje es demasiado largo
-Special characters like accents counts as a multiple: Carácteres especiales como los acentos cuentan como varios
\ No newline at end of file
diff --git a/modules/ticket/front/sms/style.scss b/modules/ticket/front/sms/style.scss
deleted file mode 100644
index 84571a5f4..000000000
--- a/modules/ticket/front/sms/style.scss
+++ /dev/null
@@ -1,5 +0,0 @@
-@import "variables";
-
-.SMSDialog {
- min-width: 400px
-}
\ No newline at end of file
diff --git a/print/templates/email/supplier-pay-method-update/assets/css/import.js b/print/templates/email/supplier-pay-method-update/assets/css/import.js
new file mode 100644
index 000000000..4b4bb7086
--- /dev/null
+++ b/print/templates/email/supplier-pay-method-update/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/supplier-pay-method-update/locale/en.yml b/print/templates/email/supplier-pay-method-update/locale/en.yml
new file mode 100644
index 000000000..f04ccc5ce
--- /dev/null
+++ b/print/templates/email/supplier-pay-method-update/locale/en.yml
@@ -0,0 +1,3 @@
+subject: Pay method updated
+title: Pay method updated
+description: The pay method of the supplier {0} has been updated from {1} to {2}
diff --git a/print/templates/email/supplier-pay-method-update/locale/es.yml b/print/templates/email/supplier-pay-method-update/locale/es.yml
new file mode 100644
index 000000000..59ee0e02f
--- /dev/null
+++ b/print/templates/email/supplier-pay-method-update/locale/es.yml
@@ -0,0 +1,3 @@
+subject: Método de pago actualizado
+title: Método de pago actualizado
+description: Se ha actualizado el método de pago del proveedor {0} de {1} a {2}
diff --git a/print/templates/email/supplier-pay-method-update/supplier-pay-method-update.html b/print/templates/email/supplier-pay-method-update/supplier-pay-method-update.html
new file mode 100644
index 000000000..df8543cd9
--- /dev/null
+++ b/print/templates/email/supplier-pay-method-update/supplier-pay-method-update.html
@@ -0,0 +1,8 @@
+
+
+
diff --git a/print/templates/email/supplier-pay-method-update/supplier-pay-method-update.js b/print/templates/email/supplier-pay-method-update/supplier-pay-method-update.js
new file mode 100755
index 000000000..283b2689c
--- /dev/null
+++ b/print/templates/email/supplier-pay-method-update/supplier-pay-method-update.js
@@ -0,0 +1,23 @@
+const Component = require(`vn-print/core/component`);
+const emailBody = new Component('email-body');
+
+module.exports = {
+ name: 'supplier-pay-method-update',
+ components: {
+ 'email-body': emailBody.build(),
+ },
+ props: {
+ name: {
+ type: String,
+ required: true
+ },
+ oldPayMethod: {
+ type: String,
+ required: true
+ },
+ newPayMethod: {
+ type: String,
+ required: true
+ }
+ }
+};
diff --git a/print/templates/reports/entry-order/entry-order.html b/print/templates/reports/entry-order/entry-order.html
index bdc4b0759..26294787b 100644
--- a/print/templates/reports/entry-order/entry-order.html
+++ b/print/templates/reports/entry-order/entry-order.html
@@ -20,7 +20,7 @@
{{$t('ref')}}
- {{entry.ref}}
+ {{entry.invoiceNumber}}
diff --git a/print/templates/reports/entry-order/sql/entry.sql b/print/templates/reports/entry-order/sql/entry.sql
index 44feaae01..57b8d9293 100644
--- a/print/templates/reports/entry-order/sql/entry.sql
+++ b/print/templates/reports/entry-order/sql/entry.sql
@@ -1,10 +1,10 @@
SELECT
e.id,
- e.ref,
+ e.invoiceNumber,
e.notes,
c.code companyCode,
t.landed
FROM entry e
JOIN travel t ON t.id = e.travelFk
JOIN company c ON c.id = e.companyFk
-WHERE e.id = ?
\ No newline at end of file
+WHERE e.id = ?
diff --git a/print/templates/reports/extra-community/extra-community.html b/print/templates/reports/extra-community/extra-community.html
index 42afedc76..6a46cc689 100644
--- a/print/templates/reports/extra-community/extra-community.html
+++ b/print/templates/reports/extra-community/extra-community.html
@@ -49,7 +49,7 @@
{{entry.supplierName}}
- {{entry.ref}}
+ {{entry.reference}}
{{entry.volumeKg | number($i18n.locale)}}
{{entry.loadedKg | number($i18n.locale)}}
{{entry.stickers}}
diff --git a/print/templates/reports/extra-community/sql/entries.sql b/print/templates/reports/extra-community/sql/entries.sql
index a90bf8b0b..84dc497c0 100644
--- a/print/templates/reports/extra-community/sql/entries.sql
+++ b/print/templates/reports/extra-community/sql/entries.sql
@@ -1,7 +1,7 @@
SELECT
e.id,
e.travelFk,
- e.ref,
+ e.reference,
s.name AS supplierName,
SUM(b.stickers) AS stickers,
CAST(SUM(b.weight * b.stickers) as DECIMAL(10,0)) as loadedKg,
@@ -15,4 +15,4 @@ SELECT
JOIN supplier s ON s.id = e.supplierFk
JOIN vn.volumeConfig vc
WHERE t.id IN(?)
- GROUP BY e.id
\ No newline at end of file
+ GROUP BY e.id
diff --git a/print/templates/reports/invoiceIn/invoiceIn.html b/print/templates/reports/invoiceIn/invoiceIn.html
index 69ce3d0f2..f101f7408 100644
--- a/print/templates/reports/invoiceIn/invoiceIn.html
+++ b/print/templates/reports/invoiceIn/invoiceIn.html
@@ -5,9 +5,8 @@
-
-
-
{{$t('title')}}
+
+
@@ -16,7 +15,7 @@
{{$t('invoiceId')}}
- {{invoice.id}}
+ {{invoice.supplierRef}}
{{$t('date')}}
@@ -26,7 +25,7 @@
-
+
@@ -43,7 +42,7 @@
-
{{$t('invoiceId')}}
+ {{$t('entry')}}
@@ -64,7 +63,7 @@
- {{entry.ref}}
+ {{entry.reference}}
@@ -82,7 +81,7 @@
{{buy.name}}
{{buy.quantity}}
- {{buy.buyingValue}}
+ {{buy.buyingValue | currency('EUR', $i18n.locale)}}
{{buyImport(buy) | currency('EUR', $i18n.locale)}}
@@ -103,27 +102,31 @@
+
-
+
+
+
+
+
{{$t('signer.received')}}:
+
{{$t('signer.signed')}}:
+
+
+
+
+
{{$t('taxBreakdown')}}
-
-
- {{$t('type')}}
- {{$t('taxBase')}}
- {{$t('tax')}}
- {{$t('fee')}}
-
-
{{tax.name}}
- {{tax.taxableBase | currency('EUR', $i18n.locale)}}
- {{tax.rate | percentage}}
+ {{tax.taxableBase | currency('EUR', $i18n.locale)}}
+
+ {{(tax.rate / 100) | percentage}}
{{tax.vat | currency('EUR', $i18n.locale)}}
@@ -150,28 +153,16 @@
-
-
-
-
-
-
{{$t('payMethod')}}
-
{{invoice.payMethod}}
-
-
-
-
+
+
+
-
diff --git a/print/templates/reports/invoiceIn/invoiceIn.js b/print/templates/reports/invoiceIn/invoiceIn.js
index 40dd25a5b..03549c276 100755
--- a/print/templates/reports/invoiceIn/invoiceIn.js
+++ b/print/templates/reports/invoiceIn/invoiceIn.js
@@ -9,6 +9,16 @@ module.exports = {
this.invoice = await this.fetchInvoice(this.id);
this.taxes = await this.fetchTaxes(this.id);
+ let defaultTax = await this.fetchDefaultTax();
+
+ if (defaultTax) {
+ defaultTax = Object.assign(defaultTax, {
+ taxableBase: 0,
+ vat: (this.taxTotal() * defaultTax.rate / 100)
+ });
+ this.taxes.push(defaultTax);
+ }
+
if (!this.invoice)
throw new Error('Something went wrong');
@@ -43,6 +53,9 @@ module.exports = {
fetchBuy(id) {
return this.rawSqlFromDef('buy', [id]);
},
+ fetchDefaultTax() {
+ return this.findOneFromDef('defaultTax');
+ },
async fetchTaxes(id) {
const taxes = await this.rawSqlFromDef(`taxes`, [id]);
return this.taxVat(taxes);
diff --git a/print/templates/reports/invoiceIn/locale/en.yml b/print/templates/reports/invoiceIn/locale/en.yml
index 92d3b0c2d..5f41a9ceb 100644
--- a/print/templates/reports/invoiceIn/locale/en.yml
+++ b/print/templates/reports/invoiceIn/locale/en.yml
@@ -1,6 +1,6 @@
-reportName: invoice
-title: Agricultural invoice
-invoiceId: Agricultural invoice
+reportName: agricultural receip
+title: Agricultural receip
+invoiceId: Agricultural receip
supplierId: Proveedor
invoiceData: Invoice data
reference: Reference
@@ -23,3 +23,8 @@ subtotal: Subtotal
taxBreakdown: Tax breakdown
observations: Observations
payMethod: Pay method
+entry: Entry
+signer:
+ received: Received
+ signed: Signature
+footer: Passive subject covered by the special agrarian regime. Please send this duly signed and sealed copy. Thanks.
diff --git a/print/templates/reports/invoiceIn/locale/es.yml b/print/templates/reports/invoiceIn/locale/es.yml
index f2fb28e64..90f7db6bd 100644
--- a/print/templates/reports/invoiceIn/locale/es.yml
+++ b/print/templates/reports/invoiceIn/locale/es.yml
@@ -1,6 +1,6 @@
-reportName: factura
-title: Factura Agrícola
-invoiceId: Factura Agrícola
+reportName: recibo agrícola
+title: Recibo Agrícola
+invoiceId: Recibo Agrícola
supplierId: Proveedor
invoiceData: Datos de facturación
reference: Referencia
@@ -23,3 +23,8 @@ subtotal: Subtotal
taxBreakdown: Desglose impositivo
observations: Observaciones
payMethod: Método de pago
+entry: Entrada
+signer:
+ received: Recibí
+ signed: Firma y sello
+footer: Sujeto pasivo acogido al régimen especial agrario. Les rogamos remitan esta copia debidamente firmada y sellada. Gracias.
diff --git a/print/templates/reports/invoiceIn/sql/defaultTax.sql b/print/templates/reports/invoiceIn/sql/defaultTax.sql
new file mode 100644
index 000000000..25f8a7090
--- /dev/null
+++ b/print/templates/reports/invoiceIn/sql/defaultTax.sql
@@ -0,0 +1,5 @@
+SELECT
+ id,
+ retentionRate rate,
+ retentionName name
+ FROM invoiceInConfig;
diff --git a/print/templates/reports/invoiceIn/sql/entry.sql b/print/templates/reports/invoiceIn/sql/entry.sql
index 0b29cd81c..d81a81afb 100644
--- a/print/templates/reports/invoiceIn/sql/entry.sql
+++ b/print/templates/reports/invoiceIn/sql/entry.sql
@@ -1,7 +1,7 @@
SELECT
e.id,
t.landed,
- e.ref
+ e.reference
FROM entry e
JOIN invoiceIn i ON i.id = e.invoiceInFk
JOIN travel t ON t.id = e.travelFk
diff --git a/print/templates/reports/invoiceIn/sql/invoice.sql b/print/templates/reports/invoiceIn/sql/invoice.sql
index fe9ef1e9e..eea8e81a5 100644
--- a/print/templates/reports/invoiceIn/sql/invoice.sql
+++ b/print/templates/reports/invoiceIn/sql/invoice.sql
@@ -1,5 +1,5 @@
SELECT
- i.id,
+ i.supplierRef,
s.id supplierId,
i.created,
s.name,
diff --git a/print/templates/reports/invoiceIn/sql/taxes.sql b/print/templates/reports/invoiceIn/sql/taxes.sql
index 20df33f83..07b7be822 100644
--- a/print/templates/reports/invoiceIn/sql/taxes.sql
+++ b/print/templates/reports/invoiceIn/sql/taxes.sql
@@ -5,4 +5,5 @@ SELECT
FROM invoiceIn ii
JOIN invoiceInTax iit ON ii.id = iit.invoiceInFk
JOIN sage.TiposIva ti ON ti.CodigoIva = iit.taxTypeSageFk
- WHERE ii.id = ?;
+ WHERE ii.id = ?
+ ORDER BY name DESC;
diff --git a/print/templates/reports/supplier-campaign-metrics/sql/entries.sql b/print/templates/reports/supplier-campaign-metrics/sql/entries.sql
index aa458dda0..b48e99c23 100644
--- a/print/templates/reports/supplier-campaign-metrics/sql/entries.sql
+++ b/print/templates/reports/supplier-campaign-metrics/sql/entries.sql
@@ -1,6 +1,6 @@
SELECT
e.id,
- e.ref,
+ e.reference,
e.supplierFk,
t.shipped
FROM vn.entry e
diff --git a/print/templates/reports/supplier-campaign-metrics/supplier-campaign-metrics.html b/print/templates/reports/supplier-campaign-metrics/supplier-campaign-metrics.html
index fd6ee5725..baff51bfe 100644
--- a/print/templates/reports/supplier-campaign-metrics/supplier-campaign-metrics.html
+++ b/print/templates/reports/supplier-campaign-metrics/supplier-campaign-metrics.html
@@ -39,7 +39,7 @@
{{$t('entry')}} {{entry.id}}
{{$t('dated')}} {{entry.shipped | date('%d-%m-%Y')}}
- {{$t('reference')}} {{entry.ref}}
+ {{$t('reference')}} {{entry.reference}}