232201_test_to_master #1582

Merged
alexm merged 126 commits from 232201_test_to_master into master 2023-06-01 06:16:49 +00:00
50 changed files with 292 additions and 324 deletions
Showing only changes of commit 0dea1dfd9e - Show all commits

View File

@ -5,19 +5,38 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [2316.01] - 2023-05-04 ## [2320.01] - 2023-05-25
### Added
-
### Changed
-
### Fixed
-
## [2318.01] - 2023-05-08
### Added ### Added
- (Usuarios -> Histórico) Nueva sección - (Usuarios -> Histórico) Nueva sección
- (Roles -> Histórico) Nueva sección - (Roles -> Histórico) Nueva sección
<<<<<<< HEAD
- (Trabajadores -> Dar de alta) Permite elegir el método de pago - (Trabajadores -> Dar de alta) Permite elegir el método de pago
=======
- (General -> Traducciones) Correo de bienvenida a clientes al portugués y al francés
>>>>>>> 8a843b37bd9067b6be1dfa090d557b59a0111bcf
### Changed ### Changed
- (Artículo -> Precio fijado) Modificado el buscador superior por uno lateral - (Artículo -> Precio fijado) Modificado el buscador superior por uno lateral
- (Trabajadores -> Dar de alta) Quitada obligatoriedad del iban - (Trabajadores -> Dar de alta) Quitada obligatoriedad del iban
### Fixed ### Fixed
- - (Ticket -> Boxing) Arreglado selección de horas
- (Cesta -> Índice) Optimizada búsqueda
## [2314.01] - 2023-04-20 ## [2314.01] - 2023-04-20

View File

@ -34,6 +34,8 @@ async function test() {
app.boot(bootOptions, app.boot(bootOptions,
err => err ? reject(err) : resolve()); err => err ? reject(err) : resolve());
}); });
// FIXME: Workaround to wait for loopback to be ready
await app.models.Application.status();
const Jasmine = require('jasmine'); const Jasmine = require('jasmine');
const jasmine = new Jasmine(); const jasmine = new Jasmine();
@ -53,7 +55,7 @@ async function test() {
const JunitReporter = require('jasmine-reporters'); const JunitReporter = require('jasmine-reporters');
jasmine.addReporter(new JunitReporter.JUnitXmlReporter()); jasmine.addReporter(new JunitReporter.JUnitXmlReporter());
jasmine.jasmine.DEFAULT_TIMEOUT_INTERVAL = 90000; jasmine.jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000;
jasmine.exitOnCompletion = true; jasmine.exitOnCompletion = true;
} }

View File

@ -1,5 +0,0 @@
UPDATE vn.supplier s
JOIN vn.country c ON c.id = s.countryFk
SET s.nif = MID(REPLACE(s.nif, ' ', ''), 3, LENGTH(REPLACE(s.nif, ' ', '')) - 1)
WHERE s.isVies = TRUE
AND c.code = LEFT(REPLACE(s.nif, ' ', ''), 2);

View File

@ -1,5 +0,0 @@
UPDATE IGNORE vn.client c
JOIN vn.country co ON co.id = c.countryFk
SET c.fi = MID(REPLACE(c.fi, ' ', ''), 3, LENGTH(REPLACE(c.fi, ' ', '')) - 1)
WHERE c.isVies = TRUE
AND co.code = LEFT(REPLACE(c.fi, ' ', ''), 2);

View File

@ -0,0 +1,77 @@
CREATE OR REPLACE
ALGORITHM = UNDEFINED VIEW `vn`.`zoneEstimatedDelivery` AS
select
`t`.`zoneFk` AS `zoneFk`,
cast(`util`.`VN_CURDATE`() + interval hour(ifnull(`zc`.`hour`, `z`.`hour`)) * 60 + minute(ifnull(`zc`.`hour`, `z`.`hour`)) minute as time) AS `hourTheoretical`,
cast(sum(`sv`.`volume`) as decimal(5, 1)) AS `totalVolume`,
cast(sum(if(`s`.`alertLevel` < 2, `sv`.`volume`, 0)) as decimal(5, 1)) AS `remainingVolume`,
greatest(
ifnull(`lhp`.`m3`, 0),
ifnull(`dl`.`minSpeed`, 0)
) AS `speed`,
cast(`zc`.`hour` + interval -sum(if(`s`.`alertLevel` < 2, `sv`.`volume`, 0)) * 60 / greatest(ifnull(`lhp`.`m3`, 0), ifnull(`dl`.`minSpeed`, 0)) minute as time) AS `hourEffective`,
floor(-sum(if(`s`.`alertLevel` < 2, `sv`.`volume`, 0)) * 60 / greatest(ifnull(`lhp`.`m3`, 0), ifnull(`dl`.`minSpeed`, 0))) AS `minutesLess`,
cast(`zc`.`hour` + interval -sum(if(`s`.`alertLevel` < 2, `sv`.`volume`, 0)) * 60 / greatest(ifnull(`lhp`.`m3`, 0), ifnull(`dl`.`minSpeed`, 0)) minute as time) AS `etc`
from
(
(
(
(
(
(
(
(
(
`vn`.`ticket` `t`
join `vn`.`ticketStateToday` `tst` on
(
`tst`.`ticket` = `t`.`id`
)
)
join `vn`.`state` `s` on
(
`s`.`id` = `tst`.`state`
)
)
join `vn`.`saleVolume` `sv` on
(
`sv`.`ticketFk` = `t`.`id`
)
)
left join `vn`.`lastHourProduction` `lhp` on
(
`lhp`.`warehouseFk` = `t`.`warehouseFk`
)
)
join `vn`.`warehouse` `w` on
(
`w`.`id` = `t`.`warehouseFk`
)
)
join `vn`.`warehouseAlias` `wa` on
(
`wa`.`id` = `w`.`aliasFk`
)
)
straight_join `vn`.`zone` `z` on
(
`z`.`id` = `t`.`zoneFk`
)
)
left join `vn`.`zoneClosure` `zc` on
(
`zc`.`zoneFk` = `t`.`zoneFk`
and `zc`.`dated` = `util`.`VN_CURDATE`()
)
)
left join `cache`.`departure_limit` `dl` on
(
`dl`.`warehouse_id` = `t`.`warehouseFk`
and `dl`.`fecha` = `util`.`VN_CURDATE`()
)
)
where
`w`.`hasProduction` <> 0
and cast(`t`.`shipped` as date) = `util`.`VN_CURDATE`()
group by
`t`.`zoneFk`;

