3448-worker_calendar-payedHolidays #846

Merged
carlosjr merged 11 commits from 3448-worker_calendar-payedHolidays into dev 2022-01-17 09:09:46 +00:00
16 changed files with 7469 additions and 2402 deletions
Showing only changes of commit d5e4d99625 - Show all commits

File diff suppressed because one or more lines are too long

View File

@ -606,7 +606,7 @@ INSERT INTO `vn`.`ticket`(`id`, `priority`, `agencyModeFk`,`warehouseFk`,`routeF
(9 , NULL, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 1104, 'Stark tower', 124, NULL, 0, 3, 5, 1, CURDATE()), (9 , NULL, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 1104, 'Stark tower', 124, NULL, 0, 3, 5, 1, CURDATE()),
(10, 1, 1, 5, 1, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 1102, 'Ingram Street', 2, NULL, 0, 1, 5, 1, CURDATE()), (10, 1, 1, 5, 1, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 1102, 'Ingram Street', 2, NULL, 0, 1, 5, 1, CURDATE()),
(11, 1, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 1102, 'NY roofs', 122, NULL, 0, 3, 5, 1, CURDATE()), (11, 1, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 1102, 'NY roofs', 122, NULL, 0, 3, 5, 1, CURDATE()),
(12, 1, 1, 1, 1, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, CURDATE()), (12, 1, 8, 1, 1, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, CURDATE()),
(13, 1, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 3, 5, 1, CURDATE()), (13, 1, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 3, 5, 1, CURDATE()),
(14, 1, 2, 1, NULL, CURDATE(), CURDATE(), 1104, 'Malibu Point', 4, NULL, 0, 9, 5, 1, CURDATE()), (14, 1, 2, 1, NULL, CURDATE(), CURDATE(), 1104, 'Malibu Point', 4, NULL, 0, 9, 5, 1, CURDATE()),
(15, 1, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 1105, 'An incredibly long alias for testing purposes', 125, NULL, 0, 3, 5, 1, CURDATE()), (15, 1, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 1105, 'An incredibly long alias for testing purposes', 125, NULL, 0, 3, 5, 1, CURDATE()),
@ -1076,11 +1076,15 @@ INSERT INTO `vn`.`itemPlacement`(`id`, `itemFk`, `warehouseFk`, `code`)
(3, 1, 3, 'A33'), (3, 1, 3, 'A33'),
(4, 2, 1, 'A44'); (4, 2, 1, 'A44');
INSERT INTO `vn`.`train`(`id`, `name`)
INSERT INTO `vn`.`collection`(`id`, `workerFk`, `stateFk`, `created`)
VALUES VALUES
(1, 1106, 5, DATE_ADD(CURDATE(),INTERVAL +1 DAY)), (1, 'Train1'),
(2, 1106, 14, CURDATE()); (2, 'Train2');
INSERT INTO `vn`.`collection`(`id`, `workerFk`, `stateFk`, `created`, `trainFk`)
VALUES
(1, 1106, 5, DATE_ADD(CURDATE(),INTERVAL +1 DAY), 1),
(2, 1106, 14, CURDATE(), 1);
INSERT INTO `vn`.`ticketCollection`(`id`, `ticketFk`, `collectionFk`) INSERT INTO `vn`.`ticketCollection`(`id`, `ticketFk`, `collectionFk`)
VALUES VALUES

File diff suppressed because it is too large Load Diff

View File

@ -458,7 +458,8 @@ export default {
firstSaleQuantity: 'vn-ticket-summary [name="sales"] vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(5)', firstSaleQuantity: 'vn-ticket-summary [name="sales"] vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(5)',
firstSaleDiscount: 'vn-ticket-summary [name="sales"] vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(8)', firstSaleDiscount: 'vn-ticket-summary [name="sales"] vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(8)',
invoiceOutRef: 'vn-ticket-summary > vn-card > vn-horizontal > vn-one:nth-child(1) > vn-label-value:nth-child(7) > section > span', invoiceOutRef: 'vn-ticket-summary > vn-card > vn-horizontal > vn-one:nth-child(1) > vn-label-value:nth-child(7) > section > span',
setOk: 'vn-ticket-summary vn-button[label="SET OK"] > button', stateButton: 'vn-ticket-summary vn-button-menu > button ',
stateAutocomplete: 'div.filter.ng-scope > vn-textfield > div.container > div.infix > div.control',
descriptorTicketId: 'vn-ticket-descriptor > vn-descriptor-content > div > div.body > div.top > div' descriptorTicketId: 'vn-ticket-descriptor > vn-descriptor-content > div > div.body > div.top > div'
}, },
ticketsIndex: { ticketsIndex: {

View File

@ -76,8 +76,24 @@ describe('Ticket Summary path', () => {
await page.waitForState('ticket.card.summary'); await page.waitForState('ticket.card.summary');
}); });
it('should click on the SET OK button', async() => { it('should set the ticket state to OK using the top right button', async() => {
await page.waitToClick(selectors.ticketSummary.setOk); const searchValue = 'OK';
await page.waitToClick(selectors.ticketSummary.stateButton);
await page.write(selectors.ticketSummary.stateAutocomplete, searchValue);
try {
await page.waitForFunction(text => {
const element = document.querySelector('li.active');
if (element)
return element.innerText.toLowerCase().includes(text.toLowerCase());
}, {}, searchValue);
} catch (error) {
const state = await page.evaluate(() => {
const stateSelector = 'vn-ticket-summary vn-label-value:nth-child(1) > section > span';
return document.querySelector(stateSelector).value;
});
throw new Error(`${stateSelector} innerText is ${state}! ${error}`);
}
await page.keyboard.press('Enter');
const message = await page.waitForSnackbar(); const message = await page.waitForSnackbar();
expect(message.text).toContain('Data saved!'); expect(message.text).toContain('Data saved!');

View File

@ -145,7 +145,7 @@
.icon-credit:before { .icon-credit:before {
content: "\e923"; content: "\e923";
} }
.icon-deletedTicketCross:before { .icon-deletedTicket:before {
content: "\e924"; content: "\e924";
} }
.icon-deleteline:before { .icon-deleteline:before {

View File

@ -59,11 +59,12 @@ module.exports = Self => {
const landedPlusWeek = new Date(ticket.landed); const landedPlusWeek = new Date(ticket.landed);
landedPlusWeek.setDate(landedPlusWeek.getDate() + 7); landedPlusWeek.setDate(landedPlusWeek.getDate() + 7);
const hasClaimManagerRole = await models.Account.hasRole(userId, 'claimManager', myOptions);
const isClaimable = landedPlusWeek >= new Date(); const isClaimable = landedPlusWeek >= new Date();
if (ticket.isDeleted) if (ticket.isDeleted)
throw new UserError(`You can't create a claim for a removed ticket`); throw new UserError(`You can't create a claim for a removed ticket`);
if (!isClaimable) if (!isClaimable && !hasClaimManagerRole)
throw new UserError(`You can't create a claim from a ticket delivered more than seven days ago`); throw new UserError(`You can't create a claim from a ticket delivered more than seven days ago`);
const newClaim = await Self.create({ const newClaim = await Self.create({

View File

@ -46,9 +46,40 @@ describe('Claim createFromSales()', () => {
} }
}); });
it('should be able to create a claim for a ticket delivered more than seven days ago as claimManager', async() => {
const tx = await models.Claim.beginTransaction({});
const claimManagerId = 72;
activeCtx.accessToken.userId = claimManagerId;
try {
const options = {transaction: tx};
const todayMinusEightDays = new Date();
todayMinusEightDays.setDate(todayMinusEightDays.getDate() - 8);
const ticket = await models.Ticket.findById(ticketId, options);
await ticket.updateAttribute('landed', todayMinusEightDays, options);
const claim = await models.Claim.createFromSales(ctx, ticketId, newSale, options);
expect(claim.ticketFk).toEqual(ticketId);
const claimBeginning = await models.ClaimBeginning.findOne({where: {claimFk: claim.id}}, options);
expect(claimBeginning.saleFk).toEqual(newSale[0].id);
expect(claimBeginning.quantity).toEqual(newSale[0].quantity);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should not be able to create a claim for a ticket delivered more than seven days ago', async() => { it('should not be able to create a claim for a ticket delivered more than seven days ago', async() => {
const tx = await models.Claim.beginTransaction({}); const tx = await models.Claim.beginTransaction({});
activeCtx.accessToken.userId = 1;
let error; let error;
try { try {

View File

@ -374,11 +374,14 @@ module.exports = Self => {
throw new UserError(`You don't have enough privileges to set this credit amount`); throw new UserError(`You don't have enough privileges to set this credit amount`);
} }
await models.ClientCredit.create({ const client = await models.Client.findById(finalState.id, null, ctx.options);
amount: changes.credit, if (client.businessTypeFk) {
clientFk: finalState.id, await models.ClientCredit.create({
workerFk: userId amount: changes.credit,
}, ctx.options); clientFk: finalState.id,
workerFk: userId
}, ctx.options);
}
}; };
const app = require('vn-loopback/server/server'); const app = require('vn-loopback/server/server');

View File

@ -23,6 +23,6 @@ describe('InvoiceOut download()', () => {
const result = await models.InvoiceOut.download(ctx, invoiceId); const result = await models.InvoiceOut.download(ctx, invoiceId);
expect(result[1]).toEqual('application/pdf'); expect(result[1]).toEqual('application/pdf');
expect(result[2]).toEqual('filename="2021T1111111.pdf"'); expect(result[2]).toMatch(/filename="\d{4}T1111111.pdf"/);
}); });
}); });

View File

@ -7,12 +7,14 @@ module.exports = Self => {
}); });
async function ibanValidation(err, done) { async function ibanValidation(err, done) {
let filter = { const supplier = await Self.app.models.Supplier.findById(this.supplierFk);
const filter = {
fields: ['code'], fields: ['code'],
where: {id: this.countryFk} where: {id: supplier.countryFk}
}; };
let country = await Self.app.models.Country.findOne(filter);
let code = country ? country.code.toLowerCase() : null; const country = await Self.app.models.Country.findOne(filter);
const code = country ? country.code.toLowerCase() : null;
if (code != 'es') if (code != 'es')
return done(); return done();

View File

@ -40,7 +40,9 @@ class Controller extends Section {
const landedPlusWeek = new Date(this.ticket.landed); const landedPlusWeek = new Date(this.ticket.landed);
landedPlusWeek.setDate(landedPlusWeek.getDate() + 7); landedPlusWeek.setDate(landedPlusWeek.getDate() + 7);
return landedPlusWeek >= new Date(); const hasClaimManagerRole = this.aclService.hasAny(['claimManager']);
return landedPlusWeek >= new Date() || hasClaimManagerRole;
} }
return false; return false;
} }

View File

@ -11,14 +11,14 @@
Ticket #{{$ctrl.summary.id}} - {{$ctrl.summary.client.name}} Ticket #{{$ctrl.summary.id}} - {{$ctrl.summary.client.name}}
({{$ctrl.summary.client.id}}) - {{$ctrl.summary.nickname}} ({{$ctrl.summary.client.id}}) - {{$ctrl.summary.nickname}}
</span> </span>
<vn-button <vn-button-menu
disabled="!$ctrl.isEditable" disabled="!$ctrl.isEditable"
class="flat" class="message"
style="color: inherit;" label="Change state"
label="SET OK" value-field="code"
ng-click="$ctrl.setOkState()" url="States/editableStates"
vn-tooltip="Change ticket state to 'Ok'"> on-change="$ctrl.changeState(value)">
</vn-button> </vn-button-menu>
<vn-ticket-descriptor-menu <vn-ticket-descriptor-menu
ng-if="!$ctrl.isTicketModule" ng-if="!$ctrl.isTicketModule"
ticket-id="$ctrl.summary.id" ticket-id="$ctrl.summary.id"

View File

@ -59,10 +59,11 @@ class Controller extends Summary {
this.$.invoiceOutDescriptor.show(event.target, this.summary.invoiceOut.id); this.$.invoiceOutDescriptor.show(event.target, this.summary.invoiceOut.id);
} }
setOkState() { changeState(value) {
const params = {ticketFk: 'id' in this.ticket ? this.ticket.id : this.$params.id}; const params = {
ticketFk: 'id' in this.ticket ? this.ticket.id : this.$params.id,
params.code = 'OK'; code: value
};
this.$http.post(`TicketTrackings/changeState`, params) this.$http.post(`TicketTrackings/changeState`, params)
.then(() => { .then(() => {

View File

@ -42,5 +42,20 @@ describe('Ticket', () => {
expect(controller.formattedAddress).toEqual('1007 Mountain Drive - 46060 - Gotham (Gotham)'); expect(controller.formattedAddress).toEqual('1007 Mountain Drive - 46060 - Gotham (Gotham)');
}); });
}); });
describe('changeState()', () => {
it('should change the state', () => {
jest.spyOn(controller.vnApp, 'showSuccess');
const value = 'myTicketState';
let res = {id: 1, nickname: 'myNickname'};
$httpBackend.when('GET', `Tickets/1/summary`).respond(200, res);
$httpBackend.expectPOST(`TicketTrackings/changeState`).respond(200, 'ok');
controller.changeState(value);
$httpBackend.flush();
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!');
});
});
}); });
}); });

View File

@ -2,4 +2,5 @@ Address phone: Tel. consignatario
Address mobile: Móv. consignatario Address mobile: Móv. consignatario
Client phone: Tel. cliente Client phone: Tel. cliente
Client mobile: Móv. cliente Client mobile: Móv. cliente
Go to the ticket: Ir al ticket Go to the ticket: Ir al ticket
Change state: Cambiar estado