#723 order.summary
This commit is contained in:
parent
5dabb5625c
commit
060ab04084
|
@ -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;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -1,9 +1,94 @@
|
|||
<vn-vertical vn-one>
|
||||
<vn-card class="summary" pad-medium>
|
||||
<vn-card class="summary ticketSummary" pad-medium>
|
||||
<vn-vertical margin-medium>
|
||||
<vn-auto>
|
||||
<h5 text-center pad-small-v class="title">Order</h5>
|
||||
<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-vertical>
|
||||
<vn-item-descriptor-popover vn-id="descriptor"
|
||||
quicklinks="$ctrl.quicklinks">
|
||||
</vn-item-descriptor-popover>
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
Controller.$inject = ['$http'];
|
||||
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 = ['$scope', '$http', '$state'];
|
||||
|
||||
ngModule.component('vnOrderSummary', {
|
||||
template: require('./index.html'),
|
||||
|
|
|
@ -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)');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
};
|
Loading…
Reference in New Issue