View File

@ -1 +1 @@
ALTER TABLE `vn`.`ticketConfig` ADD daysForWarningClaim INT DEFAULT 2 NOT NULL COMMENT 'dias restantes hasta que salte el aviso de reclamación fuerade plazo'; ALTER TABLE `vn`.`ticketConfig` ADD daysForWarningClaim INT DEFAULT 2 NOT NULL COMMENT 'dias restantes hasta que salte el aviso de reclamación fuera de plazo';

View File

@ -0,0 +1,5 @@
UPDATE `vn`.`supplier` s
JOIN `vn`.`country` c ON c.id = s.countryFk
SET s.nif = MID(REPLACE(s.nif, ' ', ''), 3, LENGTH(REPLACE(s.nif, ' ', '')) - 1)
WHERE s.isVies = TRUE
AND c.code = LEFT(REPLACE(s.nif, ' ', ''), 2);

View File

@ -0,0 +1,5 @@
UPDATE IGNORE `vn`.`client` c
JOIN `vn`.`country` co ON co.id = c.countryFk
SET c.fi = MID(REPLACE(c.fi, ' ', ''), 3, LENGTH(REPLACE(c.fi, ' ', '')) - 1)
WHERE c.isVies = TRUE
AND co.code = LEFT(REPLACE(c.fi, ' ', ''), 2);

View File

View File

