Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 6276-createNewWarehouse
gitea/salix/pipeline/head There was a failure building this commit Details

This commit is contained in:
Jorge Penadés 2024-01-08 16:21:46 +01:00
commit ab1dc7af55
17 changed files with 44 additions and 502 deletions

View File

@ -0,0 +1,9 @@
ALTER TABLE `vn`.`clientSms` ADD `ticketFk` int(11) NULL;
ALTER TABLE `vn`.`clientSms` ADD CONSTRAINT `clientSms_FK_2` FOREIGN KEY (`ticketFk`) REFERENCES `vn`.`ticket`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
INSERT INTO`vn`.`clientSms` (`clientFk`, `smsFk`, `ticketFk`)
SELECT `t`.`clientFk`, `s`.`smsFk`, `s`.`ticketFk`
FROM `vn`.`clientSms` `s`
JOIN `vn`.`ticket` `t` ON `t`.`id` = `s`.`ticketFk`;
RENAME TABLE `vn`.`ticketSms` TO `vn`.`ticketSms__`;

View File

@ -3023,6 +3023,20 @@ INSERT INTO `vn`.`docuwareTablet` (`tablet`,`description`)
('Tablet1','Jarvis tablet'),
('Tablet2','Avengers tablet');
INSERT INTO `vn`.`sms` (`id`, `senderFk`, `sender`, `destination`, `message`, `statusCode`, `status`, `created`)
VALUES (1, 66, '111111111', '0001111111111', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', 0, 'OK', util.VN_CURDATE()),
(2, 66, '222222222', '0002222222222', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', 0, 'PENDING', util.VN_CURDATE()),
(3, 66, '333333333', '0003333333333', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', 0, 'ERROR', util.VN_CURDATE()),
(4, 66, '444444444', '0004444444444', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', 0, 'OK', util.VN_CURDATE());
INSERT INTO `vn`.`clientSms` (`id`, `clientFk`, `smsFk`, `ticketFk`)
VALUES(1, 1103, 1, NULL),
(2, 1103, 2, NULL),
(3, 1103, 3, 32),
(4, 1103, 4, 32),
(13, 1101, 1, NULL),
(14, 1101, 4, 27);
-- NEW WAREHOUSE
UPDATE vn.packaging

View File

@ -1,123 +0,0 @@
const app = require('vn-loopback/server/server');
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
// 2277 solucionar problema al testear procedimiento con start transaction / rollback
xdescribe('ticket_componentMakeUpdate()', () => {
it('should recalculate the ticket components without make modifications', async() => {
let stmts = [];
let stmt;
let params = {
ticketId: 11,
clientId: 1102,
agencyModeId: 2,
addressId: 122,
zoneId: 3,
warehouseId: 1,
companyId: 442,
isDeleted: 0,
hasToBeUnrouted: 0,
componentOption: 1
};
stmts.push('START TRANSACTION');
stmt = new ParameterizedSQL('SELECT * FROM vn.ticket WHERE id = ?', [
params.ticketId
]);
stmts.push(stmt);
let originalTicketIndex = stmts.push(stmt) - 1;
stmt = new ParameterizedSQL('CALL vn.ticket_componentMakeUpdate(?, ?, ?, ?, ?, ?, ?, DATE_ADD(CURDATE(), INTERVAL +1 DAY), DATE_ADD(CURDATE(), INTERVAL +1 DAY), ?, ?, ?)', [
params.ticketId,
params.clientId,
params.agencyModeId,
params.addressId,
params.zoneId,
params.warehouseId,
params.companyId,
params.isDeleted,
params.hasToBeUnrouted,
params.componentOption
]);
stmts.push(stmt);
stmt = new ParameterizedSQL('SELECT * FROM vn.ticket WHERE id = ?', [
params.ticketId
]);
stmts.push(stmt);
let updatedTicketIndex = stmts.push(stmt) - 1;
stmts.push('ROLLBACK');
let sql = ParameterizedSQL.join(stmts, ';');
let result = await app.models.Ticket.rawStmt(sql);
let originalTicketData = result[originalTicketIndex];
let updatedTicketData = result[updatedTicketIndex];
expect(originalTicketData[0].isDeleted).toEqual(updatedTicketData[0].isDeleted);
expect(originalTicketData[0].routeFk).toEqual(updatedTicketData[0].routeFk);
});
it('should delete and unroute a ticket and recalculate the components', async() => {
let stmts = [];
let stmt;
let params = {
ticketId: 11,
clientId: 1102,
agencyModeId: 2,
addressId: 122,
zoneId: 3,
warehouseId: 1,
companyId: 442,
isDeleted: 1,
hasToBeUnrouted: 1,
componentOption: 1
};
stmts.push('START TRANSACTION');
stmt = new ParameterizedSQL('SELECT * FROM vn.ticket WHERE id = ?', [
params.ticketId
]);
stmts.push(stmt);
let originalTicketIndex = stmts.push(stmt) - 1;
stmt = new ParameterizedSQL('CALL vn.ticket_componentMakeUpdate(?, ?, ?, ?, ?, ?, ?, DATE_ADD(CURDATE(), INTERVAL +1 DAY), DATE_ADD(CURDATE(), INTERVAL +1 DAY), ?, ?, ?)', [
params.ticketId,
params.clientId,
params.agencyModeId,
params.addressId,
params.zoneId,
params.warehouseId,
params.companyId,
params.isDeleted,
params.hasToBeUnrouted,
params.componentOption
]);
stmts.push(stmt);
stmt = new ParameterizedSQL('SELECT * FROM vn.ticket WHERE id = ?', [
params.ticketId
]);
stmts.push(stmt);
let updatedTicketIndex = stmts.push(stmt) - 1;
stmts.push('ROLLBACK');
let sql = ParameterizedSQL.join(stmts, ';');
let result = await app.models.Ticket.rawStmt(sql);
let originalTicketData = result[originalTicketIndex];
let updatedTicketData = result[updatedTicketIndex];
expect(originalTicketData[0].isDeleted).not.toEqual(updatedTicketData[0].isDeleted);
expect(originalTicketData[0].routeFk).not.toEqual(updatedTicketData[0].routeFk);
});
});

View File

@ -56,63 +56,6 @@ describe('Worker time control path', () => {
expect(result).toContain(month);
});
it(`should return error when insert 'out' of first entry`, async() => {
pending('https://redmine.verdnatura.es/issues/4707');
await page.waitToClick(selectors.workerTimeControl.mondayAddTimeButton);
await page.pickTime(selectors.workerTimeControl.dialogTimeInput, eightAm);
await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'out');
await page.respondToDialog('accept');
const message = await page.waitForSnackbar();
expect(message.text).toBeDefined();
});
it(`should insert 'in' monday`, async() => {
pending('https://redmine.verdnatura.es/issues/4707');
await page.waitToClick(selectors.workerTimeControl.mondayAddTimeButton);
await page.pickTime(selectors.workerTimeControl.dialogTimeInput, eightAm);
await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'in');
await page.respondToDialog('accept');
const result = await page.waitToGetProperty(selectors.workerTimeControl.firstEntryOfMonday, 'innerText');
expect(result).toEqual(eightAm);
});
it(`should insert 'out' monday`, async() => {
pending('https://redmine.verdnatura.es/issues/4707');
await page.waitToClick(selectors.workerTimeControl.mondayAddTimeButton);
await page.pickTime(selectors.workerTimeControl.dialogTimeInput, fourPm);
await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'out');
await page.respondToDialog('accept');
const result = await page.waitToGetProperty(selectors.workerTimeControl.secondEntryOfMonday, 'innerText');
expect(result).toEqual(fourPm);
});
it(`should check Hank Pym worked 8:20 hours`, async() => {
pending('https://redmine.verdnatura.es/issues/4707');
await page.waitForTextInElement(selectors.workerTimeControl.mondayWorkedHours, '08:20 h.');
await page.waitForTextInElement(selectors.workerTimeControl.weekWorkedHours, '08:20 h.');
});
it('should remove first entry of monday', async() => {
pending('https://redmine.verdnatura.es/issues/4707');
await page.waitForTextInElement(selectors.workerTimeControl.firstEntryOfMonday, eightAm);
await page.waitForTextInElement(selectors.workerTimeControl.secondEntryOfMonday, fourPm);
await page.waitToClick(selectors.workerTimeControl.firstEntryOfMondayDelete);
await page.respondToDialog('accept');
const message = await page.waitForSnackbar();
expect(message.text).toContain('Entry removed');
});
it(`should be the 'out' the first entry of monday`, async() => {
pending('https://redmine.verdnatura.es/issues/4707');
const result = await page.waitToGetProperty(selectors.workerTimeControl.firstEntryOfMonday, 'innerText');
expect(result).toEqual(fourPm);
});
it('should change week of month', async() => {
await page.click(selectors.workerTimeControl.thrirdWeekDay);
const result = await page.getProperty(selectors.workerTimeControl.mondayWorkedHours, 'innerText');

View File

@ -188,17 +188,6 @@ describe('Ticket Edit sale path', () => {
expect(result).toContain('22.50');
});
it('should check in the history that logs has been added', async() => {
pending('https://redmine.verdnatura.es/issues/5455');
await page.reload({waitUntil: ['networkidle0', 'domcontentloaded']});
await page.waitToClick(selectors.ticketSales.firstSaleHistoryButton);
await page.waitForSelector(selectors.ticketSales.firstSaleHistory);
const result = await page.countElement(selectors.ticketSales.firstSaleHistory);
expect(result).toBeGreaterThan(0);
await page.waitToClick(selectors.ticketSales.closeHistory);
});
it('should recalculate price of sales', async() => {
await page.waitToClick(selectors.ticketSales.firstSaleCheckbox);
await page.waitToClick(selectors.ticketSales.secondSaleCheckbox);

View File

@ -1,31 +0,0 @@
import selectors from '../../helpers/selectors.js';
import getBrowser from '../../helpers/puppeteer';
// #2221 Local MySQL8 crashes when rest method Items/getBalance is called
xdescribe('Ticket diary path', () => {
let page;
beforeAll(async() => {
page = (await getBrowser()).page;
await page.loginAndModule('employee', 'ticket');
});
afterAll(async() => {
await page.browser().close();
});
it(`should navigate to item diary from ticket sale and check the lines`, async() => {
await page.accessToSearchResult('1');
await page.waitToClick(selectors.ticketSummary.firstSaleItemId);
await page.waitToClick(selectors.ticketSummary.popoverDiaryButton);
await page.waitForState('item.card.diary');
const secondIdClass = await page.getClassName(selectors.itemDiary.secondTicketId);
const fourthBalanceClass = await page.getClassName(selectors.itemDiary.fourthBalance);
const firstBalanceClass = await page.getClassName(selectors.itemDiary.firstBalance);
expect(secondIdClass).toContain('message');
expect(fourthBalanceClass).toContain('message');
expect(firstBalanceClass).toContain('balance');
});
});

View File

@ -1,114 +0,0 @@
import selectors from '../../helpers/selectors.js';
import getBrowser from '../../helpers/puppeteer.js';
// #1528 e2e claim/detail
xdescribe('Claim detail', () => {
let browser;
let page;
beforeAll(async() => {
browser = await getBrowser();
page = browser.page;
await page.loginAndModule('salesPerson', 'claim');
await page.accessToSearchResult('1');
await page.accessToSection('claim.card.detail');
});
afterAll(async() => {
await browser.close();
});
it('should add the first claimable item from ticket to the claim', async() => {
await page.waitToClick(selectors.claimDetail.addItemButton);
await page.waitToClick(selectors.claimDetail.firstClaimableSaleFromTicket);
const message = await page.waitForSnackbar();
expect(message.text).toContain('Data saved!');
});
it('should confirm the claim contains now two items', async() => {
const result = await page.countElement(selectors.claimDetail.claimDetailLine);
expect(result).toEqual(2);
});
it('should edit de first item claimed quantity', async() => {
await page.clearInput(selectors.claimDetail.firstItemQuantityInput); // selector deleted, find new upon fixes
await page.write(selectors.claimDetail.firstItemQuantityInput, '4'); // selector deleted, find new upon fixes
await page.keyboard.press('Enter');
const message = await page.waitForSnackbar();
expect(message.text).toContain('Data saved!');
});
it('should confirm the first item quantity, and the claimed total were correctly edited', async() => {
const claimedQuantity = page
.waitToGetProperty(selectors.claimDetail.firstItemQuantityInput, 'value'); // selector deleted, find new upon fixes
const totalClaimed = page
.waitToGetProperty(selectors.claimDetail.totalClaimed, 'innerText');
expect(claimedQuantity).toEqual('4');
expect(totalClaimed).toContain('€47.62');
});
it('should login as salesAssistant and navigate to the claim.detail section', async() => {
await page.loginAndModule('salesAssistant', 'claim');
await page.accessToSearchResult('1');
await page.accessToSection('claim.card.detail');
let url = await page.expectURL('/detail'); // replace with waitForState
expect(url).toBe(true);
});
it('should edit de second item claimed discount', async() => {
await page.waitToClick(selectors.claimDetail.secondItemDiscount);
await page.write(selectors.claimDetail.discount, '100');
await page.keyboard.press('Enter');
const message = await page.waitForSnackbar();
expect(message.text).toContain('Data saved!');
});
it('should check the mana is the expected one', async() => {
await page.waitToClick(selectors.claimDetail.secondItemDiscount);
const result = await page.waitToGetProperty(selectors.claimDetail.discoutPopoverMana, 'innerText');
expect(result).toContain('MANÁ: €106');
});
it('should delete the second item from the claim', async() => {
await page.waitToClick(selectors.claimDetail.secondItemDeleteButton);
const message = await page.waitForSnackbar();
expect(message.text).toContain('Data saved!');
});
it('should confirm the claim contains now one item', async() => {
const result = await page.countElement(selectors.claimDetail.claimDetailLine);
expect(result).toEqual(1);
});
it('should add the deleted ticket from to the claim', async() => {
await page.waitToClick(selectors.claimDetail.addItemButton);
await page.waitToClick(selectors.claimDetail.firstClaimableSaleFromTicket);
const message = await page.waitForSnackbar();
expect(message.text).toContain('Data saved!');
});
it(`should have been redirected to the next section in claims`, async() => {
let url = await page.expectURL('development'); // replace with waitForState
expect(url).toBe(true);
});
it('should navigate back to claim.detail to confirm the claim contains now two items', async() => {
await page.accessToSection('claim.card.detail');
await page.waitForSelector(selectors.claimDetail.claimDetailLine);
const result = await page.countElement(selectors.claimDetail.claimDetailLine);
expect(result).toEqual(2);
});
});

View File

@ -105,17 +105,4 @@ describe('Travel basic data path', () => {
it(`should check the received checkbox was saved even tho it doesn't make sense`, async() => {
await page.waitForClassPresent(selectors.travelBasicData.received, 'checked');
});
it('should navigate to the travel logs', async() => {
pending('https://redmine.verdnatura.es/issues/5455');
await page.accessToSection('travel.card.log');
await page.waitForState('travel.card.log');
});
it('should check the 1st log contains details from the changes made', async() => {
pending('https://redmine.verdnatura.es/issues/5455');
const result = await page.waitToGetProperty(selectors.travelLog.firstLogFirstTD, 'innerText');
expect(result).toContain('new reference!');
});
});

View File

@ -33,18 +33,6 @@ describe('Component vnTreeview', () => {
$element.remove();
});
// See how to test DOM element in Jest
xdescribe('undrop()', () => {
it(`should reset all drop events and properties`, () => {
controller.dropping = angular.element(`<vn-treeview-child class="dropping"></vn-treeview-child>`);
jest.spyOn(controller.dropping.classList, 'remove');
controller.undrop();
expect(controller.dropping).toBeNull();
});
});
describe('dragOver()', () => {
it(`should set the dragClientY property`, () => {
const event = new Event('dragover');

View File

@ -113,9 +113,6 @@
"SageTransactionType": {
"dataSource": "vn"
},
"TicketSms": {
"dataSource": "vn"
},
"TpvError": {
"dataSource": "vn"
},

View File

@ -21,6 +21,11 @@
"type": "belongsTo",
"model": "Sms",
"foreignKey": "smsFk"
},
"ticket": {
"type": "belongsTo",
"model": "Ticket",
"foreignKey": "ticketFk"
}
}
}

View File

@ -1,28 +0,0 @@
{
"name": "TicketSms",
"base": "VnModel",
"options": {
"mysql": {
"table": "ticketSms"
}
},
"properties": {
"smsFk": {
"type": "number",
"id": true,
"description": "Identifier"
}
},
"relations": {
"ticket": {
"type": "belongsTo",
"model": "Ticket",
"foreignKey": "ticketFk"
},
"sms": {
"type": "belongsTo",
"model": "Sms",
"foreignKey": "smsFk"
}
}
}

View File

@ -1,40 +1,2 @@
<vn-crud-model
vn-id="model"
url="ClientSms"
link="{clientFk: $ctrl.$params.id}"
filter="::$ctrl.filter"
data="clientSmsList"
limit="20"
auto-load="true">
</vn-crud-model>
<vn-data-viewer model="model">
<vn-card class="vn-w-lg">
<vn-table model="model" auto-load="false">
<vn-thead>
<vn-tr>
<vn-th field="senderFk">Sender</vn-th>
<vn-th field="destination" number>Destination</vn-th>
<vn-th field="message">Message</vn-th>
<vn-th field="status">Status</vn-th>
<vn-th field="created" expand>Created</vn-th>
</vn-tr>
</vn-thead>
<vn-tbody>
<vn-tr ng-repeat="clientSms in clientSmsList">
<vn-td>
<span class="link" ng-click="workerDescriptor.show($event, clientSms.sms.senderFk)">
{{::clientSms.sms.sender.name}}
</span>
</vn-td>
<vn-td number expand>{{::clientSms.sms.destination}}</vn-td>
<vn-td expand vn-tooltip="{{::clientSms.sms.message}}">{{::clientSms.sms.message}}</vn-td>
<vn-td>{{::clientSms.sms.status}}</vn-td>
<vn-td shrink-datetime>{{::clientSms.sms.created | date:'dd/MM/yyyy HH:mm'}}</vn-td>
</vn-tr>
</vn-tbody>
</vn-table>
</vn-card>
</vn-data-viewer>
<vn-worker-descriptor-popover
vn-id="worker-descriptor">
</vn-worker-descriptor-popover>
<vn-card>
</vn-card>

View File

@ -1,32 +1,14 @@
import ngModule from '../module';
import Section from 'salix/components/section';
export default class Controller extends Section {
class Controller extends Section {
constructor($element, $) {
super($element, $);
}
this.filter = {
fields: ['id', 'smsFk'],
include: {
relation: 'sms',
scope: {
fields: [
'senderFk',
'sender',
'destination',
'message',
'statusCode',
'status',
'created'],
include: {
relation: 'sender',
scope: {
fields: ['name']
}
}
}
}
};
async $onInit() {
this.$state.go('client.card.summary', {id: this.$params.id});
window.location.href = await this.vnApp.getUrl(`Customer/${this.$params.id}/sms`);
}
}

View File

@ -1,40 +0,0 @@
const models = require('vn-loopback/server/server').models;
const https = require('https');
xdescribe('boxing getVideo()', () => {
it('should return data', async() => {
const tx = await models.PackingSiteConfig.beginTransaction({});
try {
const options = {transaction: tx};
const id = 1;
const video = 'video.mp4';
const response = {
pipe: () => {},
on: () => {},
end: () => {},
};
const req = {
headers: 'apiHeader',
data: {
pipe: () => {},
on: () => {},
}
};
spyOn(https, 'request').and.returnValue(response);
const result = await models.Boxing.getVideo(id, video, req, null, options);
expect(result[0]).toEqual(response.data.videos[0].filename);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -33,7 +33,9 @@ module.exports = Self => {
Self.sendSms = async(ctx, id, destination, message) => {
const models = Self.app.models;
const sms = await models.Sms.send(ctx, destination, message);
await models.TicketSms.create({
const {clientFk} = await models.Ticket.findById(id);
await models.ClientSms.create({
clientFk,
ticketFk: id,
smsFk: sms.id
});

View File

@ -14,12 +14,12 @@ describe('ticket sendSms()', () => {
await models.Ticket.sendSms(ctx, id, destination, message, options);
const filter = {
ticketFk: id
};
const ticketSms = await models.TicketSms.findOne(filter, options);
const clientSms = await models.ClientSms.findOne(
{where: {ticketFk: id}},
options
);
expect(ticketSms.ticketFk).toEqual(id);
expect(clientSms.ticketFk).toEqual(id);
await tx.rollback();
} catch (e) {