This commit is contained in:
Juan Ferrer 2019-01-14 17:27:11 +01:00
commit d539a345b0
14 changed files with 213 additions and 39 deletions

View File

@ -406,6 +406,22 @@ export default {
firstDescription: 'vn-ticket-request-index > form > vn-card > div > vn-horizontal > vn-table > div > vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(2)', firstDescription: 'vn-ticket-request-index > form > vn-card > div > vn-horizontal > vn-table > div > vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(2)',
}, },
ticketLog: {
logButton: `vn-left-menu a[ui-sref="ticket.card.log"]`,
changedBy: 'vn-ticket-log > vn-log > vn-vertical > vn-card > div > vn-vertical > vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(1) > div > div:nth-child(1) > span.value.ng-scope.ng-binding',
actionTaken: 'vn-ticket-log > vn-log > vn-vertical > vn-card > div > vn-vertical > vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(1) > div > div:nth-child(3) > span.value.ng-scope.ng-binding',
id: 'vn-ticket-log > vn-log > vn-vertical > vn-card > div > vn-vertical > vn-table > div > vn-tbody > vn-tr > vn-td.before > vn-one:nth-child(1) > div > span.value.ng-scope.ng-binding'
},
ticketService: {
serviceButton: 'vn-left-menu a[ui-sref="ticket.card.service"]',
addServiceButton: 'vn-ticket-service > form > vn-card > div > vn-one:nth-child(3) > vn-icon-button > button > vn-icon',
descriptionInput: 'vn-ticket-service vn-textfield[label="Description"] input',
quantityInput: 'vn-ticket-service vn-textfield[label="Quantity"] input',
priceInput: 'vn-ticket-service vn-textfield[label="Price"] input',
vatTypeAutocomplete: 'vn-ticket-service vn-autocomplete[label="Tax class"]',
fistDeleteServiceButton: 'vn-ticket-service > form > vn-card > div > vn-one:nth-child(2) > vn-horizontal > vn-auto > vn-icon',
saveServiceButton: `${components.vnSubmit}`
},
createStateView: { createStateView: {
stateAutocomplete: `vn-autocomplete[field="$ctrl.ticket.stateFk"]`, stateAutocomplete: `vn-autocomplete[field="$ctrl.ticket.stateFk"]`,
clearStateInputButton: `vn-autocomplete[field="$ctrl.ticket.stateFk"] > div > div > div > vn-icon > i`, clearStateInputButton: `vn-autocomplete[field="$ctrl.ticket.stateFk"] > div > div > div > vn-icon > i`,

View File

@ -11,7 +11,7 @@ describe('Client log path', () => {
.accessToSection('client.card.basicData'); .accessToSection('client.card.basicData');
}); });
it('should update the clients name', async () => { it('should update the clients name', async() => {
let result = await nightmare let result = await nightmare
.wait(selectors.clientBasicData.nameInput) .wait(selectors.clientBasicData.nameInput)
.clearInput(selectors.clientBasicData.nameInput) .clearInput(selectors.clientBasicData.nameInput)
@ -22,7 +22,7 @@ describe('Client log path', () => {
expect(result).toEqual('Data saved!'); expect(result).toEqual('Data saved!');
}); });
it('should navigate to the log section', async () => { it('should navigate to the log section', async() => {
let url = await nightmare let url = await nightmare
.waitToClick(selectors.clientLog.logButton) .waitToClick(selectors.clientLog.logButton)
.waitForURL('log') .waitForURL('log')
@ -31,14 +31,14 @@ describe('Client log path', () => {
expect(url.hash).toContain('log'); expect(url.hash).toContain('log');
}); });
it('should check the previous value of the last logged change', async () => { it('should check the previous value of the last logged change', async() => {
let lastModificationPreviousValue = await nightmare let lastModificationPreviousValue = await nightmare
.waitToGetProperty(selectors.clientLog.lastModificationPreviousValue, 'innerText'); .waitToGetProperty(selectors.clientLog.lastModificationPreviousValue, 'innerText');
expect(lastModificationPreviousValue).toContain('DavidCharlesHaller'); expect(lastModificationPreviousValue).toContain('DavidCharlesHaller');
}); });
it('should check the current value of the last logged change', async () => { it('should check the current value of the last logged change', async() => {
let lastModificationCurrentValue = await nightmare let lastModificationCurrentValue = await nightmare
.waitToGetProperty(selectors.clientLog.lastModificationCurrentValue, 'innerText'); .waitToGetProperty(selectors.clientLog.lastModificationCurrentValue, 'innerText');

View File

@ -1,12 +1,13 @@
import selectors from '../../helpers/selectors.js'; import selectors from '../../helpers/selectors.js';
import createNightmare from '../../helpers/nightmare'; import createNightmare from '../../helpers/nightmare';
describe('Ticket Delete expeditions path', () => { // #776
xdescribe('Ticket expeditions and log path', () => {
const nightmare = createNightmare(); const nightmare = createNightmare();
beforeAll(() => { beforeAll(() => {
return nightmare return nightmare
.loginAndModule('production', 'ticket') .loginAndModule('developer', 'ticket')
.accessToSearchResult('id:1') .accessToSearchResult('id:1')
.accessToSection('ticket.card.expedition'); .accessToSection('ticket.card.expedition');
}); });
@ -23,4 +24,18 @@ describe('Ticket Delete expeditions path', () => {
expect(result).toEqual(3); expect(result).toEqual(3);
}); });
it(`should confirm the expedition deleted is shown now in the ticket log`, async() => {
const changedBy = await nightmare
.waitToClick(selectors.ticketLog.logButton)
.waitToGetProperty(selectors.ticketLog.changedBy, 'innerText');
const actionTaken = await nightmare
.waitToGetProperty(selectors.ticketLog.actionTaken, 'innerText');
const id = await nightmare
.waitToGetProperty(selectors.ticketLog.id, 'innerText');
expect(changedBy).toEqual('production');
expect(actionTaken).toEqual('Deletes');
expect(id).toEqual('3');
});
}); });

View File

@ -381,7 +381,7 @@ describe('Ticket Edit sale path', () => {
expect(result).toEqual(3); expect(result).toEqual(3);
}); });
it('should go back to the original ticket sales section', async() => { it('should now go back to the original ticket sales section', async() => {
const url = await nightmare const url = await nightmare
.waitToClick(selectors.itemsIndex.goBackToModuleIndexButton) .waitToClick(selectors.itemsIndex.goBackToModuleIndexButton)
.wait(selectors.ticketsIndex.searchTicketInput) .wait(selectors.ticketsIndex.searchTicketInput)

View File

@ -9,7 +9,7 @@ describe('Ticket descriptor path', () => {
.loginAndModule('employee', 'ticket'); .loginAndModule('employee', 'ticket');
}); });
it('should search for a specific ticket', async () => { it('should search for a specific ticket', async() => {
const result = await nightmare const result = await nightmare
.wait(selectors.ticketsIndex.searchTicketInput) .wait(selectors.ticketsIndex.searchTicketInput)
.type(selectors.ticketsIndex.searchTicketInput, 'id:17') .type(selectors.ticketsIndex.searchTicketInput, 'id:17')
@ -20,7 +20,7 @@ describe('Ticket descriptor path', () => {
expect(result).toEqual(1); expect(result).toEqual(1);
}); });
it(`should click on the search result to access to the ticket Sale`, async () => { it(`should click on the search result to access to the ticket Sale`, async() => {
const url = await nightmare const url = await nightmare
.waitForTextInElement(selectors.ticketsIndex.searchResult, 'address 26') .waitForTextInElement(selectors.ticketsIndex.searchResult, 'address 26')
.waitToClick(selectors.ticketsIndex.searchResult) .waitToClick(selectors.ticketsIndex.searchResult)
@ -30,7 +30,7 @@ describe('Ticket descriptor path', () => {
expect(url.hash).toContain('/summary'); expect(url.hash).toContain('/summary');
}); });
it('should delete the ticket using the descriptor more menu', async () => { it('should delete the ticket using the descriptor more menu', async() => {
const result = await nightmare const result = await nightmare
.waitToClick(selectors.ticketDescriptor.moreMenu) .waitToClick(selectors.ticketDescriptor.moreMenu)
.waitToClick(selectors.ticketDescriptor.moreMenuDeleteTicket) .waitToClick(selectors.ticketDescriptor.moreMenuDeleteTicket)
@ -40,14 +40,14 @@ describe('Ticket descriptor path', () => {
expect(result).toEqual('Ticket deleted'); expect(result).toEqual('Ticket deleted');
}); });
it('should have been relocated to the ticket index', async () => { it('should have been relocated to the ticket index', async() => {
const url = await nightmare const url = await nightmare
.parsedUrl(); .parsedUrl();
expect(url.hash).toEqual('#!/ticket/index'); expect(url.hash).toEqual('#!/ticket/index');
}); });
it(`should search for the deleted ticket and check it's date`, async () => { it(`should search for the deleted ticket and check it's date`, async() => {
const result = await nightmare const result = await nightmare
.wait(selectors.ticketsIndex.searchTicketInput) .wait(selectors.ticketsIndex.searchTicketInput)
.type(selectors.ticketsIndex.searchTicketInput, 'id:17') .type(selectors.ticketsIndex.searchTicketInput, 'id:17')

View File

@ -0,0 +1,71 @@
import selectors from '../../helpers/selectors.js';
import createNightmare from '../../helpers/nightmare';
// Bug #961 ticket.service fallo en borrado
xdescribe('Ticket services path', () => {
const nightmare = createNightmare();
beforeAll(() => {
nightmare
.loginAndModule('employee', 'ticket')
.accessToSearchResult('id:1')
.accessToSection('ticket.card.service');
});
it('should create a new service', async() => {
const result = await nightmare
.waitToClick(selectors.ticketService.addServiceButton)
.write(selectors.ticketService.descriptionInput, 'my service')
.clearInput(selectors.ticketService.quantityInput)
.write(selectors.ticketService.quantityInput, 99)
.write(selectors.ticketService.priceInput, 999)
.autocompleteSearch(selectors.ticketService.vatTypeAutocomplete, 'Reduced VAT')
.waitToClick(selectors.ticketService.saveServiceButton)
.waitForLastSnackbar();
expect(result).toEqual('Data saved!');
});
it('should confirm the service description was created correctly', async() => {
const result = await nightmare
.waitToClick(selectors.ticketBasicData.basicDataButton)
.wait(selectors.ticketBasicData.clientAutocomplete)
.click(selectors.ticketService.serviceButton)
.waitToGetProperty(selectors.ticketService.descriptionInput, 'value');
expect(result).toEqual('my service');
});
it('should confirm the service quantity was created correctly', async() => {
const result = await nightmare
.waitToGetProperty(selectors.ticketService.quantityInput, 'value');
expect(result).toEqual('99');
});
it('should confirm the service price was created correctly', async() => {
const result = await nightmare
.waitToGetProperty(selectors.ticketService.priceInput, 'value');
expect(result).toEqual('999');
});
it('should confirm the service VAT was created correctly', async() => {
const result = await nightmare
.waitToGetProperty(`${selectors.ticketService.vatTypeAutocomplete} input`, 'value');
expect(result).toEqual('Reduced VAT');
});
it('should delete the service and check there are none now', async() => {
const result = await nightmare
.waitToClick(selectors.ticketService.fistDeleteServiceButton)
.waitToClick(selectors.ticketBasicData.basicDataButton)
.wait(selectors.ticketBasicData.clientAutocomplete)
.click(selectors.ticketService.serviceButton)
.waitForNumberOfElements(selectors.ticketService.descriptionInput, 0)
.countElement(selectors.ticketService.descriptionInput);
expect(result).toEqual(0);
});
});

View File

@ -4,27 +4,32 @@
fields="['id', 'claimFk', 'claimReasonFk', 'claimResultFk', 'claimResponsibleFk', 'workerFk', 'claimRedeliveryFk']" fields="['id', 'claimFk', 'claimReasonFk', 'claimResultFk', 'claimResponsibleFk', 'workerFk', 'claimRedeliveryFk']"
link="{claimFk: $ctrl.$state.params.id}" link="{claimFk: $ctrl.$state.params.id}"
filter="$ctrl.filter" filter="$ctrl.filter"
data="claimDevelopments"> data="claimDevelopments"
auto-load="true">
</vn-crud-model> </vn-crud-model>
<vn-crud-model <vn-crud-model
url="claim/api/ClaimReasons" url="claim/api/ClaimReasons"
data="claimReasons" data="claimReasons"
order="description"> order="description"
auto-load="true">
</vn-crud-model> </vn-crud-model>
<vn-crud-model <vn-crud-model
url="claim/api/ClaimResults" url="claim/api/ClaimResults"
data="claimResults" data="claimResults"
order="description"> order="description"
auto-load="true">
</vn-crud-model> </vn-crud-model>
<vn-crud-model <vn-crud-model
url="claim/api/ClaimResponsibles" url="claim/api/ClaimResponsibles"
data="claimResponsibles" data="claimResponsibles"
order="description"> order="description"
auto-load="true">
</vn-crud-model> </vn-crud-model>
<vn-crud-model <vn-crud-model
url="claim/api/ClaimRedeliveries" url="claim/api/ClaimRedeliveries"
data="claimRedeliveries" data="claimRedeliveries"
order="description"> order="description"
auto-load="true">
</vn-crud-model> </vn-crud-model>
<vn-watcher <vn-watcher
vn-id="watcher" vn-id="watcher"

View File

@ -0,0 +1,26 @@
module.exports = Self => {
Self.remoteMethod('confirm', {
description: 'Gets the taxes of a given order',
accessType: 'WRITE',
accepts: [{
arg: 'id',
type: 'number',
required: true,
description: 'order id',
http: {source: 'path'}
}],
returns: {
type: 'object',
root: true
},
http: {
path: `/:id/confirm`,
verb: 'POST'
}
});
Self.confirm = async orderFk => {
let query = `CALL hedera.orderConfirm(?);`;
return await Self.rawSql(query, [orderFk]);
};
};

View File

@ -11,4 +11,5 @@ module.exports = Self => {
require('../methods/order/getSourceValues')(Self); require('../methods/order/getSourceValues')(Self);
require('../methods/order/newFromTicket')(Self); require('../methods/order/newFromTicket')(Self);
require('../methods/order/updateBasicData')(Self); require('../methods/order/updateBasicData')(Self);
require('../methods/order/confirm')(Self);
}; };

View File

@ -22,7 +22,7 @@
value="{{$ctrl.order.client.salesPerson.firstName}} {{$ctrl.order.client.salesPerson.name}}"> value="{{$ctrl.order.client.salesPerson.firstName}} {{$ctrl.order.client.salesPerson.name}}">
</vn-label-value> </vn-label-value>
<vn-label-value label="Landed" <vn-label-value label="Landed"
value="{{$ctrl.order.landed | date: 'dd/MM/yyyy HH:mm' }}"> value="{{$ctrl.order.landed | date: 'dd/MM/yyyy' }}">
</vn-label-value> </vn-label-value>
<vn-label-value label="Agency" <vn-label-value label="Agency"
value="{{$ctrl.order.agencyMode.name}}"> value="{{$ctrl.order.agencyMode.name}}">

View File

@ -11,7 +11,7 @@
<div class="totalBox"> <div class="totalBox">
<vn-label translate>Subtotal</vn-label> <vn-label translate>Subtotal</vn-label>
<span>{{$ctrl.order.total - $ctrl.VAT | currency:'€':2}}</span> <span>{{$ctrl.subtotal | currency:'€':2}}</span>
<p> <p>
<vn-label translate>VAT</vn-label> <vn-label translate>VAT</vn-label>
<span>{{$ctrl.VAT | currency:'€':2}}</span> <span>{{$ctrl.VAT | currency:'€':2}}</span>
@ -49,7 +49,7 @@
</vn-td> </vn-td>
<vn-td><vn-fetched-tags max-length="6" item="row.item"/></vn-td> <vn-td><vn-fetched-tags max-length="6" item="row.item"/></vn-td>
<vn-td>{{row.warehouse.name}}</vn-td> <vn-td>{{row.warehouse.name}}</vn-td>
<vn-td>{{row.shipped | dashIfEmpty}}</vn-td> <vn-td>{{row.shipped | date: 'dd/MM/yyyy'}}</vn-td>
<vn-td number>{{row.quantity}}</vn-td> <vn-td number>{{row.quantity}}</vn-td>
<vn-td number> <vn-td number>
{{row.price | currency:'€':2}} {{row.price | currency:'€':2}}
@ -59,7 +59,7 @@
medium-grey medium-grey
vn-tooltip="Remove item" vn-tooltip="Remove item"
icon="delete" icon="delete"
ng-click="$ctrl.removeRow($index)" ng-click="$ctrl.showDeleteRow($index)"
tabindex="-1"> tabindex="-1">
</vn-icon-button> </vn-icon-button>
</vn-td> </vn-td>
@ -81,4 +81,11 @@
<vn-item-descriptor-popover <vn-item-descriptor-popover
vn-id="descriptor"> vn-id="descriptor">
</vn-item-descriptor-popover> </vn-item-descriptor-popover>
<vn-confirm
vn-id="delete-row"
on-response="$ctrl.deleteRow(response)"
question="Delete row"
message="Are you sure you want to delete this row?">
</vn-confirm>

View File

@ -13,9 +13,17 @@ class Controller {
$onInit() { $onInit() {
this.getRows(); this.getRows();
}
set order(value) {
this._order = value;
this.getVAT(); this.getVAT();
} }
get order() {
return this._order;
}
getRows() { getRows() {
let filter = { let filter = {
where: {orderFk: this.$state.params.id}, where: {orderFk: this.$state.params.id},
@ -40,9 +48,32 @@ class Controller {
}); });
} }
removeRow(index) { get subtotal() {
let [lineRemoved] = this.rows.splice(index, 1); return this.order.total - this.VAT || 0;
this.idsToRemove.push(lineRemoved.id); }
showDeleteRow(index) {
this.lineIdToRemove = index;
this.$scope.deleteRow.show();
}
deleteRow(response) {
if (response == 'ACCEPT') {
let [lineRemoved] = this.rows.splice(this.lineIdToRemove, 1);
this.idsToRemove.push(lineRemoved.id);
let params = {
rows: this.idsToRemove,
actualOrderId: this.$state.params.id
};
let query = `/order/api/OrderRows/removes`;
this.$http.post(query, params).then(() => {
this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
});
this.getVAT();
this.card.reload();
}
this.lineIdToRemove = undefined;
} }
// Item Descriptor // Item Descriptor
@ -57,14 +88,10 @@ class Controller {
} }
save() { save() {
let params = { let query = `/api/Orders/${this.order.id}/confirm`;
rows: this.idsToRemove,
actualOrderId: this.$state.params.id
};
let query = `/order/api/OrderRows/removes`;
this.$http.post(query, params).then(() => { this.$http.post(query).then(() => {
this.vnApp.showSuccess(this.$translate.instant('Data saved!')); this.vnApp.showSuccess(this.$translate.instant('Order confirmed'));
}); });
} }
} }
@ -76,5 +103,8 @@ ngModule.component('vnOrderLine', {
controller: Controller, controller: Controller,
bindings: { bindings: {
order: '<' order: '<'
},
require: {
card: '^vnOrderCard'
} }
}); });

View File

@ -58,9 +58,9 @@ class Controller {
} }
addQuantity(price) { addQuantity(price) {
if (this.total + price.grouping <= this.max) { if (this.total + price.grouping <= this.max)
price.quantity += price.grouping; price.quantity += price.grouping;
}
this.validate(); this.validate();
} }
validate() { validate() {
@ -76,11 +76,10 @@ class Controller {
}); });
let wrongInputs = this.$element[0].querySelectorAll('vn-input-number[name="quantity"] div.infix.invalid'); let wrongInputs = this.$element[0].querySelectorAll('vn-input-number[name="quantity"] div.infix.invalid');
if (wrongInputs.length > 0) { if (wrongInputs.length > 0)
this.$element[0].querySelector('vn-vertical.prices').classList.add('invalid'); this.$element[0].querySelector('vn-vertical.prices').classList.add('invalid');
} else { else
this.$element[0].querySelector('vn-vertical.prices').classList.remove('invalid'); this.$element[0].querySelector('vn-vertical.prices').classList.remove('invalid');
}
}); });
} }
getFilledLines() { getFilledLines() {
@ -119,6 +118,7 @@ class Controller {
this.$http.post(`/order/api/OrderRows/addToOrder`, params).then(res => { this.$http.post(`/order/api/OrderRows/addToOrder`, params).then(res => {
this.vnApp.showSuccess(this.$translate.instant('Data saved!')); this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
this.$.popover.hide(); this.$.popover.hide();
this.card.reload();
}); });
}); });
} }
@ -131,5 +131,8 @@ ngModule.component('vnOrderPricesPopover', {
controller: Controller, controller: Controller,
bindings: { bindings: {
order: '<' order: '<'
},
require: {
card: '^vnOrderCard'
} }
}); });

View File

@ -14,10 +14,10 @@
<vn-title vn-two>Volume</vn-title> <vn-title vn-two>Volume</vn-title>
<div class="totalBox"> <div class="totalBox">
<vn-label-value label="Total" <vn-label-value label="Total"
value="{{::edit.model.totalVolume}}"> value="{{::edit.model.totalVolume}}">
</vn-label-value> </vn-label-value>
<vn-label-value label="Cajas" <vn-label-value label="Cajas"
value="{{::edit.model.totalBoxes}}"> value="{{::edit.model.totalBoxes | dashIfEmpty}} U">
</vn-label-value> </vn-label-value>
</div> </div>
</vn-horizontal> </vn-horizontal>