Tarea #438 order.line
This commit is contained in:
parent
da9a783843
commit
65ffade0a3
|
@ -0,0 +1,82 @@
|
||||||
|
<vn-watcher
|
||||||
|
vn-id="watcher"
|
||||||
|
data="$ctrl.rows">
|
||||||
|
</vn-watcher>
|
||||||
|
|
||||||
|
<vn-vertical>
|
||||||
|
<vn-card pad-large>
|
||||||
|
<vn-vertical>
|
||||||
|
<vn-horizontal>
|
||||||
|
<vn-title vn-two>Sale</vn-title>
|
||||||
|
|
||||||
|
<div class="totalBox">
|
||||||
|
<vn-label translate>Subtotal</vn-label>
|
||||||
|
<span>{{$ctrl.order.total - $ctrl.VAT | currency:'€':2}}</span>
|
||||||
|
<p>
|
||||||
|
<vn-label translate>VAT</vn-label>
|
||||||
|
<span>{{$ctrl.VAT | currency:'€':2}}</span>
|
||||||
|
</p>
|
||||||
|
<vn-label><strong>Total</strong></vn-label>
|
||||||
|
<strong>{{$ctrl.order.total | currency:'€':2}}</strong>
|
||||||
|
</div>
|
||||||
|
</vn-horizontal>
|
||||||
|
<vn-table model="model">
|
||||||
|
<vn-thead>
|
||||||
|
<vn-tr>
|
||||||
|
<vn-th style="text-align: center">Item</vn-th>
|
||||||
|
<vn-th style="text-align: center">ID</vn-th>
|
||||||
|
<vn-th>Description</vn-th>
|
||||||
|
<vn-th>Warehouse</vn-th>
|
||||||
|
<vn-th>Shipped</vn-th>
|
||||||
|
<vn-th number>Quantity</vn-th>
|
||||||
|
<vn-th number>Price</vn-th>
|
||||||
|
<vn-th ng-if="!$ctrl.order.isConfirmed"></vn-th>
|
||||||
|
</vn-tr>
|
||||||
|
</vn-thead>
|
||||||
|
<vn-tbody>
|
||||||
|
<vn-tr ng-repeat="row in $ctrl.rows">
|
||||||
|
<vn-td style="text-align: center">
|
||||||
|
<img
|
||||||
|
ng-src="//verdnatura.es/vn-image-data/catalog/50x50/{{::row.item.image}}"
|
||||||
|
zoom-image="//verdnatura.es/vn-image-data/catalog/1600x900/{{::row.item.image}}"
|
||||||
|
on-error-src/>
|
||||||
|
</vn-td>
|
||||||
|
<vn-td ng-click="$ctrl.showDescriptor($event, row.itemFk)"
|
||||||
|
pointer number class="link">
|
||||||
|
{{("000000"+row.itemFk).slice(-6)}}
|
||||||
|
</vn-td>
|
||||||
|
<vn-td><vn-fetched-tags concept="row.item.name" tags="row.item.tags"/></vn-td>
|
||||||
|
<vn-td>{{row.warehouse.name}}</vn-td>
|
||||||
|
<vn-td>{{row.shipped | dashIfEmpty}}</vn-td>
|
||||||
|
<vn-td number>{{row.quantity}}</vn-td>
|
||||||
|
<vn-td number>
|
||||||
|
{{row.price | currency:'€':2}}
|
||||||
|
</vn-td>
|
||||||
|
<vn-td ng-if="!$ctrl.order.isConfirmed">
|
||||||
|
<vn-icon-button
|
||||||
|
medium-grey
|
||||||
|
vn-tooltip="Remove item"
|
||||||
|
icon="remove_circle_outline"
|
||||||
|
ng-click="$ctrl.removeRow($index)"
|
||||||
|
tabindex="-1">
|
||||||
|
</vn-icon-button>
|
||||||
|
</vn-td>
|
||||||
|
</vn-tr>
|
||||||
|
</vn-tbody>
|
||||||
|
<vn-empty-rows ng-if="$ctrl.rows.length === 0" translate>
|
||||||
|
No results
|
||||||
|
</vn-empty-rows>
|
||||||
|
</vn-table>
|
||||||
|
</vn-vertical>
|
||||||
|
</vn-card>
|
||||||
|
<vn-button-bar ng-if="!$ctrl.order.isConfirmed">
|
||||||
|
<vn-button
|
||||||
|
label="Save"
|
||||||
|
ng-click="$ctrl.save()">
|
||||||
|
</vn-button>
|
||||||
|
</vn-button-bar>
|
||||||
|
</vn-vertical>
|
||||||
|
|
||||||
|
<vn-item-descriptor-popover
|
||||||
|
vn-id="descriptor">
|
||||||
|
</vn-item-descriptor-popover>
|
|
@ -0,0 +1,95 @@
|
||||||
|
import ngModule from '../module';
|
||||||
|
import './style.scss';
|
||||||
|
|
||||||
|
class Controller {
|
||||||
|
constructor($scope, $state, $http, vnApp, $translate) {
|
||||||
|
this.$scope = $scope;
|
||||||
|
this.vnApp = vnApp;
|
||||||
|
this.$translate = $translate;
|
||||||
|
this.$state = $state;
|
||||||
|
this.$http = $http;
|
||||||
|
this.idsToRemove = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$onInit() {
|
||||||
|
this.getRows();
|
||||||
|
this.getVAT();
|
||||||
|
}
|
||||||
|
|
||||||
|
getRows() {
|
||||||
|
let filter = {
|
||||||
|
where: {orderFk: this.$state.params.id},
|
||||||
|
include: [{
|
||||||
|
relation: 'item',
|
||||||
|
scope: {
|
||||||
|
include: {
|
||||||
|
relation: 'tags',
|
||||||
|
scope: {
|
||||||
|
fields: ['tagFk', 'value'],
|
||||||
|
include: {
|
||||||
|
relation: 'tag',
|
||||||
|
scope: {
|
||||||
|
fields: ['name']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fields: ['itemFk', 'name', 'image']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{relation: 'warehouse'}]
|
||||||
|
};
|
||||||
|
filter = encodeURIComponent(JSON.stringify(filter));
|
||||||
|
let query = `/order/api/OrderRows?filter=${filter}`;
|
||||||
|
|
||||||
|
this.$http.get(query).then(res => {
|
||||||
|
this.rows = res.data;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getVAT() {
|
||||||
|
let query = `/order/api/Orders/${this.$state.params.id}/getTaxes`;
|
||||||
|
|
||||||
|
this.$http.get(query).then(res => {
|
||||||
|
this.VAT = res.data.tax;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
removeRow(index) {
|
||||||
|
let [lineRemoved] = this.rows.splice(index, 1);
|
||||||
|
this.idsToRemove.push(lineRemoved.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Item Descriptor
|
||||||
|
showDescriptor(event, itemFk) {
|
||||||
|
this.$scope.descriptor.itemFk = itemFk;
|
||||||
|
this.$scope.descriptor.parent = event.target;
|
||||||
|
this.$scope.descriptor.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
onDescriptorLoad() {
|
||||||
|
this.$scope.popover.relocate();
|
||||||
|
}
|
||||||
|
|
||||||
|
save() {
|
||||||
|
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!'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Controller.$inject = ['$scope', '$state', '$http', 'vnApp', '$translate'];
|
||||||
|
|
||||||
|
ngModule.component('vnOrderLine', {
|
||||||
|
template: require('./index.html'),
|
||||||
|
controller: Controller,
|
||||||
|
bindings: {
|
||||||
|
order: '<'
|
||||||
|
}
|
||||||
|
});
|
|
@ -0,0 +1,109 @@
|
||||||
|
import './index.js';
|
||||||
|
|
||||||
|
describe('Order', () => {
|
||||||
|
describe('Component vnOrderLine', () => {
|
||||||
|
let $componentController;
|
||||||
|
let $state;
|
||||||
|
let controller;
|
||||||
|
let $httpBackend;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
angular.mock.module('order');
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(angular.mock.inject((_$componentController_, _$state_, _$httpBackend_) => {
|
||||||
|
$componentController = _$componentController_;
|
||||||
|
$state = _$state_;
|
||||||
|
$state = {params: {id: 1}};
|
||||||
|
$httpBackend = _$httpBackend_;
|
||||||
|
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
|
||||||
|
controller = $componentController('vnOrderLine', {$state: $state});
|
||||||
|
controller.rows = [{id: 1}];
|
||||||
|
controller.$scope.popover = {relocate: () => {}};
|
||||||
|
controller.$scope.descriptor = {show: () => {}};
|
||||||
|
controller.vnApp = {showSuccess: () => {}};
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('getRows()', () => {
|
||||||
|
it('should make a query to get the rows of a given order', () => {
|
||||||
|
let filter = {
|
||||||
|
where: {orderFk: controller.$state.params.id},
|
||||||
|
include: [{
|
||||||
|
relation: 'item',
|
||||||
|
scope: {
|
||||||
|
include: {
|
||||||
|
relation: 'tags',
|
||||||
|
scope: {
|
||||||
|
fields: ['tagFk', 'value'],
|
||||||
|
include: {
|
||||||
|
relation: 'tag',
|
||||||
|
scope: {
|
||||||
|
fields: ['name']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fields: ['itemFk', 'name', 'image']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{relation: 'warehouse'}]
|
||||||
|
};
|
||||||
|
|
||||||
|
filter = encodeURIComponent(JSON.stringify(filter));
|
||||||
|
$httpBackend.expectGET(`/order/api/OrderRows?filter=${filter}`).respond({data: [{id: 1}]});
|
||||||
|
controller.getRows();
|
||||||
|
$httpBackend.flush();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getTaxes()', () => {
|
||||||
|
it('should make a query to get the taxes of a given order', () => {
|
||||||
|
$httpBackend.expectGET(`/order/api/Orders/1/getTaxes`).respond({data: {tax: 3}});
|
||||||
|
controller.getVAT();
|
||||||
|
$httpBackend.flush();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('removeRow()', () => {
|
||||||
|
it('should remove a row from rows and add his id to idsRemoved', () => {
|
||||||
|
controller.removeRow(0);
|
||||||
|
|
||||||
|
expect(controller.rows.length).toBe(0);
|
||||||
|
expect(controller.idsToRemove[0]).toBe(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('showDescriptor()', () => {
|
||||||
|
it('should set $scope.descriptor.itemFk, $scope.descriptor.parent and call $scope.descriptor.show()', () => {
|
||||||
|
let event = {target: 1};
|
||||||
|
let itemFk = 1;
|
||||||
|
spyOn(controller.$scope.descriptor, 'show');
|
||||||
|
controller.showDescriptor(event, itemFk);
|
||||||
|
|
||||||
|
expect(controller.$scope.descriptor.itemFk).toBe(1);
|
||||||
|
expect(controller.$scope.descriptor.parent).toBe(1);
|
||||||
|
expect(controller.$scope.descriptor.show).toHaveBeenCalledWith();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('onDescriptorLoad()', () => {
|
||||||
|
it('should call $scope.popover.relocate()', () => {
|
||||||
|
spyOn(controller.$scope.popover, 'relocate');
|
||||||
|
controller.onDescriptorLoad();
|
||||||
|
|
||||||
|
expect(controller.$scope.popover.relocate).toHaveBeenCalledWith();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('save()', () => {
|
||||||
|
it('should make a query to remove the selected rows and call vnApp.showSuccess', () => {
|
||||||
|
spyOn(controller.vnApp, 'showSuccess');
|
||||||
|
$httpBackend.expectPOST(`/order/api/OrderRows/removes`).respond();
|
||||||
|
controller.save();
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1 @@
|
||||||
|
Remove item: Eliminar articulo
|
|
@ -0,0 +1,8 @@
|
||||||
|
vn-order-line{
|
||||||
|
vn-table {
|
||||||
|
img {
|
||||||
|
border-radius: 50%;
|
||||||
|
max-width: 50px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -27,7 +27,7 @@ input[type=reset]::-moz-focus-inner
|
||||||
|
|
||||||
.totalBox {
|
.totalBox {
|
||||||
border: 1px solid #CCC;
|
border: 1px solid #CCC;
|
||||||
text-align: left;
|
text-align: right!important;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 18px;
|
padding: 18px;
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethod('getTaxes', {
|
||||||
|
description: 'Gets the taxes of a given order',
|
||||||
|
accessType: 'READ',
|
||||||
|
accepts: [{
|
||||||
|
arg: 'id',
|
||||||
|
type: 'number',
|
||||||
|
required: true,
|
||||||
|
description: 'order id',
|
||||||
|
http: {source: 'path'}
|
||||||
|
}],
|
||||||
|
returns: {
|
||||||
|
type: 'object',
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/:id/getTaxes`,
|
||||||
|
verb: 'GET'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.getTaxes = async orderFk => {
|
||||||
|
let query = `CALL hedera.orderGetTax(?);
|
||||||
|
SELECT * FROM tmp.orderTax;`;
|
||||||
|
let res = await Self.rawSql(query, [orderFk]);
|
||||||
|
let [taxes] = res[1];
|
||||||
|
|
||||||
|
return taxes;
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,21 @@
|
||||||
|
const app = require(`../../../../server/server`);
|
||||||
|
|
||||||
|
describe('order getTaxes()', () => {
|
||||||
|
it('should call the getTaxes method and return undefined if its called with a string', async() => {
|
||||||
|
let result = await app.models.Order.getTaxes('pepinillos');
|
||||||
|
|
||||||
|
expect(result).toEqual(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call the getTaxes method and return undefined if its called with unknown id', async() => {
|
||||||
|
let result = await app.models.Order.getTaxes(99999999999999999999999);
|
||||||
|
|
||||||
|
expect(result).toEqual(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
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.tax).toEqual(0.95);
|
||||||
|
});
|
||||||
|
});
|
|
@ -2,7 +2,7 @@ module.exports = Self => {
|
||||||
require('../methods/order/new')(Self);
|
require('../methods/order/new')(Self);
|
||||||
require('../methods/order/getTotalVolume')(Self);
|
require('../methods/order/getTotalVolume')(Self);
|
||||||
require('../methods/order/getVolumes')(Self);
|
require('../methods/order/getVolumes')(Self);
|
||||||
//require('../methods/order/getTaxes')(Self);
|
require('../methods/order/getTaxes')(Self);
|
||||||
require('../methods/order/isEditable')(Self);
|
require('../methods/order/isEditable')(Self);
|
||||||
require('../methods/order/getTotal')(Self);
|
require('../methods/order/getTotal')(Self);
|
||||||
require('../methods/order/itemFilter')(Self);
|
require('../methods/order/itemFilter')(Self);
|
||||||
|
|
Loading…
Reference in New Issue