Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into dev
gitea/salix/dev This commit looks good Details

This commit is contained in:
Joan Sanchez 2019-07-03 12:47:03 +02:00
commit d90ebbef2e
22 changed files with 197 additions and 393 deletions

View File

@ -51,7 +51,12 @@
"type": "hasOne",
"model": "EmailUser",
"foreignKey": "userFk"
}
},
"worker": {
"type": "hasOne",
"model": "Worker",
"foreignKey": "userFk"
}
},
"acls": [
{

View File

@ -58,11 +58,11 @@ INSERT INTO `vn`.`country`(`id`, `country`, `isUeeMember`, `code`, `currencyFk`,
INSERT INTO `vn`.`warehouse`(`id`, `name`, `isComparative`, `isInventory`, `hasAvailable`, `isManaged`)
VALUES
(1, 'Warehouse One', 0, 1, 1, 1),
(2, 'Warehouse Two', 0, 1, 1, 1),
(1, 'Warehouse One', 1, 1, 1, 1),
(2, 'Warehouse Two', 1, 1, 1, 1),
(3, 'Warehouse Three', 1, 1, 1, 1),
(4, 'Warehouse Four', 1, 1, 1, 1),
(5, 'Warehouse Five', 1, 0, 1, 0);
(5, 'Warehouse Five', 1, 1, 1, 1);
INSERT INTO `vn`.`warehouseAlias`(`id`, `name`)
VALUES
@ -566,9 +566,9 @@ INSERT INTO `vn`.`itemType`(`id`, `code`, `name`, `categoryFk`, `life`,`workerFk
INSERT INTO `vn`.`ink`(`id`, `name`, `picture`, `showOrder`)
VALUES
('YEL', 'Yellow', 1 , 1),
('BLU', 'Blue', 1 , 2),
('RED', 'Red', 1 , 3);
('YEL', 'Yellow', 1, 1),
('BLU', 'Blue', 1, 2),
('RED', 'Red', 1, 3);
INSERT INTO `vn`.`origin`(`id`,`code`, `name`)
VALUES
@ -1062,10 +1062,10 @@ INSERT INTO `vn`.`buy`(`id`,`entryFk`,`itemFk`,`buyingValue`,`quantity`,`package
(9, 4, 4, 1.25, 1000, 3, 1, 0.000, 0.000, 0.000, 10, 10, 1, NULL, 0.00, 1.75, 1.67, 0.00, NULL, 0, 1, 0, CURDATE()),
(10, 5, 1, 50, 10, 4, 1, 0.000, 0.000, 0.000, 1, 1, 1, NULL, 0.00, 99.6, 99.4, 0.00, NULL, 0, 1, 0, CURDATE()),
(11, 5, 4, 1.25, 10, 3, 1, 0.000, 0.000, 0.000, 10, 10, 1, NULL, 0.00, 1.75, 1.67, 0.00, NULL, 0, 1, 0, CURDATE()),
(12, 6, 4, 1.25, 1, 3, 1, 0.000, 0.000, 0.000, 10, 10, 1, NULL, 0.00, 1.75, 1.67, 0.00, NULL, 0, 1, 0, CURDATE()),
(13, 7, 1, 50, 1, 4, 1, 0.000, 0.000, 0.000, 1, 1, 1, NULL, 0.00, 99.6, 99.4, 0.00, NULL, 0, 1, 0, CURDATE()),
(14, 7, 2, 5, 100, 1, 1, 0.000, 0.000, 0.000, 10, 10, 1, NULL, 0.00, 7.30, 7.00, 0.00, NULL, 0, 1, 0, CURDATE()),
(15, 7, 4, 1.25, 10, 3, 1, 0.000, 0.000, 0.000, 10, 10, 1, NULL, 0.00, 1.75, 1.67, 0.00, NULL, 0, 1, 0, CURDATE());
(12, 6, 4, 1.25, 0, 3, 1, 0.000, 0.000, 0.000, 10, 10, 1, NULL, 0.00, 1.75, 1.67, 0.00, NULL, 0, 1, 0, CURDATE()),
(13, 7, 1, 50, 0, 3, 1, 0.000, 0.000, 0.000, 1, 1, 1, NULL, 0.00, 99.6, 99.4, 0.00, NULL, 0, 1, 0, CURDATE()),
(14, 7, 2, 5, 0, 3, 1, 0.000, 0.000, 0.000, 10, 10, 1, NULL, 0.00, 7.30, 7.00, 0.00, NULL, 0, 1, 0, CURDATE()),
(15, 7, 4, 1.25, 0, 3, 1, 0.000, 0.000, 0.000, 10, 10, 1, NULL, 0.00, 1.75, 1.67, 0.00, NULL, 0, 1, 0, CURDATE());
INSERT INTO `vn2008`.`tblContadores`(`id`,`FechaInventario`)
VALUES
@ -1343,10 +1343,9 @@ INSERT INTO `vn`.`claim`(`id`, `ticketCreated`, `claimStateFk`, `observation`, `
INSERT INTO `vn`.`claimBeginning`(`id`, `claimFk`, `saleFk`, `quantity`)
VALUES
(1, 1, 7, 5),
(2, 1, 8, 4),
(3, 2, 10, 10),
(4, 3, 22, 1),
(5, 4, 13, 5);
(2, 2, 10, 10),
(3, 3, 22, 1),
(4, 4, 13, 5);
INSERT INTO `vn`.`claimDestination`(`id`, `description`, `addressFk`)
VALUES
@ -1460,7 +1459,7 @@ INSERT INTO `postgresql`.`person`(`person_id`, `name`, `nickname`, `nif`, `first
INSERT INTO `postgresql`.`person`(`person_id`, `name`, `nickname`, `nif`, `firstname`, `id_trabajador`)
VALUES
(1000, 'VERDNATURA LEVANTE SL', 'VNL', 'B78945612', NULL, NULL);
(1000, 'VERDNATURA LEVANTE SL', 'VNL', 'B78945612', NULL, NULL);
INSERT INTO `postgresql`.`profile`(`profile_id`, `person_id`, `profile_type_id`)
SELECT p.person_id, p.person_id, 1

View File

@ -508,7 +508,9 @@ export default {
itemDescriptorPopover: 'vn-claim-summary vn-item-descriptor-popover > vn-popover',
itemDescriptorPopoverItemDiaryButton: 'vn-claim-summary > vn-item-descriptor-popover a[href="#!/item/2/diary"]',
firstDevelopmentWorker: 'vn-claim-summary vn-horizontal > vn-auto:nth-child(5) > vn-table > div > vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(4) > span',
firstdevelopmentWorkerGoToClientButton: 'vn-claim-summary > vn-worker-descriptor-popover > vn-popover vn-worker-descriptor div.quicklinks > a[href="#!/client/21/summary"]'
firstDevelopmentWorkerGoToClientButton: 'vn-claim-summary > vn-worker-descriptor-popover > vn-popover vn-worker-descriptor div.quicklinks > a[href="#!/client/21/summary"]',
firstActionTicketId: 'vn-claim-summary > vn-card > div > vn-horizontal > vn-auto:nth-child(6) > vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(2) > span',
firstActionTicketDescriptor: 'vn-claim-summary > vn-ticket-descriptor-popover > vn-popover > div > div.content > vn-ticket-descriptor'
},
claimBasicData: {
claimStateAutocomplete: 'vn-claim-basic-data vn-autocomplete[field="$ctrl.claim.claimStateFk"]',
@ -517,10 +519,13 @@ export default {
saveButton: `${components.vnSubmit}`
},
claimDetail: {
secondItemDiscount: 'vn-claim-detail > vn-vertical > vn-card > div > vn-vertical > vn-table > div > vn-tbody > vn-tr:nth-child(2) > vn-td:nth-child(7) > span',
discountInput: 'vn-claim-detail vn-popover vn-input-number[model="$ctrl.newDiscount"] > div > div > div.infix > input',
discoutPopoverMana: 'vn-claim-detail > vn-popover > div > div.content > div > vn-horizontal > h5',
addItemButton: 'vn-claim-detail a vn-float-button',
firstClaimableSaleFromTicket: 'vn-claim-detail > vn-dialog vn-tbody > vn-tr',
claimDetailLine: 'vn-claim-detail > vn-vertical > vn-card > div > vn-vertical > vn-table > div > vn-tbody > vn-tr',
secondItemQuantityInput: 'vn-claim-detail vn-tr:nth-child(2) vn-input-number[model="saleClaimed.quantity"] input',
firstItemQuantityInput: 'vn-claim-detail vn-tr:nth-child(1) vn-input-number[model="saleClaimed.quantity"] input',
totalClaimed: 'vn-claim-detail > vn-vertical > vn-card > div > vn-vertical > vn-horizontal > div > vn-label-value:nth-child(2) > section > span',
secondItemDeleteButton: 'vn-claim-detail > vn-vertical > vn-card > div > vn-vertical > vn-table > div > vn-tbody > vn-tr:nth-child(2) > vn-td:nth-child(9) > vn-icon-button > button > vn-icon > i'
},
@ -623,6 +628,7 @@ export default {
secondTicketPriority: 'vn-route-tickets vn-tr:nth-child(2) vn-textfield[model="ticket.priority"] input',
thirdTicketPriority: 'vn-route-tickets vn-tr:nth-child(3) vn-textfield[model="ticket.priority"] input',
fourthTicketPriority: 'vn-route-tickets vn-tr:nth-child(4) vn-textfield[model="ticket.priority"] input',
eleventhTicketPriority: 'vn-route-tickets vn-tr:nth-child(11) vn-textfield[model="ticket.priority"] input',
firstTicketCheckbox: 'vn-route-tickets vn-tr:nth-child(1) vn-check md-checkbox',
buscamanButton: 'vn-route-tickets vn-button[icon="icon-buscaman"]',
firstTicketDeleteButton: 'vn-route-tickets vn-tr:nth-child(1) vn-icon[icon="delete"]',

View File

@ -1,13 +1,14 @@
import selectors from '../../helpers/selectors.js';
import createNightmare from '../../helpers/nightmare';
describe('Claim detail', () => {
// #1528 e2e claim/detail
xdescribe('Claim detail', () => {
const nightmare = createNightmare();
beforeAll(() => {
nightmare
.loginAndModule('salesPerson', 'claim')
.accessToSearchResult('4')
.accessToSearchResult(1)
.accessToSection('claim.card.detail');
});
@ -27,25 +28,54 @@ describe('Claim detail', () => {
expect(result).toEqual(2);
});
it('should edit de second item claimed quantity', async() => {
it('should edit de first item claimed quantity', async() => {
const result = await nightmare
.clearInput(selectors.claimDetail.secondItemQuantityInput)
.write(selectors.claimDetail.secondItemQuantityInput, 1)
.clearInput(selectors.claimDetail.firstItemQuantityInput)
.write(selectors.claimDetail.firstItemQuantityInput, 4)
.write('body', '\u000d') // simulates enter
.waitForLastSnackbar();
expect(result).toEqual('Data saved!');
});
it('should confirm the second item, and the claimed total were correctly edited', async() => {
it('should confirm the first item quantity, and the claimed total were correctly edited', async() => {
const claimedQuantity = await nightmare
.waitToGetProperty(selectors.claimDetail.secondItemQuantityInput, 'value');
.waitToGetProperty(selectors.claimDetail.firstItemQuantityInput, 'value');
const totalClaimed = await nightmare
.waitToGetProperty(selectors.claimDetail.totalClaimed, 'innerText');
expect(claimedQuantity).toEqual('1');
expect(totalClaimed).toContain('138.89');
expect(claimedQuantity).toEqual('4');
expect(totalClaimed).toContain('€47.62');
});
it('should login as salesAssistant and navigate to the claim.detail section', async() => {
const url = await nightmare
.loginAndModule('salesAssistant', 'claim')
.accessToSearchResult(1)
.accessToSection('claim.card.detail')
.waitForURL('/detail')
.parsedUrl();
expect(url.hash).toContain('/detail');
});
it('should edit de second item claimed discount', async() => {
const result = await nightmare
.waitToClick(selectors.claimDetail.secondItemDiscount)
.write(selectors.claimDetail.discountInput, 100)
.write('body', '\u000d') // simulates enter
.waitForLastSnackbar();
expect(result).toEqual('Data saved!');
});
it('should check the mana is the expected one', async() => {
const result = await nightmare
.waitToClick(selectors.claimDetail.secondItemDiscount)
.waitToGetProperty(selectors.claimDetail.discoutPopoverMana, 'innerText');
expect(result).toContain('MANÁ: €106');
});
it('should delete the second item from the claim', async() => {
@ -63,11 +93,8 @@ describe('Claim detail', () => {
expect(result).toEqual(1);
});
it('should login as salesAssistant to be redirected to the next claim section', async() => {
it('should add the deleted ticket from to the claim', async() => {
const result = await nightmare
.loginAndModule('salesAssistant', 'claim')
.accessToSearchResult('2')
.accessToSection('claim.card.detail')
.waitToClick(selectors.claimDetail.addItemButton)
.waitToClick(selectors.claimDetail.firstClaimableSaleFromTicket)
.waitForLastSnackbar();
@ -82,4 +109,13 @@ describe('Claim detail', () => {
expect(url.hash).toContain('development');
});
it('should navigate back to claim.detail to confirm the claim contains now two items', async() => {
const result = await nightmare
.accessToSection('claim.card.detail')
.wait(selectors.claimDetail.claimDetailLine)
.countElement(selectors.claimDetail.claimDetailLine);
expect(result).toEqual(2);
});
});

View File

@ -71,16 +71,25 @@ describe('claim Summary path', () => {
it(`should click on the first development worker making the worker descriptor visible`, async() => {
const visible = await nightmare
.waitToClick(selectors.claimSummary.firstDevelopmentWorker)
.wait(selectors.claimSummary.firstdevelopmentWorkerGoToClientButton)
.isVisible(selectors.claimSummary.firstdevelopmentWorkerGoToClientButton);
.wait(selectors.claimSummary.firstDevelopmentWorkerGoToClientButton)
.isVisible(selectors.claimSummary.firstDevelopmentWorkerGoToClientButton);
expect(visible).toBeTruthy();
});
it(`should check the url for the go to clientlink of the descriptor is for the right client id`, async() => {
const exists = await nightmare
.exists(selectors.claimSummary.firstdevelopmentWorkerGoToClientButton);
.exists(selectors.claimSummary.firstDevelopmentWorkerGoToClientButton);
expect(exists).toBeTruthy();
});
it(`should click on the first action ticket ID making the ticket descriptor visible`, async() => {
const visible = await nightmare
.waitToClick(selectors.claimSummary.firstActionTicketId)
.wait(selectors.claimSummary.firstActionTicketDescriptor)
.isVisible(selectors.claimSummary.firstActionTicketDescriptor);
expect(visible).toBeTruthy();
});
});

View File

@ -1,26 +1,18 @@
import selectors from '../../helpers/selectors.js';
import createNightmare from '../../helpers/nightmare';
describe('Route basic Data path', () => {
// #1528 e2e claim/detail
xdescribe('Route basic Data path', () => {
const nightmare = createNightmare();
beforeAll(() => {
nightmare
.loginAndModule('delivery', 'route')
.accessToSearchResult(2)
.accessToSearchResult(3)
.accessToSection('route.card.tickets');
});
it('should next modify the first ticket priority', async() => {
const result = await nightmare
.write(selectors.routeTickets.firstTicketPriority, 3)
.write('body', '\u000d') // simulates enter
.waitForLastSnackbar();
expect(result).toEqual('Data saved!');
});
it('should once more modify the first ticket priority', async() => {
it('should modify the first ticket priority', async() => {
const result = await nightmare
.write(selectors.routeTickets.firstTicketPriority, 2)
.write('body', '\u000d') // simulates enter
@ -29,37 +21,6 @@ describe('Route basic Data path', () => {
expect(result).toEqual('Data saved!');
});
it('should finally modify the first ticket priority', async() => {
const result = await nightmare
.write(selectors.routeTickets.firstTicketPriority, 1)
.write('body', '\u000d') // simulates enter
.waitForLastSnackbar();
expect(result).toEqual('Data saved!');
});
it('should reload the section as a pre-step to check the first ticket priority', async() => {
const result = await nightmare
.reloadSection('route.card.tickets')
.waitToGetProperty(selectors.routeTickets.firstTicketPriority, 'value');
expect(result).toEqual('1');
});
it('should confirm the second ticket priority', async() => {
const result = await nightmare
.waitToGetProperty(selectors.routeTickets.secondTicketPriority, 'value');
expect(result).toEqual('2');
});
it('should confirm the third ticket priority', async() => {
const result = await nightmare
.waitToGetProperty(selectors.routeTickets.thirdTicketPriority, 'value');
expect(result).toEqual('3');
});
it('should confirm the buscamanButton is disabled', async() => {
const result = await nightmare
.evaluate(selector => {
@ -69,7 +30,7 @@ describe('Route basic Data path', () => {
expect(result).toBeTruthy();
});
it('should check the first ticket checkbox and confirm the buscamanButton button isnt disabled anymore', async() => {
it('should check the first ticket checkbox and confirm the buscamanButton button is no longer disabled', async() => {
const result = await nightmare
.waitToClick(selectors.routeTickets.firstTicketCheckbox)
.evaluate(selector => {
@ -83,14 +44,14 @@ describe('Route basic Data path', () => {
const result = await nightmare
.waitToGetProperty(selectors.routeDescriptor.volume, 'innerText');
expect(result).toEqual('0.9 / 50 m³');
expect(result).toEqual('1.1 / 18 m³');
});
it('should count how many tickets are in route', async() => {
const result = await nightmare
.countElement('vn-route-tickets vn-textfield[model="ticket.priority"]');
expect(result).toEqual(3);
expect(result).toEqual(11);
});
it('should delete the first ticket in route', async() => {
@ -102,17 +63,26 @@ describe('Route basic Data path', () => {
expect(result).toEqual('Ticket removed from route');
});
it('should again delete the first ticket in route', async() => {
const result = await nightmare
.waitToClick(selectors.routeTickets.firstTicketDeleteButton)
.waitToClick(selectors.routeTickets.confirmButton)
.waitForLastSnackbar();
expect(result).toEqual('Ticket removed from route');
});
it('should now count how many tickets are in route to find one less', async() => {
const result = await nightmare
.countElement('vn-route-tickets vn-textfield[model="ticket.priority"]');
expect(result).toEqual(2);
expect(result).toEqual(9);
});
it('should confirm the route volume on the descriptor has been updated by the changes made', async() => {
const result = await nightmare
.waitToGetProperty(selectors.routeDescriptor.volume, 'innerText');
expect(result).toEqual('0.7 / 50 m³');
expect(result).toEqual('0.9 / 18 m³');
});
});

View File

@ -28,13 +28,11 @@ describe('claimBeginning', () => {
let refundTicketState = await app.models.TicketState.findById(ticket.id);
salesInsertedInClaimEnd = await app.models.ClaimEnd.find({where: {claimFk: claimId}});
expect(refundTicketSales.length).toEqual(2);
expect(refundTicketSales.length).toEqual(1);
expect(refundTicketSales[0].quantity).toEqual(-5);
expect(refundTicketSales[1].quantity).toEqual(-4);
expect(refundTicketObservations[0].description).toEqual('Reclama ticket: 11');
expect(refundTicketState.stateFk).toEqual(16);
expect(salesInsertedInClaimEnd[0].saleFk).toEqual(refundTicketSales[0].id);
expect(salesInsertedInClaimEnd[1].saleFk).toEqual(refundTicketSales[1].id);
});
});
});

View File

@ -1,9 +1 @@
<vn-crud-model
vn-id="model"
url="/client/api/ClientLogs"
link="{originFk: $ctrl.$stateParams.id}"
filter="$ctrl.filter"
limit="20"
data="$ctrl.logs" auto-load="false">
</vn-crud-model>
<vn-log model="model"></vn-log>
<vn-log url="/api/ClientLogs" origin-id="$ctrl.$stateParams.id"></vn-log>

View File

@ -4,44 +4,6 @@ class Controller {
constructor($scope, $stateParams) {
this.$scope = $scope;
this.$stateParams = $stateParams;
this.filter = {
include: [{
relation: 'user',
scope: {
fields: ['name'],
},
}],
};
}
get logs() {
return this._logs;
}
set logs(value) {
this._logs = value;
if (this.logs) {
this.logs.forEach(log => {
log.oldProperties = this.getInstance(log.oldInstance);
log.newProperties = this.getInstance(log.newInstance);
});
}
}
getInstance(instance) {
let validDate = /^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(.[0-9]+)?(Z)?$/;
const properties = [];
if (typeof instance == 'object' && instance != null) {
Object.keys(instance).forEach(property => {
if (validDate.test(instance[property]))
instance[property] = new Date(instance[property]).toLocaleString('es-ES');
properties.push({key: property, value: instance[property]});
});
return properties;
}
return null;
}
}

View File

@ -1,37 +0,0 @@
import './index';
describe('Client', () => {
describe('Component vnClientLog', () => {
let $componentController;
let $scope;
let controller;
beforeEach(ngModule('client'));
beforeEach(angular.mock.inject((_$componentController_, $rootScope) => {
$componentController = _$componentController_;
$scope = $rootScope.$new();
controller = $componentController('vnClientLog', {$scope: $scope});
controller.$scope.model = {data: [{newInstance: {id: 1}, oldInstance: {id: 2}}]};
}));
describe('logs setter', () => {
it('should call the function getInstance() twice', () => {
spyOn(controller, 'getInstance');
controller.logs = [{newInstance: {id: 1}, oldInstance: {id: 2}}];
expect(controller.getInstance.calls.count()).toBe(2);
expect(controller.getInstance).toHaveBeenCalledWith({id: 1});
expect(controller.getInstance).toHaveBeenCalledWith({id: 2});
});
});
describe('getInstance(instance)', () => {
it('should transform the object given in to an array', () => {
let newInstance = controller.getInstance(controller.$scope.model.data[0].newInstance);
expect(newInstance).toEqual([{key: 'id', value: 1}]);
});
});
});
});

View File

@ -8,7 +8,7 @@ describe('item getDiary()', () => {
expect(result.length).toBe(4);
expect(result[0].balance).toBe(-100);
expect(result[1].balance).toBe(-110);
expect(result[2].balance).toBe(-111);
expect(result[3].balance).toBe(-211);
expect(result[2].balance).toBe(-110);
expect(result[3].balance).toBe(-210);
});
});

View File

@ -1,9 +1 @@
<vn-crud-model
vn-id="model"
url="/api/ItemLogs"
link="{originFk: $ctrl.$stateParams.id}"
filter="$ctrl.filter"
limit="20"
data="$ctrl.logs" auto-load="false">
</vn-crud-model>
<vn-log model="model"></vn-log>
<vn-log url="/api/ItemLogs" origin-id="$ctrl.$stateParams.id"></vn-log>

View File

@ -4,44 +4,6 @@ class Controller {
constructor($scope, $stateParams) {
this.$scope = $scope;
this.$stateParams = $stateParams;
this.filter = {
include: [{
relation: 'user',
scope: {
fields: ['name'],
},
}],
};
}
get logs() {
return this._logs;
}
set logs(value) {
this._logs = value;
if (this.logs) {
this.logs.forEach(log => {
log.oldProperties = this.getInstance(log.oldInstance);
log.newProperties = this.getInstance(log.newInstance);
});
}
}
getInstance(instance) {
let validDate = /^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(.[0-9]+)?(Z)?$/;
const properties = [];
if (typeof instance == 'object' && instance != null) {
Object.keys(instance).forEach(property => {
if (validDate.test(instance[property]))
instance[property] = new Date(instance[property]).toLocaleString('es-ES');
properties.push({key: property, value: instance[property]});
});
return properties;
}
return null;
}
}

View File

@ -1,9 +1 @@
<vn-crud-model
vn-id="model"
url="/api/RouteLogs"
link="{originFk: $ctrl.$stateParams.id}"
filter="$ctrl.filter"
limit="20"
data="$ctrl.logs" auto-load="false">
</vn-crud-model>
<vn-log model="model"></vn-log>
<vn-log url="/api/RouteLogs" origin-id="$ctrl.$stateParams.id"></vn-log>

View File

@ -4,44 +4,6 @@ class Controller {
constructor($scope, $stateParams) {
this.$scope = $scope;
this.$stateParams = $stateParams;
this.filter = {
include: [{
relation: 'user',
scope: {
fields: ['name'],
},
}],
};
}
get logs() {
return this._logs;
}
set logs(value) {
this._logs = value;
if (this.logs) {
this.logs.forEach(log => {
log.oldProperties = this.getInstance(log.oldInstance);
log.newProperties = this.getInstance(log.newInstance);
});
}
}
getInstance(instance) {
let validDate = /^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(.[0-9]+)?(Z)?$/;
const properties = [];
if (typeof instance == 'object' && instance != null) {
Object.keys(instance).forEach(property => {
if (validDate.test(instance[property]))
instance[property] = new Date(instance[property]).toLocaleString('es-ES');
properties.push({key: property, value: instance[property]});
});
return properties;
}
return null;
}
}

View File

@ -1,37 +0,0 @@
import './index';
describe('Route', () => {
describe('Component vnRouteLog', () => {
let $componentController;
let $scope;
let controller;
beforeEach(ngModule('route'));
beforeEach(angular.mock.inject((_$componentController_, $rootScope) => {
$componentController = _$componentController_;
$scope = $rootScope.$new();
controller = $componentController('vnRouteLog', {$scope: $scope});
controller.$scope.model = {data: [{newInstance: {id: 1}, oldInstance: {id: 2}}]};
}));
describe('logs setter', () => {
it('should call the function getInstance() twice', () => {
spyOn(controller, 'getInstance');
controller.logs = [{newInstance: {id: 1}, oldInstance: {id: 2}}];
expect(controller.getInstance.calls.count()).toBe(2);
expect(controller.getInstance).toHaveBeenCalledWith({id: 1});
expect(controller.getInstance).toHaveBeenCalledWith({id: 2});
});
});
describe('getInstance(instance)', () => {
it('should transform the object given in to an array', () => {
let newInstance = controller.getInstance(controller.$scope.model.data[0].newInstance);
expect(newInstance).toEqual([{key: 'id', value: 1}]);
});
});
});
});

View File

@ -1,3 +1,4 @@
module.exports = Self => {
require('../methods/ticket/changeWorker')(Self);
require('../methods/ticket/getVolume')(Self);
@ -23,4 +24,24 @@ module.exports = Self => {
require('../methods/ticket/updateDiscount')(Self);
require('../methods/ticket/uploadFile')(Self);
require('../methods/ticket/addSale')(Self);
Self.observe('before save', async function(ctx) {
if (ctx.isNewInstance) return;
let changes = ctx.data || ctx.instance;
if (changes.routeFk === null && ctx.currentInstance.routeFk != null) {
let instance = JSON.parse(JSON.stringify(ctx.currentInstance));
let userId = ctx.options.accessToken.userId;
let logRecord = {
originFk: ctx.currentInstance.routeFk,
userFk: userId,
action: 'delete',
changedModel: 'Route',
oldInstance: {ticket: instance.id},
newInstance: null
};
await Self.app.models.RouteLog.create(logRecord);
}
});
};

View File

@ -1,9 +1 @@
<vn-crud-model auto-load="false"
vn-id="model"
url="/ticket/api/TicketLogs"
link="{originFk: $ctrl.$stateParams.id}"
filter="$ctrl.filter"
limit="20"
data="$ctrl.logs">
</vn-crud-model>
<vn-log model="model"></vn-log>
<vn-log url="/api/TicketLogs" origin-id="$ctrl.$stateParams.id"></vn-log>

View File

@ -4,45 +4,6 @@ class Controller {
constructor($scope, $stateParams) {
this.$scope = $scope;
this.$stateParams = $stateParams;
this.filter = {
include: [{
relation: 'user',
scope: {
fields: ['name'],
},
}],
};
}
get logs() {
return this._logs;
}
set logs(value) {
this._logs = value;
if (this.logs) {
this.logs.forEach(log => {
log.oldProperties = this.getInstance(log.oldInstance);
log.newProperties = this.getInstance(log.newInstance);
});
}
}
getInstance(instance) {
const properties = [];
let validDate = /^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(.[0-9]+)?(Z)?$/;
if (typeof instance == 'object' && instance != null) {
Object.keys(instance).forEach(property => {
if (validDate.test(instance[property]))
instance[property] = new Date(instance[property]).toLocaleString('es-ES');
properties.push({key: property, value: instance[property]});
});
return properties;
}
return null;
}
}

View File

@ -1,37 +0,0 @@
import './index';
describe('Ticket', () => {
describe('Component vnTicketLog', () => {
let $componentController;
let $scope;
let controller;
beforeEach(ngModule('ticket'));
beforeEach(angular.mock.inject((_$componentController_, $rootScope) => {
$componentController = _$componentController_;
$scope = $rootScope.$new();
controller = $componentController('vnTicketLog', {$scope: $scope});
controller.$scope.model = {data: [{newInstance: {id: 1}, oldInstance: {id: 2}}]};
}));
describe('logs setter', () => {
it('should call the function getInstance() twice', () => {
spyOn(controller, 'getInstance');
controller.logs = [{newInstance: {id: 1}, oldInstance: {id: 2}}];
expect(controller.getInstance.calls.count()).toBe(2);
expect(controller.getInstance).toHaveBeenCalledWith({id: 1});
expect(controller.getInstance).toHaveBeenCalledWith({id: 2});
});
});
describe('getInstance(instance)', () => {
it('should transform the object given in to an array', () => {
const newInstance = controller.getInstance(controller.$scope.model.data[0].newInstance);
expect(newInstance).toEqual([{key: 'id', value: 1}]);
});
});
});
});

View File

@ -1,8 +1,17 @@
<vn-crud-model
vn-id="model"
url="{{$ctrl.url}}"
filter="$ctrl.filter"
link="{originFk: $ctrl.originId}"
data="$ctrl.logs"
limit="20"
auto-load="true">
</vn-crud-model>
<vn-vertical>
<vn-card pad-large>
<vn-vertical>
<vn-title>History</vn-title>
<vn-table model="$ctrl.model">
<vn-table model="model">
<vn-thead>
<vn-tr>
<vn-th field="creationDate">Date</vn-th>
@ -15,7 +24,7 @@
</vn-tr>
</vn-thead>
<vn-tbody>
<vn-tr ng-repeat="log in $ctrl.model.data">
<vn-tr ng-repeat="log in $ctrl.logs">
<vn-td>
{{::log.creationDate | dateTime:'dd/MM/yyyy HH:mm'}}
<div class="changes">
@ -23,7 +32,7 @@
<span translate class="label">Changed by</span><span class="label">: </span>
<span
class="link"
ng-click="$ctrl.showWorkerDescriptor($event, log.user.id)"
ng-click="$ctrl.showWorkerDescriptor($event, log.user.worker.id)"
translate
class="value">{{::log.user.name | dashIfEmpty}}
</span>
@ -45,7 +54,7 @@
<vn-td class="expendable">
<span
class="link"
ng-click="$ctrl.showWorkerDescriptor($event, log.user.id)"
ng-click="$ctrl.showWorkerDescriptor($event, log.user.worker.id)"
translate
class="value">{{::log.user.name | dashIfEmpty}}
</span>
@ -89,7 +98,7 @@
</vn-tbody>
</vn-table>
</vn-vertical>
<vn-pagination model="$ctrl.model"></vn-pagination>
<vn-pagination model="model"></vn-pagination>
</vn-card>
</vn-vertical>
<vn-worker-descriptor-popover

View File

@ -10,6 +10,35 @@ export default class Controller {
'delete': 'Deletes',
'select': 'Views'
};
this.filter = {
include: [{
relation: 'user',
scope: {
fields: ['name'],
include: {
relation: 'worker',
scope: {
fields: ['id']
}
}
},
}],
};
}
get logs() {
return this._logs;
}
set logs(value) {
this._logs = value;
if (this.logs) {
this.logs.forEach(log => {
log.oldProperties = this.getInstance(log.oldInstance);
log.newProperties = this.getInstance(log.newInstance);
});
}
}
showWorkerDescriptor(event, workerFk) {
@ -22,6 +51,22 @@ export default class Controller {
this.$.workerDescriptor.parent = event.target;
this.$.workerDescriptor.show();
}
getInstance(instance) {
const properties = [];
let validDate = /^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(.[0-9]+)?(Z)?$/;
if (typeof instance == 'object' && instance != null) {
Object.keys(instance).forEach(property => {
if (validDate.test(instance[property]))
instance[property] = new Date(instance[property]).toLocaleString('es-ES');
properties.push({key: property, value: instance[property]});
});
return properties;
}
return null;
}
}
Controller.$inject = ['$scope'];
@ -30,6 +75,8 @@ ngModule.component('vnLog', {
controller: Controller,
template: require('./index.html'),
bindings: {
model: '<'
model: '<',
originId: '<',
url: '@'
}
});