@ -285,21 +285,6 @@ export default {
clientMandate: { clientMandate: {
firstMandateText: 'vn-client-mandate vn-card vn-table vn-tbody > vn-tr' firstMandateText: 'vn-client-mandate vn-card vn-table vn-tbody > vn-tr'
}, },
clientBalance: {
company: 'vn-client-balance-index vn-autocomplete[ng-model="$ctrl.companyId"]',
newPaymentButton: `vn-float-button`,
newPaymentBank: '.vn-dialog.shown vn-autocomplete[ng-model="$ctrl.bankFk"]',
newPaymentAmount: '.vn-dialog.shown vn-input-number[ng-model="$ctrl.amountPaid"]',
newDescription: 'vn-textfield[ng-model="$ctrl.receipt.description"]',
deliveredAmount: '.vn-dialog vn-input-number[ng-model="$ctrl.deliveredAmount"]',
refundAmount: '.vn-dialog vn-input-number[ng-model="$ctrl.amountToReturn"]',
saveButton: '.vn-dialog.shown [response="accept"]',
anyBalanceLine: 'vn-client-balance-index vn-tbody > vn-tr',
firstLineBalance: 'vn-client-balance-index vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(8)',
firstLineReference: 'vn-client-balance-index vn-tbody > vn-tr:nth-child(1) > vn-td-editable',
firstLineReferenceInput: 'vn-client-balance-index vn-tbody > vn-tr:nth-child(1) > vn-td-editable > div > field > vn-textfield',
compensationButton: 'vn-client-balance-index vn-icon-button[vn-dialog="send_compensation"]'
},
webPayment: { webPayment: {
confirmFirstPaymentButton: 'vn-client-web-payment vn-tr:nth-child(1) vn-icon-button[icon="done_all"]', confirmFirstPaymentButton: 'vn-client-web-payment vn-tr:nth-child(1) vn-icon-button[icon="done_all"]',
firstPaymentConfirmed: 'vn-client-web-payment vn-tr:nth-child(1) vn-icon[icon="check"]' firstPaymentConfirmed: 'vn-client-web-payment vn-tr:nth-child(1) vn-icon[icon="check"]'
@ -841,15 +826,6 @@ export default {
landedDatePicker: 'vn-date-picker[label="Landed"]', landedDatePicker: 'vn-date-picker[label="Landed"]',
createButton: 'button[type=submit]' createButton: 'button[type=submit]'
}, },
orderSummary: {
id: 'vn-order-summary vn-one:nth-child(1) > vn-label-value:nth-child(1) span',
alias: 'vn-order-summary vn-one:nth-child(1) > vn-label-value:nth-child(2) span',
consignee: 'vn-order-summary vn-one:nth-child(2) > vn-label-value:nth-child(6) span',
subtotal: 'vn-order-summary vn-one.taxes > p:nth-child(1)',
vat: 'vn-order-summary vn-one.taxes > p:nth-child(2)',
total: 'vn-order-summary vn-one.taxes > p:nth-child(3)',
sale: 'vn-order-summary vn-tbody > vn-tr',
},
orderCatalog: { orderCatalog: {
plantRealmButton: 'vn-order-catalog > vn-side-menu vn-icon[icon="icon-plant"]', plantRealmButton: 'vn-order-catalog > vn-side-menu vn-icon[icon="icon-plant"]',
type: 'vn-order-catalog vn-autocomplete[data="$ctrl.itemTypes"]', type: 'vn-order-catalog vn-autocomplete[data="$ctrl.itemTypes"]',

View File

@ -29,19 +29,16 @@ describe('Client Add greuge path', () => {
expect(message.text).toContain('Some fields are invalid'); expect(message.text).toContain('Some fields are invalid');
}); });
it(`should create a new greuge with all its data`, async() => { it(`should create a new greuge with all its data and confirm the greuge was added to the list`, async() => {
await page.write(selectors.clientGreuge.amount, '999'); await page.write(selectors.clientGreuge.amount, '999');
await page.waitForTextInField(selectors.clientGreuge.amount, '999'); await page.waitForTextInField(selectors.clientGreuge.amount, '999');
await page.write(selectors.clientGreuge.description, 'new armor for Batman!'); await page.write(selectors.clientGreuge.description, 'new armor for Batman!');
await page.waitToClick(selectors.clientGreuge.saveButton); await page.waitToClick(selectors.clientGreuge.saveButton);
const message = await page.waitForSnackbar(); const message = await page.waitForSnackbar();
expect(message.text).toContain('Data saved!');
});
it('should confirm the greuge was added to the list', async() => {
const result = await page.waitToGetProperty(selectors.clientGreuge.firstGreugeText, 'innerText'); const result = await page.waitToGetProperty(selectors.clientGreuge.firstGreugeText, 'innerText');
expect(message.text).toContain('Data saved!');
expect(result).toContain(999); expect(result).toContain(999);
expect(result).toContain('new armor for Batman!'); expect(result).toContain('new armor for Batman!');
expect(result).toContain('Diff'); expect(result).toContain('Diff');

View File

@ -1,6 +1,17 @@
import selectors from '../../helpers/selectors'; import selectors from '../../helpers/selectors';
import getBrowser from '../../helpers/puppeteer'; import getBrowser from '../../helpers/puppeteer';
const $ = {
company: 'vn-client-balance-index vn-autocomplete[ng-model="$ctrl.companyId"]',
newPaymentButton: `vn-float-button`,
newPayment: '.vn-dialog.shown',
refundAmount: '.vn-dialog.shown [vn-name="amountToReturn"]',
saveButton: '.vn-dialog.shown [response="accept"]',
firstLineBalance: 'vn-client-balance-index vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(8)',
firstLineReference: 'vn-client-balance-index vn-tbody > vn-tr:nth-child(1) > vn-td-editable',
firstLineReferenceInput: 'vn-client-balance-index vn-tbody > vn-tr:nth-child(1) > vn-td-editable vn-textfield',
};
describe('Client balance path', () => { describe('Client balance path', () => {
let browser; let browser;
let page; let page;
@ -18,125 +29,100 @@ describe('Client balance path', () => {
it('should now edit the local user config data', async() => { it('should now edit the local user config data', async() => {
await page.waitToClick(selectors.globalItems.userMenuButton); await page.waitToClick(selectors.globalItems.userMenuButton);
await page.autocompleteSearch(selectors.globalItems.userLocalCompany, 'CCs'); await page.autocompleteSearch(selectors.globalItems.userLocalCompany, 'CCs');
const message = await page.waitForSnackbar(); const companyMessage = await page.waitForSnackbar();
expect(message.text).toContain('Data saved!');
});
it('should access to the balance section to check the data shown matches the local settings', async() => {
await page.accessToSection('client.card.balance.index'); await page.accessToSection('client.card.balance.index');
let result = await page.waitToGetProperty(selectors.clientBalance.company, 'value'); const company = await page.getValue($.company);
expect(result).toEqual('CCs');
});
it('should now clear the user local settings', async() => {
await page.waitToClick(selectors.globalItems.userMenuButton); await page.waitToClick(selectors.globalItems.userMenuButton);
await page.clearInput(selectors.globalItems.userConfigThirdAutocomplete); await page.clearInput(selectors.globalItems.userConfigThirdAutocomplete);
const message = await page.waitForSnackbar(); const message = await page.waitForSnackbar();
expect(message.text).toContain('Data saved!');
});
it('should reload the section', async() => {
await page.closePopup(); await page.closePopup();
await page.reloadSection('client.card.balance.index'); await page.reloadSection('client.card.balance.index');
expect(companyMessage.isSuccess).toBeTrue();
expect(company).toEqual('CCs');
expect(message.isSuccess).toBeTrue();
}); });
it('should create a new payment that clears the debt', async() => { it('should create a new payment that clears the debt', async() => {
await page.closePopup(); await page.waitToClick($.newPaymentButton);
await page.waitToClick(selectors.clientBalance.newPaymentButton); await page.fillForm($.newPayment, {
await page.autocompleteSearch(selectors.clientBalance.newPaymentBank, 'Cash'); bank: 'Cash',
await page.clearInput(selectors.clientBalance.newDescription); description: 'Description',
await page.write(selectors.clientBalance.newDescription, 'Description'); viewReceipt: false
await page.waitToClick(selectors.clientBalance.saveButton); });
await page.respondToDialog('accept');
const message = await page.waitForSnackbar(); const message = await page.waitForSnackbar();
expect(message.text).toContain('Data saved!'); expect(message.isSuccess).toBeTrue();
}); });
it('should edit the 1st line reference', async() => { it('should edit the 1st line reference and check data', async() => {
await page.waitToClick(selectors.clientBalance.firstLineReference); await page.waitToClick($.firstLineReference);
await page.write(selectors.clientBalance.firstLineReferenceInput, 'Miscellaneous payment'); await page.write($.firstLineReferenceInput, 'Miscellaneous payment');
await page.keyboard.press('Enter'); await page.keyboard.press('Enter');
const message = await page.waitForSnackbar(); const message = await page.waitForSnackbar();
expect(message.text).toContain('Data saved!');
});
it('should check balance is now 0, the reference was saved and the company is now VNL becouse the user local settings were removed', async() => {
await page.waitForSpinnerLoad(); await page.waitForSpinnerLoad();
let company = await page let company = await page.getValue($.company);
.waitToGetProperty(selectors.clientBalance.company, 'value'); let reference = await page.innerText($.firstLineReference);
let firstBalanceLine = await page.innerText($.firstLineBalance);
let reference = await page
.waitToGetProperty(selectors.clientBalance.firstLineReference, 'innerText');
let firstBalanceLine = await page
.waitToGetProperty(selectors.clientBalance.firstLineBalance, 'innerText');
expect(message.isSuccess).toBeTrue();
expect(company).toEqual('VNL'); expect(company).toEqual('VNL');
expect(reference).toEqual('Miscellaneous payment'); expect(reference).toEqual('Miscellaneous payment');
expect(firstBalanceLine).toContain('0.00'); expect(firstBalanceLine).toContain('0.00');
}); });
it('should create a new payment and check the cash comparison works correctly', async() => { it('should create a new payment, check the cash comparison works correctly and balance value is -100', async() => {
const amountPaid = '100'; await page.waitToClick($.newPaymentButton);
const cashHanded = '500'; await page.fillForm($.newPayment, {
const expectedRefund = '400'; amountPaid: 100,
description: 'Payment',
await page.waitToClick(selectors.clientBalance.newPaymentButton); deliveredAmount: 500,
await page.write(selectors.clientBalance.newPaymentAmount, amountPaid); viewReceipt: false
await page.clearInput(selectors.clientBalance.newDescription); });
await page.write(selectors.clientBalance.newDescription, 'Payment'); const refund = await page.getValue($.refundAmount);
await page.write(selectors.clientBalance.deliveredAmount, cashHanded); await page.respondToDialog('accept');
const refund = await page.waitToGetProperty(selectors.clientBalance.refundAmount, 'value');
await page.waitToClick(selectors.clientBalance.saveButton);
const message = await page.waitForSnackbar(); const message = await page.waitForSnackbar();
expect(refund).toEqual(expectedRefund); const result = await page.innerText($.firstLineBalance);
expect(message.text).toContain('Data saved!');
});
it('should check the balance value is now -100', async() => {
let result = await page
.waitToGetProperty(selectors.clientBalance.firstLineBalance, 'innerText');
expect(refund).toEqual('400');
expect(message.isSuccess).toBeTrue();
expect(result).toContain('-€100.00'); expect(result).toContain('-€100.00');
}); });
it('should create a new payment and check the cash exceeded the maximum', async() => { it('should create a new payment and check the cash exceeded the maximum', async() => {
const amountPaid = '1001'; await page.waitToClick($.newPaymentButton);
await page.fillForm($.newPayment, {
await page.closePopup(); bank: 'Cash',
await page.waitToClick(selectors.clientBalance.newPaymentButton); amountPaid: 1001,
await page.autocompleteSearch(selectors.clientBalance.newPaymentBank, 'Cash'); description: 'Payment'
await page.write(selectors.clientBalance.newPaymentAmount, amountPaid); });
await page.clearInput(selectors.clientBalance.newDescription); await page.waitToClick($.saveButton);
await page.write(selectors.clientBalance.newDescription, 'Payment');
await page.waitToClick(selectors.clientBalance.saveButton);
const message = await page.waitForSnackbar(); const message = await page.waitForSnackbar();
expect(message.text).toContain('Amount exceeded'); expect(message.text).toContain('Amount exceeded');
}); });
it('should create a new payment that sets the balance back to the original negative value', async() => { it('should create a new payment that sets the balance back to negative value and check it', async() => {
await page.closePopup(); await page.closePopup();
await page.waitToClick(selectors.clientBalance.newPaymentButton); await page.waitToClick($.newPaymentButton);
await page.autocompleteSearch(selectors.clientBalance.newPaymentBank, 'Pay on receipt');
await page.overwrite(selectors.clientBalance.newPaymentAmount, '-150'); await page.fillForm($.newPayment, {
await page.clearInput(selectors.clientBalance.newDescription); bank: 'Pay on receipt',
await page.write(selectors.clientBalance.newDescription, 'Description'); amountPaid: -150,
await page.waitToClick(selectors.clientBalance.saveButton); description: 'Description'
});
await page.respondToDialog('accept');
const message = await page.waitForSnackbar(); const message = await page.waitForSnackbar();
expect(message.text).toContain('Data saved!'); const result = await page.innerText($.firstLineBalance);
});
it('should check balance is now 50', async() => {
let result = await page
.waitToGetProperty(selectors.clientBalance.firstLineBalance, 'innerText');
expect(message.isSuccess).toBeTrue();
expect(result).toEqual('€50.00'); expect(result).toEqual('€50.00');
}); });
@ -149,12 +135,9 @@ describe('Client balance path', () => {
await page.waitForState('client.index'); await page.waitForState('client.index');
}); });
it('should now search for the user Petter Parker', async() => { it('should now search for the user Petter Parker not check the payment button is not present', async() => {
await page.accessToSearchResult('Petter Parker'); await page.accessToSearchResult('Petter Parker');
await page.accessToSection('client.card.balance.index'); await page.accessToSection('client.card.balance.index');
}); await page.waitForSelector($.newPaymentButton, {hidden: true});
it('should not be able to click the new payment button as it isnt present', async() => {
await page.waitForSelector(selectors.clientBalance.newPaymentButton, {hidden: true});
}); });
}); });

View File

@ -1,6 +1,11 @@
import selectors from '../../helpers/selectors';
import getBrowser from '../../helpers/puppeteer'; import getBrowser from '../../helpers/puppeteer';
const $ = {
company: 'vn-client-balance-index vn-autocomplete[ng-model="$ctrl.companyId"]',
compensationButton: 'vn-client-balance-index vn-icon-button[vn-dialog="send_compensation"]',
saveButton: '.vn-dialog.shown [response="accept"]'
};
describe('Client Send balance compensation', () => { describe('Client Send balance compensation', () => {
let browser; let browser;
let page; let page;
@ -17,9 +22,9 @@ describe('Client Send balance compensation', () => {
}); });
it(`should click on send compensation button`, async() => { it(`should click on send compensation button`, async() => {
await page.autocompleteSearch(selectors.clientBalance.company, 'VNL'); await page.autocompleteSearch($.company, 'VNL');
await page.waitToClick(selectors.clientBalance.compensationButton); await page.waitToClick($.compensationButton);
await page.waitToClick(selectors.clientBalance.saveButton); await page.waitToClick($.saveButton);
const message = await page.waitForSnackbar(); const message = await page.waitForSnackbar();
expect(message.text).toContain('Notification sent!'); expect(message.text).toContain('Notification sent!');

View File

@ -53,12 +53,4 @@ describe('Item edit tax path', () => {
expect(firstVatType).toEqual('Reduced VAT'); expect(firstVatType).toEqual('Reduced VAT');
}); });
// # #2680 Undo changes button bugs
xit(`should now click the undo changes button and see the form is restored`, async() => {
await page.waitToClick(selectors.itemTax.undoChangesButton);
const firstVatType = await page.waitToGetProperty(selectors.itemTax.firstClass, 'value');
expect(firstVatType).toEqual('General VAT');
});
}); });

View File

@ -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('20'); expect(result).toContain('10');
}); });
it('should go back to the original ticket sales section', async() => { it('should go back to the original ticket sales section', async() => {
@ -425,20 +425,6 @@ describe('Ticket Edit sale path', () => {
expect(result).toBeFalsy(); expect(result).toBeFalsy();
}); });
// tickets no longer update their totals instantly, a task performed ever 5-10 mins does it. disabled this test until it changes.
xit('should update all sales discount', async() => {
await page.closePopup();
await page.waitToClick(selectors.ticketSales.moreMenu);
await page.waitToClick(selectors.ticketSales.moreMenuUpdateDiscount);
await page.waitForSelector(selectors.ticketSales.moreMenuUpdateDiscountInput);
await page.type(selectors.ticketSales.moreMenuUpdateDiscountInput, '100');
await page.keyboard.press('Enter');
await page.waitForTextInElement(selectors.ticketSales.totalImport, '0.00');
const result = await page.waitToGetProperty(selectors.ticketSales.totalImport, 'innerText');
expect(result).toContain('0.00');
});
it('should log in as Production role and go to a target ticket summary', async() => { it('should log in as Production role and go to a target ticket summary', async() => {
await page.loginAndModule('production', 'ticket'); await page.loginAndModule('production', 'ticket');
await page.accessToSearchResult('13'); await page.accessToSearchResult('13');

View File

@ -1,5 +1,10 @@
import selectors from '../../helpers/selectors.js'; import selectors from '../../helpers/selectors.js';
import getBrowser from '../../helpers/puppeteer'; import getBrowser from '../../helpers/puppeteer';
const $ = {
newPayment: '.vn-dialog.shown',
anyBalanceLine: 'vn-client-balance-index vn-tbody > vn-tr',
firstLineReference: 'vn-client-balance-index vn-tbody > vn-tr:nth-child(1) > vn-td-editable'
};
describe('Ticket index payout path', () => { describe('Ticket index payout path', () => {
let browser; let browser;
@ -8,17 +13,14 @@ describe('Ticket index payout path', () => {
beforeAll(async() => { beforeAll(async() => {
browser = await getBrowser(); browser = await getBrowser();
page = browser.page; page = browser.page;
await page.loginAndModule('administrative', 'ticket');
await page.waitForState('ticket.index');
}); });
afterAll(async() => { afterAll(async() => {
await browser.close(); await browser.close();
}); });
it('should navigate to the ticket index', async() => {
await page.loginAndModule('administrative', 'ticket');
await page.waitForState('ticket.index');
});
it('should check the second ticket from a client and 1 of another', async() => { it('should check the second ticket from a client and 1 of another', async() => {
await page.waitToClick(selectors.globalItems.searchButton); await page.waitToClick(selectors.globalItems.searchButton);
await page.waitToClick(selectors.ticketsIndex.thirdTicketCheckbox); await page.waitToClick(selectors.ticketsIndex.thirdTicketCheckbox);
@ -42,27 +44,27 @@ describe('Ticket index payout path', () => {
await page.waitForSelector(selectors.ticketsIndex.payoutCompany); await page.waitForSelector(selectors.ticketsIndex.payoutCompany);
}); });
it('should fill the company and bank to perform a payout', async() => { it('should fill the company and bank to perform a payout and check a new balance line was entered', async() => {
await page.autocompleteSearch(selectors.ticketsIndex.payoutCompany, 'VNL'); await page.fillForm($.newPayment, {
await page.autocompleteSearch(selectors.ticketsIndex.payoutBank, 'cash'); company: 'VNL',
await page.write(selectors.clientBalance.newPaymentAmount, '100'); bank: 'cash',
await page.write(selectors.ticketsIndex.payoutDescription, 'Payment'); amountPaid: 100,
await page.waitToClick(selectors.ticketsIndex.submitPayout); description: 'Payment',
viewReceipt: false
});
await page.respondToDialog('accept');
const message = await page.waitForSnackbar(); const message = await page.waitForSnackbar();
expect(message.text).toContain('Data saved!');
});
it('should navigate to the client balance section and check a new balance line was entered', async() => {
await page.waitToClick(selectors.globalItems.homeButton); await page.waitToClick(selectors.globalItems.homeButton);
await page.selectModule('client'); await page.selectModule('client');
await page.accessToSearchResult('1101'); await page.accessToSearchResult('1101');
await page.accessToSection('client.card.balance.index'); await page.accessToSection('client.card.balance.index');
await page.waitForSelector(selectors.clientBalance.anyBalanceLine); await page.waitForSelector($.anyBalanceLine);
const count = await page.countElement(selectors.clientBalance.anyBalanceLine); const count = await page.countElement($.anyBalanceLine);
const reference = await page.waitToGetProperty(selectors.clientBalance.firstLineReference, 'innerText'); const reference = await page.innerText($.firstLineReference);
expect(message.isSuccess).toBeTrue();
expect(count).toEqual(4); expect(count).toEqual(4);
expect(reference).toContain('Cash, Albaran: 7, 8Payment'); expect(reference).toContain('Payment');
}); });
}); });

View File

@ -1,6 +1,15 @@
import selectors from '../../helpers/selectors.js';
import getBrowser from '../../helpers/puppeteer'; import getBrowser from '../../helpers/puppeteer';
const $ = {
id: 'vn-order-summary vn-one:nth-child(1) > vn-label-value:nth-child(1) span',
alias: 'vn-order-summary vn-one:nth-child(1) > vn-label-value:nth-child(2) span',
consignee: 'vn-order-summary vn-one:nth-child(2) > vn-label-value:nth-child(6) span',
subtotal: 'vn-order-summary vn-one.taxes > p:nth-child(1)',
vat: 'vn-order-summary vn-one.taxes > p:nth-child(2)',
total: 'vn-order-summary vn-one.taxes > p:nth-child(3)',
sale: 'vn-order-summary vn-tbody > vn-tr',
};
describe('Order summary path', () => { describe('Order summary path', () => {
let browser; let browser;
let page; let page;
@ -15,49 +24,23 @@ describe('Order summary path', () => {
await browser.close(); await browser.close();
}); });
it('should reach the order summary section', async() => { it('should reach the order summary section and check data', async() => {
await page.waitForState('order.card.summary'); await page.waitForState('order.card.summary');
});
it('should check the summary contains the order id', async() => { const id = await page.innerText($.id);
const result = await page.waitToGetProperty(selectors.orderSummary.id, 'innerText'); const alias = await page.innerText($.alias);
const consignee = await page.innerText($.consignee);
const subtotal = await page.innerText($.subtotal);
const vat = await page.innerText($.vat);
const total = await page.innerText($.total);
const sale = await page.countElement($.sale);
expect(result).toEqual('16'); expect(id).toEqual('16');
}); expect(alias).toEqual('Many places');
expect(consignee).toEqual('address 26 - Gotham (Province one)');
it('should check the summary contains the order alias', async() => { expect(subtotal.length).toBeGreaterThan(1);
const result = await page.waitToGetProperty(selectors.orderSummary.alias, 'innerText'); expect(vat.length).toBeGreaterThan(1);
expect(total.length).toBeGreaterThan(1);
expect(result).toEqual('Many places'); expect(sale).toBeGreaterThan(0);
});
it('should check the summary contains the order consignee', async() => {
const result = await page.waitToGetProperty(selectors.orderSummary.consignee, 'innerText');
expect(result).toEqual('address 26 - Gotham (Province one)');
});
it('should check the summary contains the order subtotal', async() => {
const result = await page.waitToGetProperty(selectors.orderSummary.subtotal, 'innerText');
expect(result.length).toBeGreaterThan(1);
});
it('should check the summary contains the order vat', async() => {
const result = await page.waitToGetProperty(selectors.orderSummary.vat, 'innerText');
expect(result.length).toBeGreaterThan(1);
});
it('should check the summary contains the order total', async() => {
const result = await page.waitToGetProperty(selectors.orderSummary.total, 'innerText');
expect(result.length).toBeGreaterThan(1);
});
it('should check the summary contains the order sales', async() => {
const result = await page.countElement(selectors.orderSummary.sale);
expect(result).toBeGreaterThan(0);
}); });
}); });

View File

@ -57,11 +57,4 @@ describe('Route tickets path', () => {
it('should now count how many tickets are in route to find one less', async() => { it('should now count how many tickets are in route to find one less', async() => {
await page.waitForNumberOfElements(selectors.routeTickets.anyTicket, 0); await page.waitForNumberOfElements(selectors.routeTickets.anyTicket, 0);
}); });
// #2862 updateVolume() route descriptor no actualiza volumen
xit('should confirm the route volume on the descriptor has been updated by the changes made', async() => {
const result = await page.waitToGetProperty(selectors.routeDescriptor.volume, 'innerText');
expect(result).toEqual('0 / 50 m³');
});
}); });

View File

@ -42,20 +42,6 @@ describe('Entry lastest buys path', () => {
expect(httpRequests.find(req => req.includes(('typeFk')))).toBeDefined(); expect(httpRequests.find(req => req.includes(('typeFk')))).toBeDefined();
}); });
it('should filter by from date', async() => {
await page.pickDate(selectors.entryLatestBuys.fromInput, new Date());
await page.waitToClick(selectors.entryLatestBuys.chip);
expect(httpRequests.find(req => req.includes(('from')))).toBeDefined();
});
it('should filter by to date', async() => {
await page.pickDate(selectors.entryLatestBuys.toInput, new Date());
await page.waitToClick(selectors.entryLatestBuys.chip);
expect(httpRequests.find(req => req.includes(('to')))).toBeDefined();
});
it('should filter by sales person', async() => { it('should filter by sales person', async() => {
await page.autocompleteSearch(selectors.entryLatestBuys.salesPersonInput, 'buyerNick'); await page.autocompleteSearch(selectors.entryLatestBuys.salesPersonInput, 'buyerNick');
await page.waitToClick(selectors.entryLatestBuys.chip); await page.waitToClick(selectors.entryLatestBuys.chip);

View File

@ -139,7 +139,7 @@ export default class CrudModel extends ModelProxy {
filter.limit = this.page * this.limit; filter.limit = this.page * this.limit;
} }
return this.sendRequest(filter, append); return this.sendRequest(filter, append, true);
} }
clear() { clear() {
@ -231,12 +231,12 @@ export default class CrudModel extends ModelProxy {
return params; return params;
} }
sendRequest(filter, append) { sendRequest(filter, append, loadMore) {
this.cancelRequest(); this.cancelRequest();
this.canceler = this.$q.defer(); this.canceler = this.$q.defer();
this.isPaging = append; this.isPaging = append;
if (!append && this.status != 'ready') if (!loadMore)
this.status = 'loading'; this.status = 'loading';
let params = Object.assign( let params = Object.assign(

View File

@ -150,7 +150,7 @@ describe('Component vnCrudModel', () => {
controller.loadMore(true); controller.loadMore(true);
expect(controller.sendRequest).toHaveBeenCalledWith({'skip': 2}, true); expect(controller.sendRequest).toHaveBeenCalledWith({'skip': 2}, true, true);
}); });
}); });

View File

@ -36,30 +36,6 @@ describe('Component vnPopover', () => {
expect(controller.emit).not.toHaveBeenCalledWith('open'); expect(controller.emit).not.toHaveBeenCalledWith('open');
}); });
// #1615 migrar karma a jest (this doesn't work anymore, needs fixing)
xit(`should check that popover is visible into the screen`, () => {
$parent.css({
backgroundColor: 'red',
position: 'absolute',
width: '50px',
height: '50px',
top: '0',
left: '100px'
});
controller.show($parent[0]);
let rect = controller.popover.getBoundingClientRect();
let style = controller.window.getComputedStyle(controller.element);
expect(style.visibility).toEqual('visible');
expect(style.display).not.toEqual('none');
expect(0).toBeLessThanOrEqual(rect.top);
expect(0).toBeLessThanOrEqual(rect.left);
expect(controller.window.innerHeight).toBeGreaterThan(rect.bottom);
expect(controller.window.innerWidth).toBeGreaterThan(rect.right);
});
}); });
describe('hide()', () => { describe('hide()', () => {

View File

@ -8,18 +8,8 @@ export default class Th {
$element.on('click', () => this.onToggleOrder()); $element.on('click', () => this.onToggleOrder());
} }
/**
* Changes the order if the cell has a field and defaultOrder property
*/
$onInit() { $onInit() {
if (!this.field) return; if (!this.field) return;
if (this.defaultOrder) {
this.order = this.defaultOrder;
this.table.applyOrder(this.field, this.order);
this.updateArrow();
}
this.updateArrow(); this.updateArrow();
} }
@ -82,9 +72,6 @@ ngModule.vnComponent('vnTh', {
template: require('./index.html'), template: require('./index.html'),
transclude: true, transclude: true,
controller: Th, controller: Th,
bindings: {
defaultOrder: '@?'
},
require: { require: {
table: '^^vnTable' table: '^^vnTable'
} }

View File

@ -17,17 +17,6 @@ describe('Component vnTh', () => {
controller.column.setAttribute('field', 'MyField'); controller.column.setAttribute('field', 'MyField');
})); }));
describe('onInit()', () => {
it(`should define controllers order as per defaultOrder then call setOrder()`, () => {
controller.defaultOrder = 'DESC';
jest.spyOn(controller.table, 'setOrder');
controller.$onInit();
expect(controller.order).toEqual('DESC');
expect(controller.table.setOrder).toHaveBeenCalledWith('MyField', 'DESC');
});
});
describe('toggleOrder()', () => { describe('toggleOrder()', () => {
it(`should change the ordenation to DESC (descendant) if it was ASC (ascendant)`, () => { it(`should change the ordenation to DESC (descendant) if it was ASC (ascendant)`, () => {
controller.order = 'ASC'; controller.order = 'ASC';

View File

@ -170,5 +170,6 @@
"comercialName": "Comercial", "comercialName": "Comercial",
"Added observation": "Added observation", "Added observation": "Added observation",
"Comment added to client": "Comment added to client", "Comment added to client": "Comment added to client",
"This ticket is already a refund": "This ticket is already a refund" "This ticket is already a refund": "This ticket is already a refund",
"A claim with that sale already exists": "A claim with that sale already exists"
} }

View File

@ -13,6 +13,7 @@
<vn-date-picker <vn-date-picker
label="Date" label="Date"
ng-model="$ctrl.receipt.payed" ng-model="$ctrl.receipt.payed"
vn-name="payed"
required="true"> required="true">
</vn-date-picker> </vn-date-picker>
<vn-autocomplete <vn-autocomplete
@ -21,6 +22,7 @@
show-field="code" show-field="code"
value-field="id" value-field="id"
ng-model="$ctrl.companyFk" ng-model="$ctrl.companyFk"
vn-name="company"
required="true"> required="true">
</vn-autocomplete> </vn-autocomplete>
</vn-horizontal> </vn-horizontal>
@ -33,6 +35,7 @@
fields="['accountingTypeFk']" fields="['accountingTypeFk']"
include="{relation: 'accountingType'}" include="{relation: 'accountingType'}"
ng-model="$ctrl.bankFk" ng-model="$ctrl.bankFk"
vn-name="bank"
search-function="$ctrl.bankSearchFunc($search)" search-function="$ctrl.bankSearchFunc($search)"
selection="$ctrl.bankSelection" selection="$ctrl.bankSelection"
order="id" order="id"
@ -43,6 +46,7 @@
vn-focus vn-focus
label="Amount" label="Amount"
ng-model="$ctrl.amountPaid" ng-model="$ctrl.amountPaid"
vn-name="amountPaid"
step="0.01" step="0.01"
required="true" required="true"
max="$ctrl.maxAmount"> max="$ctrl.maxAmount">
@ -52,6 +56,7 @@
<h6 translate>Compensation</h6> <h6 translate>Compensation</h6>
<vn-textfield <vn-textfield
ng-model="$ctrl.receipt.compensationAccount" ng-model="$ctrl.receipt.compensationAccount"
vn-name="compensationAccount"
label="Compensation Account" label="Compensation Account"
on-change="$ctrl.accountShortToStandard(value)"> on-change="$ctrl.accountShortToStandard(value)">
</vn-textfield> </vn-textfield>
@ -60,6 +65,7 @@
<vn-textfield <vn-textfield
label="Reference" label="Reference"
ng-model="$ctrl.receipt.description" ng-model="$ctrl.receipt.description"
vn-name="description"
rule rule
required="true"> required="true">
</vn-textfield> </vn-textfield>
@ -70,23 +76,27 @@
<vn-input-number <vn-input-number
ng-model="$ctrl.deliveredAmount" ng-model="$ctrl.deliveredAmount"
label="Delivered amount" label="Delivered amount"
step="0.01"> step="0.01"
vn-name="deliveredAmount">
</vn-input-number> </vn-input-number>
<vn-input-number <vn-input-number
disabled="true" disabled="true"
ng-model="$ctrl.amountToReturn" ng-model="$ctrl.amountToReturn"
label="Amount to return"> label="Amount to return"
vn-name="amountToReturn">
</vn-input-number> </vn-input-number>
</vn-horizontal> </vn-horizontal>
</vn-vertical> </vn-vertical>
<vn-horizontal ng-show="$ctrl.bankSelection.accountingType.code == 'cash'"> <vn-horizontal ng-show="$ctrl.bankSelection.accountingType.code == 'cash'">
<vn-check <vn-check
label="View receipt" label="View receipt"
ng-model="$ctrl.viewReceipt"> ng-model="$ctrl.viewReceipt"
vn-name="viewReceipt">
</vn-check> </vn-check>
<vn-check <vn-check
label="Send email" label="Send email"
ng-model="$ctrl.sendEmail"> ng-model="$ctrl.sendEmail"
vn-name="sendEmail">
</vn-check> </vn-check>
</vn-horizontal> </vn-horizontal>
</tpl-body> </tpl-body>

View File

@ -28,7 +28,7 @@
<vn-table model="model" auto-load="false"> <vn-table model="model" auto-load="false">
<vn-thead> <vn-thead>
<vn-tr> <vn-tr>
<vn-th field="shipped" default-order="DESC" expand>Date</vn-th> <vn-th field="shipped" expand>Date</vn-th>
<vn-th field="userFk">Created by</vn-thfield></vn-th> <vn-th field="userFk">Created by</vn-thfield></vn-th>
<vn-th field="description">Comment</vn-th> <vn-th field="description">Comment</vn-th>
<vn-th field="greugeTypeFk">Type</vn-th> <vn-th field="greugeTypeFk">Type</vn-th>

View File

@ -11,8 +11,7 @@ class Controller extends Section {
scope: { scope: {
fields: ['id', 'name'] fields: ['id', 'name']
}, },
}, }, {
{
relation: 'user', relation: 'user',
scope: { scope: {
fields: ['id', 'name'] fields: ['id', 'name']
@ -24,8 +23,6 @@ class Controller extends Section {
} }
} }
Controller.$inject = ['$element', '$scope'];
ngModule.vnComponent('vnClientGreugeIndex', { ngModule.vnComponent('vnClientGreugeIndex', {
template: require('./index.html'), template: require('./index.html'),
controller: Controller controller: Controller

View File

@ -141,7 +141,7 @@ module.exports = Self => {
let stmt; let stmt;
stmt = new ParameterizedSQL( stmt = new ParameterizedSQL(
`CREATE TEMPORARY TABLE tmp.filter `CREATE OR REPLACE TEMPORARY TABLE tmp.filter
(INDEX (id)) (INDEX (id))
ENGINE = MEMORY ENGINE = MEMORY
SELECT SELECT

View File

@ -24,7 +24,7 @@
<vn-table model="model"> <vn-table model="model">
<vn-thead> <vn-thead>
<vn-tr> <vn-tr>
<vn-th shrink field="itemFk" default-order="ASC" number>Item</vn-th> <vn-th shrink field="itemFk" number>Item</vn-th>
<vn-th>Description</vn-th> <vn-th>Description</vn-th>
<vn-th shrink field="quantity" number>Quantity</vn-th> <vn-th shrink field="quantity" number>Quantity</vn-th>
<vn-th shrink number>m³ per quantity</vn-th> <vn-th shrink number>m³ per quantity</vn-th>

View File

@ -6,9 +6,10 @@ class Controller extends Section {
constructor($element, $) { constructor($element, $) {
super($element, $); super($element, $);
this.filter = { this.filter = {
include: [{ include: {
relation: 'item' relation: 'item'
}] },
order: 'itemFk'
}; };
this.order = {}; this.order = {};
this.ticketVolumes = []; this.ticketVolumes = [];

View File

@ -1,4 +1,5 @@
<vn-crud-model auto-load="false" <vn-crud-model
auto-load="true"
vn-id="model" vn-id="model"
url="sales" url="sales"
filter="::$ctrl.filter" filter="::$ctrl.filter"
@ -23,7 +24,7 @@
<vn-thead> <vn-thead>
<vn-tr> <vn-tr>
<vn-th field="itemFk" number>Item</vn-th> <vn-th field="itemFk" number>Item</vn-th>
<vn-th field="concept" default-order="ASC">Description</vn-th> <vn-th field="concept">Description</vn-th>
<vn-th field="itemPackingTypeFk" number>Packing type</vn-th> <vn-th field="itemPackingTypeFk" number>Packing type</vn-th>
<vn-th field="quantity" number>Quantity</vn-th> <vn-th field="quantity" number>Quantity</vn-th>
<vn-th number>m³ per quantity</vn-th> <vn-th number>m³ per quantity</vn-th>

View File

@ -5,9 +5,10 @@ class Controller extends Section {
constructor($element, $) { constructor($element, $) {
super($element, $); super($element, $);
this.filter = { this.filter = {
include: [{ include: {
relation: 'item' relation: 'item'
}] },
order: 'concept'
}; };
this.ticketVolumes = []; this.ticketVolumes = [];

4
package-lock.json generated
View File

@ -1,7 +1,7 @@
{ {
"name": "salix-back", "name": "salix-back",
"version": "23.16.01", "version": "23.18.01",
"lockfileVersion": 2, "lockfileVersion": 1,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {

View File

@ -1,6 +1,6 @@
{ {
"name": "salix-back", "name": "salix-back",
"version": "23.16.01", "version": "23.20.01",
"author": "Verdnatura Levante SL", "author": "Verdnatura Levante SL",
"description": "Salix backend", "description": "Salix backend",
"license": "GPL-3.0", "license": "GPL-3.0",

View File

@ -1,6 +1,7 @@
subject: Weekly time log subject: Weekly time log
title: Record of hours week {0} year {1} title: Record of hours week {0} year {1}
dear: Dear worker dear: Dear worker
description: Access the following link:<br/><br/> Acceda al siguiente enlace: Access the following link:<br/>
{0} <br/><br/> description:
Click 'SATISFIED' if you agree with the hours worked. Otherwise, press 'NOT SATISFIED', detailing the cause of the disagreement. Click 'SATISFIED' if you agree with the hours worked. Otherwise, press 'NOT SATISFIED', detailing the cause of the disagreement.
Hours: Hours

View File

@ -1,6 +1,7 @@
subject: Registro de horas semanal subject: Registro de horas semanal
title: Registro de horas semana {0} año {1} title: Registro de horas semana {0} año {1}
dear: Estimado trabajador dear: Estimado trabajador
description: Acceda al siguiente enlace:<br/><br/> toaccess: Acceda al siguiente enlace:<br/>
{0} <br/><br/> description:
Pulse 'CONFORME' si esta de acuerdo con las horas trabajadas. En caso contrario pulse 'NO CONFORME', detallando la causa de la disconformidad. Pulse 'CONFORME' si esta de acuerdo con las horas trabajadas. En caso contrario pulse 'NO CONFORME', detallando la causa de la disconformidad.
Hours: Horas

View File

@ -3,7 +3,9 @@
<div class="grid-block vn-pa-ml"> <div class="grid-block vn-pa-ml">
<h1>{{ $t('title', [week, year]) }}</h1> <h1>{{ $t('title', [week, year]) }}</h1>
<p>{{$t('dear')}},</p> <p>{{$t('dear')}},</p>
<p v-html="$t('description', [url])"></p> <p v-html="$t('toaccess')"></p>
<a :href="url"><button>{{$t('Hours')}}</button></a>
<p>{{$t('description')}}</p>
</div> </div>
</div> </div>
</email-body> </email-body>