#723 order.summary

This commit is contained in:
Gerard 2018-10-10 12:55:04 +02:00
parent 5dabb5625c
commit 060ab04084
9 changed files with 305 additions and 15 deletions

View File

@ -47,7 +47,7 @@ class Controller {
let query = `/order/api/Orders/${this.$state.params.id}/getTotal`;
this.$http.get(query).then(res => {
if (res.data) {
this.order.total = res.data.total;
this.order.total = res.data;
}
});
}

View File

@ -48,7 +48,7 @@ describe('Order', () => {
describe('getTotal()', () => {
it(`should make a query and save the data in order.total`, () => {
$httpBackend.expectGET(`/order/api/Orders/${controller.$state.params.id}/getTotal`).respond({total: '20M'});
$httpBackend.expectGET(`/order/api/Orders/${controller.$state.params.id}/getTotal`).respond('20M');
controller.getTotal();
$httpBackend.flush();

View File

@ -1,9 +1,94 @@
<vn-vertical vn-one>
<vn-card class="summary" pad-medium>
<vn-vertical margin-medium>
<vn-auto>
<h5 text-center pad-small-v class="title">Order</h5>
</vn-auto>
</vn-vertical>
</vn-card>
</vn-vertical>
<vn-card class="summary ticketSummary" pad-medium>
<vn-vertical margin-medium>
<vn-auto>
<h5 text-center pad-small-v class="title">{{$ctrl.summary.id}} - {{$ctrl.summary.client.name}} - {{$ctrl.summary.client.salesPerson.id}}</h5>
</vn-auto>
<vn-horizontal class="ticketSummary__data" pad-medium-v>
<vn-one>
<vn-label-value label="Id"
value="{{::$ctrl.summary.id}}">
</vn-label-value>
<vn-label-value label="Nickname"
value="{{::$ctrl.summary.address.nickname}}">
</vn-label-value>
<vn-label-value label="Confirmed"
value="{{::$ctrl.summary.isConfirmed}}">
</vn-label-value>
<vn-label-value label="Warehouse"
value="{{::$ctrl.summary.sourceApp}}">
</vn-label-value>
</vn-one>
<vn-one>
<vn-label-value label="Created"
value="{{::$ctrl.summary.created | date: 'dd/MM/yyyy HH:mm'}}">
</vn-label-value>
<vn-label-value label="Confirmed"
value="{{::$ctrl.summary.confirmed | date: 'dd/MM/yyyy'}}">
</vn-label-value>
<vn-label-value label="Address"
value="{{::$ctrl.formattedAddress}}">
<vn-label-value label="Phone"
value="{{::$ctrl.summary.address.phone}}">
</vn-label-value>
</vn-one>
<vn-one>
<vn-label-value label="{{'Notes'}}"
value="{{::$ctrl.summary.note}}">
</vn-label-value>
</vn-one>
<vn-one class="ticketSummary__taxes">
<section>
<p><vn-label translate>Subtotal</vn-label> {{::$ctrl.summary.subTotal | currency:' €':2}}</p>
<p><vn-label translate>VAT</vn-label> {{::$ctrl.summary.VAT | currency:' €':2}}</p>
<p><vn-label><strong>Total</strong></vn-label> <strong>{{::$ctrl.summary.total | currency:' €':2}}</strong></p>
</section>
</vn-one>
</vn-horizontal>
<vn-horizontal>
<table class="vn-grid">
<thead>
<tr>
<th></th>
<th number translate>Item</th>
<th translate>Description</th>
<th number translate>Quantity</th>
<th number translate>Price</th>
<th number translate>Amount</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in $ctrl.summary.rows track by row.id">
<td>
<vn-icon
ng-show="row.visible || row.available"
orange
icon="warning"
vn-tooltip="Visible: {{::row.visible || 0}} <br> {{::$ctrl.translate.instant('Available')}} {{::row.available || 0}}">
</vn-icon>
<vn-icon ng-show="row.reserved" icon="icon-reserva"></vn-icon>
</td>
<td number>
<span
ng-click="$ctrl.showDescriptor($event, row.itemFk)"
class="link" pointer>
{{("000000"+row.itemFk).slice(-6)}}
</span>
</td>
<td><vn-fetched-tags concept="row.item.name" tags="row.item.tags"/></td>
<td number>{{::row.quantity}}</td>
<td number>{{::row.price | currency:'€':2}}</td>
<td number>{{::row.quantity * row.price | currency:'€':2}}</td>
</tr>
<tr ng-if="!$ctrl.summary.rows" class="list list-element">
<td colspan="8" style="text-align: center" translate>No results</td>
</tr>
</tbody>
</table>
</vn-horizontal>
</vn-vertical>
</vn-card>
<vn-item-descriptor-popover vn-id="descriptor"
quicklinks="$ctrl.quicklinks">
</vn-item-descriptor-popover>

View File

@ -1,12 +1,55 @@
import ngModule from '../module';
import './style.scss';
class Controller {
constructor($http) {
constructor($scope, $http, $state) {
this.$scope = $scope;
this.$http = $http;
this.$state = $state;
this.setSummary();
}
setSummary() {
this.$http.get(`/order/api/Orders/${this.$state.params.id}/summary`).then(res => {
if (res && res.data) {
this.summary = res.data;
console.log(res.data);
}
});
}
get formattedAddress() {
if (!this.summary) return;
let address = this.summary.address;
let province = address.province ? `(${address.province.name})` : '';
return `${address.street} - ${address.city} ${province}`;
}
/* showDescriptor(event, itemFk) {
this.quicklinks = {
btnThree: {
icon: 'icon-transaction',
state: `item.card.diary({
id: ${itemFk},
warehouseFk: ${this.ticket.warehouseFk},
ticketFk: ${this.ticket.id}
})`,
tooltip: 'Item diary'
}
};
this.$scope.descriptor.itemFk = itemFk;
this.$scope.descriptor.parent = event.target;
this.$scope.descriptor.show();
}
onDescriptorLoad() {
this.$scope.popover.relocate();
} */
}
Controller.$inject = ['$http'];
Controller.$inject = ['$scope', '$http', '$state'];
ngModule.component('vnOrderSummary', {
template: require('./index.html'),

View File

@ -0,0 +1,50 @@
import './index';
describe('Ticket', () => {
describe('Component vnTicketSummary', () => {
let $componentController;
let controller;
let $httpBackend;
beforeEach(() => {
angular.mock.module('ticket');
});
beforeEach(angular.mock.inject((_$componentController_, _$httpBackend_) => {
$componentController = _$componentController_;
$httpBackend = _$httpBackend_;
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
controller = $componentController('vnTicketSummary');
controller.ticket = {id: 1};
}));
describe('ticket()', () => {
it('should perform a GET query and define summary property', () => {
let res = {id: 1, nickname: 'Batman'};
$httpBackend.when('GET', `/ticket/api/Tickets/1/summary`).respond(200, res);
$httpBackend.expect('GET', `/ticket/api/Tickets/1/summary`);
controller.ticket = {id: 1};
$httpBackend.flush();
expect(controller.summary).toBeDefined();
expect(controller.summary.nickname).toEqual('Batman');
});
});
describe('formattedAddress()', () => {
it('should return a full fromatted address with city and province', () => {
controller.summary = {
address: {
province: {
name: 'Gotham'
},
street: '1007 Mountain Drive',
city: 'Gotham'
}
};
expect(controller.formattedAddress).toEqual('1007 Mountain Drive - Gotham (Gotham)');
});
});
});
});

View File

@ -0,0 +1,25 @@
.ticketSummary {
.ticketSummary__data {
vn-one {
padding-right: 20px
}
vn-one:last-child {
padding-right: 0
}
}
.ticketSummary__notes {
max-width: 18em
}
.ticketSummary__taxes {
max-width: 15em;
& section {
border: 1px solid #CCC;
text-align: right;
padding: 10px
}
}
}

View File

@ -23,6 +23,6 @@ module.exports = Self => {
let query = `SELECT hedera.orderGetTotal(?) total;`;
let [total] = await Self.rawSql(query, [orderFk]);
return total;
return total.total;
};
};

View File

@ -16,7 +16,7 @@ describe('order getTaxes()', () => {
it('should call the getTaxes method and return the taxes if its called with a known id', async() => {
let result = await app.models.Order.getTaxes(1);
expect(result[0].tax).toEqual(0.95);
expect(result[0].tax).toEqual(9.49);
expect(result.length).toEqual(1);
});
});

View File

@ -0,0 +1,87 @@
module.exports = Self => {
Self.remoteMethod('summary', {
description: 'Returns a summary for a given order id',
accessType: 'READ',
accepts: [{
arg: 'id',
type: 'number',
required: true,
description: 'order id',
http: {source: 'path'}
}],
returns: {
type: [this.modelName],
root: true
},
http: {
path: `/:id/summary`,
verb: 'GET'
}
});
Self.summary = async orderId => {
let models = Self.app.models;
let summary = await getOrderData(Self, orderId);
summary.subTotal = getSubTotal(summary.rows);
summary.VAT = await models.Order.getVAT(orderId);
summary.total = await models.Order.getTotal(orderId);
return summary;
};
async function getOrderData(Self, orderId) {
let filter = {
include: [
{relation: 'agencyMode', scope: {fields: ['name']}},
{
relation: 'client',
scope: {
fields: ['salesPersonFk', 'name'],
include: {
relation: 'salesPerson',
fields: ['firstName', 'name']
}
}
},
{
relation: 'address',
scope: {
fields: ['street', 'city', 'provinceFk', 'phone', 'nickname'],
include: {
relation: 'province',
scope: {
fields: ['name']
}
}
}
},
{
relation: 'rows',
scope: {
include: {
relation: 'item',
scope: {
include: {
relation: 'tags'
}
}
}
}
}
],
where: {id: orderId}
};
return await Self.findOne(filter);
}
function getSubTotal(rows) {
let subTotal = 0.00;
rows().forEach(row => {
subTotal += row.quantity * row.price;
});
return subTotal;
}
};