This commit is contained in:
Juan 2018-07-09 18:07:02 +02:00
commit 303290af53
52 changed files with 607 additions and 157 deletions

View File

@ -6,7 +6,7 @@
vn-one vn-one
label="Credit" label="Credit"
model="$ctrl.creditClassification.credit", model="$ctrl.creditClassification.credit",
rule="CreditInsurance.credit" rule="creditInsurance.credit"
step="1" step="1"
vn-focus> vn-focus>
</vn-textfield> </vn-textfield>
@ -20,7 +20,7 @@
vn-one vn-one
label="Since" label="Since"
model="$ctrl.creditClassification.started" model="$ctrl.creditClassification.started"
ini-options="{dateFormat: 'd-m-Y'}"> ini-options="{enableTime: true, dateFormat: 'd-m-Y', time_24hr: true}">
</vn-date-picker> </vn-date-picker>
</vn-horizontal> </vn-horizontal>
</vn-card> </vn-card>

View File

@ -14,7 +14,7 @@ class Controller {
submit() { submit() {
if (this.$scope.form.$invalid) if (this.$scope.form.$invalid)
return this.vnApp.showMessage(this.$translate.instant('Some fields are invalid')); return this.vnApp.showError(this.$translate.instant('Some fields are invalid'));
let query = `/client/api/creditClassifications/createWithInsurance`; let query = `/client/api/creditClassifications/createWithInsurance`;
let data = this.creditClassification; let data = this.creditClassification;

View File

@ -20,7 +20,7 @@ describe('Client', () => {
describe('_getClassifications()', () => { describe('_getClassifications()', () => {
it('should perform a GET query to define the classifications property in the controller', () => { it('should perform a GET query to define the classifications property in the controller', () => {
let res = ['some classifications']; let res = ['some classifications'];
let query = '/client/api/CreditClassifications?filter=%7B%22order%22%3A%22finished%20ASC%2C%20started%20DESC%22%2C%22include%22%3A%5B%7B%22relation%22%3A%22creditInsurances%22%2C%22scope%22%3A%7B%22fields%22%3A%5B%22id%22%2C%22credit%22%2C%22created%22%2C%22grade%22%5D%2C%22order%22%3A%22created%20DESC%22%2C%22limit%22%3A2%7D%7D%5D%2C%22where%22%3A%7B%7D%7D'; let query = '/client/api/CreditClassifications?filter=%7B%22order%22%3A%22finished%20ASC%2C%20started%20DESC%22%2C%22include%22%3A%5B%7B%22relation%22%3A%22insurances%22%2C%22scope%22%3A%7B%22fields%22%3A%5B%22id%22%2C%22credit%22%2C%22created%22%2C%22grade%22%5D%2C%22order%22%3A%22created%20DESC%22%2C%22limit%22%3A2%7D%7D%5D%2C%22where%22%3A%7B%7D%7D';
$httpBackend.whenGET(query).respond(res); $httpBackend.whenGET(query).respond(res);
$httpBackend.expectGET(query); $httpBackend.expectGET(query);

View File

@ -15,7 +15,7 @@
<div><vn-label translate>To</vn-label> {{classification.finished | date:'dd/MM/yyyy'}}</div> <div><vn-label translate>To</vn-label> {{classification.finished | date:'dd/MM/yyyy'}}</div>
</vn-one> </vn-one>
<vn-vertical vn-one pad-medium-h> <vn-vertical vn-one pad-medium-h>
<vn-horizontal ng-repeat="insurance in classification.creditInsurances track by insurance.id"> <vn-horizontal ng-repeat="insurance in classification.insurances track by insurance.id">
<vn-one> <vn-one>
<vn-label-value label="Credit" <vn-label-value label="Credit"
value="{{::insurance.credit}}"> value="{{::insurance.credit}}">

View File

@ -17,7 +17,7 @@ class Controller {
order: 'finished ASC, started DESC', order: 'finished ASC, started DESC',
include: [ include: [
{ {
relation: 'creditInsurances', relation: 'insurances',
scope: { scope: {
fields: ['id', 'credit', 'created', 'grade'], fields: ['id', 'credit', 'created', 'grade'],
order: 'created DESC', order: 'created DESC',

View File

@ -1,4 +1,4 @@
<mg-ajax path="/client/api/CreditClassifications/{{post.params.classificationId}}/creditInsurances" options="vnPost"></mg-ajax> <mg-ajax path="/client/api/CreditClassifications/{{post.params.classificationId}}/insurances" options="vnPost"></mg-ajax>
<vn-watcher <vn-watcher
vn-id="watcher" vn-id="watcher"
data="$ctrl.insurance" data="$ctrl.insurance"
@ -22,7 +22,7 @@
<vn-date-picker vn-one <vn-date-picker vn-one
label="Date" label="Date"
model="$ctrl.insurance.created" model="$ctrl.insurance.created"
ini-options="{enableTime: true, dateFormat: 'd-m-Y h:i', time_24hr: true}"> ini-options="{enableTime: true, dateFormat: 'd-m-Y', time_24hr: true}">
</vn-date-picker> </vn-date-picker>
</vn-horizontal> </vn-horizontal>
<vn-horizontal> <vn-horizontal>

View File

@ -3,7 +3,7 @@ import ngModule from '../../../module';
class Controller { class Controller {
constructor($filter) { constructor($filter) {
this.insurance = { this.insurance = {
created: $filter('date')(new Date(), 'yyyy-MM-dd HH:mm') created: $filter('date')(new Date(), 'yyyy-MM-dd HH:mm:ss')
}; };
} }
} }

View File

@ -1,4 +1,4 @@
<mg-ajax path="/client/api/CreditClassifications/{{index.params.classificationId}}/creditInsurances" options="vnIndex"></mg-ajax> <mg-ajax path="/client/api/CreditClassifications/{{index.params.classificationId}}/insurances" options="vnIndex"></mg-ajax>
<vn-vertical> <vn-vertical>
<vn-card pad-large> <vn-card pad-large>
<vn-vertical> <vn-vertical>

View File

@ -199,9 +199,16 @@
<vn-label-value label="Credit" <vn-label-value label="Credit"
value="{{$ctrl.summary.credit | currency:'€ ':2}}"> value="{{$ctrl.summary.credit | currency:'€ ':2}}">
</vn-label-value> </vn-label-value>
<vn-label-value label="Secured credit" <vn-horizontal>
value="{{$ctrl.summary.creditInsurance | currency:'€ ':2}}"> <vn-one>
</vn-label-value> <vn-label-value label="Secured credit"
value="{{$ctrl.summary.creditInsurance | currency:'€ ':2}}">
</vn-label-value>
</vn-one>
<vn-one title="Grade">
{{$ctrl.grade ? '&nbsp;/ ' + $ctrl.grade : '&nbsp;/ - '}}
</vn-one>
</vn-horizontal>
</vn-one> </vn-one>
</vn-horizontal> </vn-horizontal>
</vn-vertical> </vn-vertical>

View File

@ -11,8 +11,12 @@ class Controller {
return; return;
this.$http.get(`/client/api/Clients/${this.client.id}/summary`).then(res => { this.$http.get(`/client/api/Clients/${this.client.id}/summary`).then(res => {
if (res && res.data) if (res && res.data) {
this.summary = res.data; this.summary = res.data;
if (res.data.classifications.length)
this.grade = res.data.classifications[0].insurances[0].grade;
}
}); });
} }
} }

View File

@ -75,15 +75,6 @@ export default class Popover extends Component {
this.document.addEventListener('keydown', this.docKeyDownHandler); this.document.addEventListener('keydown', this.docKeyDownHandler);
this.document.addEventListener('focusin', this.docFocusInHandler); this.document.addEventListener('focusin', this.docFocusInHandler);
let firstFocusable = this.element.querySelector('input, textarea');
if (firstFocusable) {
firstFocusable.addEventListener('focus', () => {
firstFocusable.select();
});
setTimeout(() => {
firstFocusable.focus();
}, 200);
}
this.deregisterCallback = this.$transitions.onStart({}, () => this.hide()); this.deregisterCallback = this.$transitions.onStart({}, () => this.hide());
this.relocate(); this.relocate();

View File

@ -88,7 +88,7 @@ describe('Item', () => {
describe('submit()', () => { describe('submit()', () => {
it("should return an error message 'The barcode must be unique' when the code isnt unique", () => { it("should return an error message 'The barcode must be unique' when the code isnt unique", () => {
spyOn(controller.vnApp, 'showMessage').and.callThrough(); spyOn(controller.vnApp, 'showError').and.callThrough();
controller.barcodes = [ controller.barcodes = [
{code: 123454, itemFk: 1, id: 1}, {code: 123454, itemFk: 1, id: 1},
{code: 123454, itemFk: 1} {code: 123454, itemFk: 1}
@ -96,7 +96,7 @@ describe('Item', () => {
controller.oldBarcodes = {1: {id: 1, code: 123454, itemFk: 1}}; controller.oldBarcodes = {1: {id: 1, code: 123454, itemFk: 1}};
controller.submit(); controller.submit();
expect(controller.vnApp.showMessage).toHaveBeenCalledWith('The barcode must be unique'); expect(controller.vnApp.showError).toHaveBeenCalledWith('The barcode must be unique');
}); });
it("should perfom a query to delete barcodes", () => { it("should perfom a query to delete barcodes", () => {
@ -131,7 +131,7 @@ describe('Item', () => {
}); });
it("should return a message 'No changes to save' when there are no changes to apply", () => { it("should return a message 'No changes to save' when there are no changes to apply", () => {
spyOn(controller.vnApp, 'showMessage').and.callThrough(); spyOn(controller.vnApp, 'showError').and.callThrough();
controller.oldBarcodes = [ controller.oldBarcodes = [
{code: 1, itemFk: 1, id: 1}, {code: 1, itemFk: 1, id: 1},
{code: 2, itemFk: 1, id: 2} {code: 2, itemFk: 1, id: 2}
@ -139,7 +139,7 @@ describe('Item', () => {
controller.barcodes = []; controller.barcodes = [];
controller.submit(); controller.submit();
expect(controller.vnApp.showMessage).toHaveBeenCalledWith('No changes to save'); expect(controller.vnApp.showError).toHaveBeenCalledWith('No changes to save');
}); });
}); });
}); });

View File

@ -86,7 +86,7 @@ export default class Controller {
} }
if (repeatedBarcodes) { if (repeatedBarcodes) {
return this.vnApp.showMessage(this.$translate.instant('The barcode must be unique')); return this.vnApp.showError(this.$translate.instant('The barcode must be unique'));
} }
canSubmit = barcodesObj.update.length > 0 || barcodesObj.create.length > 0 || barcodesObj.delete.length > 0; canSubmit = barcodesObj.update.length > 0 || barcodesObj.create.length > 0 || barcodesObj.delete.length > 0;
@ -98,7 +98,7 @@ export default class Controller {
this.$scope.watcher.notifySaved(); this.$scope.watcher.notifySaved();
}); });
} }
this.vnApp.showMessage(this.$translate.instant('No changes to save')); this.vnApp.showError(this.$translate.instant('No changes to save'));
} }
setOldBarcodes(response) { setOldBarcodes(response) {

View File

@ -24,10 +24,10 @@
<vn-thead> <vn-thead>
<vn-tr> <vn-tr>
<vn-th>Date</vn-th> <vn-th>Date</vn-th>
<vn-th number>State</vn-th> <vn-th number>Id</vn-th>
<vn-th number>Origin</vn-th> <vn-th>State</vn-th>
<vn-th number>Reference</vn-th> <vn-th>Reference</vn-th>
<vn-th field="name">Worker</vn-th> <vn-th>Worker</vn-th>
<vn-th number>In</vn-th> <vn-th number>In</vn-th>
<vn-th number>Out</vn-th> <vn-th number>Out</vn-th>
<vn-th number>Balance</vn-th> <vn-th number>Balance</vn-th>
@ -37,9 +37,9 @@
<vn-tr ng-class="{'warning': $ctrl.isToday(sale.date)}" <vn-tr ng-class="{'warning': $ctrl.isToday(sale.date)}"
ng-repeat="sale in sales" vn-repeat-last on-last="$ctrl.scrollToActive()"> ng-repeat="sale in sales" vn-repeat-last on-last="$ctrl.scrollToActive()">
<vn-td>{{::sale.date | date:'dd/MM/yyyy HH:mm' }}</vn-td> <vn-td>{{::sale.date | date:'dd/MM/yyyy HH:mm' }}</vn-td>
<vn-td number>{{::sale.alertLevel | dashIfEmpty}}</vn-td>
<vn-td number>{{::sale.origin | dashIfEmpty}}</vn-td> <vn-td number>{{::sale.origin | dashIfEmpty}}</vn-td>
<vn-td number>{{::sale.reference | dashIfEmpty}}</vn-td> <vn-td>{{::sale.stateName | dashIfEmpty}}</vn-td>
<vn-td>{{::sale.reference | dashIfEmpty}}</vn-td>
<vn-td>{{sale.name | dashIfEmpty}}</vn-td> <vn-td>{{sale.name | dashIfEmpty}}</vn-td>
<vn-td number>{{::sale.in | dashIfEmpty}}</vn-td> <vn-td number>{{::sale.in | dashIfEmpty}}</vn-td>
<vn-td number>{{::sale.out | dashIfEmpty}}</vn-td> <vn-td number>{{::sale.out | dashIfEmpty}}</vn-td>

View File

@ -122,11 +122,11 @@ export default class Controller {
}); });
if (this.$scope.form.$invalid) { if (this.$scope.form.$invalid) {
return this.vnApp.showMessage(this.$translate.instant('Some fields are invalid')); return this.vnApp.showError(this.$translate.instant('Some fields are invalid'));
} }
if (repeatedWarehouse) { if (repeatedWarehouse) {
return this.vnApp.showMessage(this.$translate.instant('The niche must be unique')); return this.vnApp.showError(this.$translate.instant('The niche must be unique'));
} }
canSubmit = nichesObj.update.length > 0 || nichesObj.create.length > 0 || nichesObj.delete.length > 0; canSubmit = nichesObj.update.length > 0 || nichesObj.create.length > 0 || nichesObj.delete.length > 0;
@ -138,7 +138,7 @@ export default class Controller {
this.$scope.watcher.notifySaved(); this.$scope.watcher.notifySaved();
}); });
} }
this.vnApp.showMessage(this.$translate.instant('No changes to save')); this.vnApp.showError(this.$translate.instant('No changes to save'));
} }
} }

View File

@ -98,7 +98,7 @@ describe('Item', () => {
describe('submit()', () => { describe('submit()', () => {
it("should return an error message 'The niche must be unique' when the niche warehouse isnt unique", () => { it("should return an error message 'The niche must be unique' when the niche warehouse isnt unique", () => {
controller.$scope.form = {}; controller.$scope.form = {};
spyOn(controller.vnApp, 'showMessage').and.callThrough(); spyOn(controller.vnApp, 'showError').and.callThrough();
controller.niches = [ controller.niches = [
{warehouseFk: 1, code: 123454, itemFk: 1, id: 1}, {warehouseFk: 1, code: 123454, itemFk: 1, id: 1},
{warehouseFk: 1, code: 123454, itemFk: 1} {warehouseFk: 1, code: 123454, itemFk: 1}
@ -106,7 +106,7 @@ describe('Item', () => {
controller.oldNiches = {1: {warehouseFk: 1, id: 1, code: 123454, itemFk: 1}}; controller.oldNiches = {1: {warehouseFk: 1, id: 1, code: 123454, itemFk: 1}};
controller.submit(); controller.submit();
expect(controller.vnApp.showMessage).toHaveBeenCalledWith('The niche must be unique'); expect(controller.vnApp.showError).toHaveBeenCalledWith('The niche must be unique');
}); });
it("should perfom a query to delete niches", () => { it("should perfom a query to delete niches", () => {
@ -144,7 +144,7 @@ describe('Item', () => {
it("should return a message 'No changes to save' when there are no changes to apply", () => { it("should return a message 'No changes to save' when there are no changes to apply", () => {
controller.$scope.form = {$setPristine: () => {}}; controller.$scope.form = {$setPristine: () => {}};
spyOn(controller.vnApp, 'showMessage').and.callThrough(); spyOn(controller.vnApp, 'showError').and.callThrough();
controller.oldNiches = [ controller.oldNiches = [
{warehouseFk: 1, code: 1, itemFk: 1, id: 1}, {warehouseFk: 1, code: 1, itemFk: 1, id: 1},
{warehouseFk: 2, code: 2, itemFk: 1, id: 2} {warehouseFk: 2, code: 2, itemFk: 1, id: 2}
@ -152,7 +152,7 @@ describe('Item', () => {
controller.niches = []; controller.niches = [];
controller.submit(); controller.submit();
expect(controller.vnApp.showMessage).toHaveBeenCalledWith('No changes to save'); expect(controller.vnApp.showError).toHaveBeenCalledWith('No changes to save');
}); });
}); });
}); });

View File

@ -132,7 +132,7 @@ describe('Item', () => {
// TODO: Server validation should be implemented // TODO: Server validation should be implemented
xit("should return an error message 'The tag must be unique' when the tag value isnt unique", () => { xit("should return an error message 'The tag must be unique' when the tag value isnt unique", () => {
controller.$.form = []; controller.$.form = [];
spyOn(controller.vnApp, 'showMessage').and.callThrough(); spyOn(controller.vnApp, 'showError').and.callThrough();
controller.tags = [ controller.tags = [
{typeFk: 1, value: 123454, itemFk: 1, id: 1}, {typeFk: 1, value: 123454, itemFk: 1, id: 1},
{typeFk: 1, value: 123454, itemFk: 1} {typeFk: 1, value: 123454, itemFk: 1}
@ -140,7 +140,7 @@ describe('Item', () => {
controller.orgTags = {1: {typeFk: 1, id: 1, value: 123454, itemFk: 1}}; controller.orgTags = {1: {typeFk: 1, id: 1, value: 123454, itemFk: 1}};
controller.submit(); controller.submit();
expect(controller.vnApp.showMessage).toHaveBeenCalledWith('The tag must be unique'); expect(controller.vnApp.showError).toHaveBeenCalledWith('The tag must be unique');
}); });
it("should perfom a query to delete tags", () => { it("should perfom a query to delete tags", () => {

View File

@ -29,7 +29,7 @@ export default class Controller {
let url = `/item/api/Items/${this.$stateParams.id}/updateTaxes`; let url = `/item/api/Items/${this.$stateParams.id}/updateTaxes`;
this.$http.post(url, data).then( this.$http.post(url, data).then(
() => this.vnApp.showMessage(this._.instant('Data saved!')) () => this.vnApp.showSuccess(this._.instant('Data saved!'))
); );
} }
} }

View File

@ -0,0 +1,34 @@
<vn-title>New order</vn-title>
<vn-autocomplete
vn-focus
vn-id="client"
url="/api/Clients"
label="Client"
show-field="name"
value-field="id"
field="$ctrl.clientFk">
<tpl-item>{{id}}: {{name}}</tpl-item>
</vn-autocomplete>
<vn-autocomplete
disabled="!$ctrl.clientFk"
url="{{ $ctrl.clientFk ? '/api/Clients/'+ $ctrl.clientFk +'/addresses' : null }}"
select-fields=["nickname","street","city"]
field="$ctrl.addressFk"
show-field="nickname"
value-field="id"
label="Address">
<tpl-item>{{nickname}}: {{street}}, {{city}}</tpl-item>
</vn-autocomplete>
<vn-date-picker
label="Landed"
model="$ctrl.landed"
ini-options="{enableTime: false}">
</vn-date-picker>
<vn-autocomplete
disabled="!$ctrl.clientFk || !$ctrl.landed"
data="$ctrl._avaibleAgencies"
label="Agency"
show-field="agency"
value-field="id"
field="$ctrl.ticket.agencyModeFk">
</vn-autocomplete>

View File

@ -0,0 +1,93 @@
import ngModule from '../module';
class Controller {
constructor($scope, $http, vnApp, $translate) {
this.$scope = $scope;
this.$http = $http;
this.translate = $translate;
this.vnApp = vnApp;
this.ticket = {};
}
set ticket(value) {
if (value) {
this._ticket = value;
}
}
get ticket() {
return this._ticket;
}
set clientFk(value) {
this.ticket.clientFk = value;
this.addressFk = null;
}
get clientFk() {
return this.ticket.clientFk;
}
set addressFk(value) {
this.ticket.addressFk = value;
this.getAvaibleAgencies();
}
get addressFk() {
return this.ticket.addressFk;
}
set landed(value) {
this.ticket.landed = value;
this.getAvaibleAgencies();
}
get landed() {
return this.ticket.landed;
}
get warehouseFk() {
return this.ticket.warehouseFk;
}
getAvaibleAgencies() {
this.ticket.agencyModeFk = null;
if (this.ticket.landed && this.ticket.addressFk) {
let filter = {addressFk: this.ticket.addressFk, landed: this.ticket.landed};
filter = encodeURIComponent(JSON.stringify(filter));
let query = `/api/Agencies/landsThatDay?filter=${filter}`;
this.$http.get(query).then(res => {
this._avaibleAgencies = res.data[0];
});
}
}
onSubmit() {
this.createOrder();
}
createOrder() {
let params = {
landed: this.ticket.landed,
addressFk: this.ticket.addressFk,
agencyModeFk: this.ticket.agencyModeFk
};
this.$http.post(`order/api/Orders/new`, params).then(res => {
this.vnApp.showSuccess(this.translate.instant('Data saved!'));
return res.data.id;
}).catch(e => {
this.vnApp.showError(this.translate.instant(e.data.error.message));
});
}
}
Controller.$inject = ['$scope', '$http', 'vnApp', '$translate'];
ngModule.component('vnTicketCreateCard', {
template: require('./card.html'),
controller: Controller,
bindings: {
ticket: '<?'
}
});

View File

@ -1,6 +1,6 @@
//import './card.js'; import './card.js';
xdescribe('Ticket', () => { describe('Ticket', () => {
describe('Component vnTicketCreateCard', () => { describe('Component vnTicketCreateCard', () => {
let $componentController; let $componentController;
let $scope; let $scope;
@ -19,7 +19,7 @@ xdescribe('Ticket', () => {
controller.item = {id: 3}; controller.item = {id: 3};
})); }));
describe('set clientFk()', () => { describe('set clientFk', () => {
it(`should set addressFk to null and clientFk to a value`, () => { it(`should set addressFk to null and clientFk to a value`, () => {
controller.clientFk = 2; controller.clientFk = 2;
@ -28,7 +28,7 @@ xdescribe('Ticket', () => {
}); });
}); });
describe('set addressFk()', () => { describe('set addressFk', () => {
it(`should set agencyModeFk property to null and addressFk to a value`, () => { it(`should set agencyModeFk property to null and addressFk to a value`, () => {
controller.addressFk = 101; controller.addressFk = 101;
@ -37,25 +37,39 @@ xdescribe('Ticket', () => {
}); });
}); });
describe('set onSubmit()', () => { describe('getAvaibleAgencies()', () => {
it(`should call createTicket()`, () => { it(`should make a query if landed and addressFk exists`, () => {
spyOn(controller, 'createTicket'); controller.ticket.addressFk = 101;
controller.onSubmit(); controller.ticket.landed = 101;
expect(controller.createTicket).toHaveBeenCalledWith(); let filter = {addressFk: controller.ticket.addressFk, landed: controller.ticket.landed};
filter = encodeURIComponent(JSON.stringify(filter));
$httpBackend.whenGET(`/api/Agencies/landsThatDay?filter=${filter}`).respond({data: 1});
$httpBackend.expectGET(`/api/Agencies/landsThatDay?filter=${filter}`);
controller.getAvaibleAgencies();
$httpBackend.flush();
}); });
}); });
describe('createTicket()', () => { describe('onSubmit()', () => {
it(`should call createOrder()`, () => {
spyOn(controller, 'createOrder');
controller.onSubmit();
expect(controller.createOrder).toHaveBeenCalledWith();
});
});
describe('createOrder()', () => {
it(`should make a query`, () => { it(`should make a query`, () => {
controller.ticket.clientFk = 101;
controller.ticket.addressFk = 101; controller.ticket.addressFk = 101;
controller.ticket.agencyModeFk = 101; controller.ticket.agencyModeFk = 101;
controller.ticket.shipped = 101; controller.ticket.landed = 101;
$httpBackend.whenPOST('order/api/Orders/new').respond({data: 'item'}); $httpBackend.whenPOST('order/api/Orders/new').respond({data: 1});
$httpBackend.expectPOST('order/api/Orders/new'); $httpBackend.expectPOST('order/api/Orders/new');
controller.createTicket(); controller.createOrder();
$httpBackend.flush(); $httpBackend.flush();
}); });
}); });

View File

@ -1,18 +1,11 @@
<mg-ajax path="/item/api/Tickets" options="vnPost"></mg-ajax> <div margin-medium>
<vn-watcher <div style="max-width: 70em; margin: 0 auto;" >
vn-id="watcher"
data="$ctrl.ticket"
form="form"
save="post">
</vn-watcher>
<form name="form" ng-submit="$ctrl.onSubmit()" margin-medium>
<div style="max-width: 70em; margin: 0 auto;">
<vn-card pad-large> <vn-card pad-large>
<vn-title>New ticket</vn-title> <vn-ticket-create-card vn-id="card" on-save=""></vn-ticket-create-card>
</vn-card> </vn-card>
<vn-button-bar> <vn-button-bar>
<vn-submit label="Create"></vn-submit> <vn-submit ng-click="$ctrl.onSubmit()" label="Save">
</vn-submit>
</vn-button-bar> </vn-button-bar>
</div> </div>
</form> </div>

View File

@ -1,20 +1,18 @@
import ngModule from '../module'; import ngModule from '../module';
class Controller { class Controller {
constructor($scope, $state) { constructor($scope, $http, $state) {
this.$ = $scope; this.$ = $scope;
this.$http = $http;
this.$state = $state; this.$state = $state;
this.Ticket = {};
} }
onSubmit() { async onSubmit() {
this.$.watcher.submit().then( let newOrderID = await this.$.card.createOrder();
json => this.$state.go('ticket.card.data', {id: json.data.id}) this.$state.go("ticket.card.summary", {id: newOrderID});
);
} }
} }
Controller.$inject = ['$scope', '$http', '$state'];
Controller.$inject = ['$scope', '$state'];
ngModule.component('vnTicketCreate', { ngModule.component('vnTicketCreate', {
template: require('./index.html'), template: require('./index.html'),

View File

@ -15,18 +15,17 @@ describe('Ticket', () => {
$componentController = _$componentController_; $componentController = _$componentController_;
$scope = $rootScope.$new(); $scope = $rootScope.$new();
$scope.card = {createTicket: () => {}}; $scope.card = {createOrder: () => {}};
$state = _$state_; $state = _$state_;
$state.go = () => {};
controller = $componentController('vnTicketCreate', {$scope: $scope, $state: $state}); controller = $componentController('vnTicketCreate', {$scope: $scope, $state: $state});
})); }));
describe('onSubmit()', () => { describe('onSubmit()', () => {
it(`should call createTicket()`, () => { it(`should call createOrder()`, () => {
spyOn(controller.$.card, 'createTicket'); spyOn(controller.$.card, 'createOrder');
controller.onSubmit(); controller.onSubmit();
expect(controller.$.card.createTicket).toHaveBeenCalledWith(); expect(controller.$.card.createOrder).toHaveBeenCalledWith();
}); });
xit(`should call go()`, () => { xit(`should call go()`, () => {

View File

@ -0,0 +1,6 @@
You can't create an order for a frozen client: No puedes crear una orden a un cliente congelado
You can't create an order for a inactive client: No puedes crear una orden a un cliente inactivo
You can't create an order for a client that doesn't has tax data verified:
No puedes crear una orden a un cliente cuyos datos fiscales no han sido verificados
You can't create an order for a client that has a debt: No puedes crear una orden a un cliente que tiene deuda
New order: Nueva orden

View File

@ -1,5 +1,4 @@
import ngModule from '../../module'; import ngModule from '../../module';
import {toJsonDate} from 'core/src/lib/date';
class Controller { class Controller {
constructor($scope, $http, $translate, vnApp) { constructor($scope, $http, $translate, vnApp) {
@ -36,7 +35,7 @@ class Controller {
let query = `/ticket/api/sales/${this.ticket.id}/priceDifference`; let query = `/ticket/api/sales/${this.ticket.id}/priceDifference`;
let data = { let data = {
landed: toJsonDate(this.ticket.landed), landed: this.ticket.landed,
addressFk: this.ticket.addressFk, addressFk: this.ticket.addressFk,
agencyModeFk: this.ticket.agencyModeFk, agencyModeFk: this.ticket.agencyModeFk,
warehouseFk: this.ticket.warehouseFk warehouseFk: this.ticket.warehouseFk

View File

@ -1,6 +1,6 @@
<vn-horizontal> <vn-horizontal>
<vn-one>{{::$ctrl.sale.concept}}</vn-one> <vn-one>{{::$ctrl.sale.concept}}</vn-one>
<vn-two class="ellipsize"> <vn-two>
<section <section
class="inline-tag ellipsize" ng-class="{'empty': !fetchedTag.value}" class="inline-tag ellipsize" ng-class="{'empty': !fetchedTag.value}"
ng-repeat="fetchedTag in $ctrl.sale.item.tags track by $index" ng-repeat="fetchedTag in $ctrl.sale.item.tags track by $index"

View File

@ -1,23 +1,41 @@
@import "colors"; @import "colors";
vn-fetched-tags { vn-fetched-tags {
@media screen and (max-width: 1700px){ @media screen and (max-width: 1600px){
& vn-horizontal { & vn-horizontal {
flex-direction: column; flex-direction: column;
text-align: center; text-align: center;
& vn-two { & vn-two {
text-align: center; text-align: center;
max-width: 10.5em;
margin: 0 auto margin: 0 auto
} }
.inline-tag {
font-size: 0.7em;
padding: 0.3em
}
} }
} }
@media screen and (max-width: 1200px){
& vn-horizontal {
.inline-tag {
font-size: 0.6em;
padding: 0.2em
}
}
}
& vn-one { & vn-one {
padding-top: 6px padding-top: 6px
} }
& vn-two {
white-space: nowrap
}
& .inline-tag { & .inline-tag {
background-color: $secondary-font-color; background-color: $secondary-font-color;
display: inline-block; display: inline-block;

View File

@ -41,7 +41,7 @@
<th number>{{::ticket.id}}</th> <th number>{{::ticket.id}}</th>
<td>{{::ticket.client.salesPerson.name | dashIfEmpty}}</td> <td>{{::ticket.client.salesPerson.name | dashIfEmpty}}</td>
<td>{{::ticket.shipped | date:'dd/MM/yyyy'}}</td> <td>{{::ticket.shipped | date:'dd/MM/yyyy'}}</td>
<td>{{::ticket.shipped | date:'HH:MM'}}</td> <td>{{::ticket.shipped | date:'HH:mm'}}</td>
<td>{{::ticket.nickname}}</td> <td>{{::ticket.nickname}}</td>
<td>{{::ticket.address.province.name}}</td> <td>{{::ticket.address.province.name}}</td>
<td>{{::ticket.tracking.state.name}}</td> <td>{{::ticket.tracking.state.name}}</td>

View File

@ -106,11 +106,11 @@ class Controller {
}); });
if (this.$scope.form.$invalid) { if (this.$scope.form.$invalid) {
return this.vnApp.showMessage(this.$translate.instant('Some fields are invalid')); return this.vnApp.showError(this.$translate.instant('Some fields are invalid'));
} }
if (repeatedType) { if (repeatedType) {
return this.vnApp.showMessage(this.$translate.instant('The observation type must be unique')); return this.vnApp.showError(this.$translate.instant('The observation type must be unique'));
} }
canSubmit = observationsObj.update.length > 0 || observationsObj.create.length > 0 || observationsObj.delete.length > 0; canSubmit = observationsObj.update.length > 0 || observationsObj.create.length > 0 || observationsObj.delete.length > 0;
@ -122,7 +122,7 @@ class Controller {
this.$scope.watcher.notifySaved(); this.$scope.watcher.notifySaved();
}); });
} }
this.vnApp.showMessage(this.$translate.instant('No changes to save')); this.vnApp.showError(this.$translate.instant('No changes to save'));
} }
$onInit() { $onInit() {

View File

@ -90,7 +90,7 @@ describe('ticket', () => {
it("should return an error message 'Some fields are invalid'", () => { it("should return an error message 'Some fields are invalid'", () => {
controller.$scope.form = {}; controller.$scope.form = {};
controller.$scope.form.$invalid = true; controller.$scope.form.$invalid = true;
spyOn(controller.vnApp, 'showMessage').and.callThrough(); spyOn(controller.vnApp, 'showError').and.callThrough();
controller.ticketObservations = [ controller.ticketObservations = [
{id: 1, observationTypeFk: 1, description: 'one', itemFk: 1}, {id: 1, observationTypeFk: 1, description: 'one', itemFk: 1},
{observationTypeFk: 1, description: 'one', itemFk: 1} {observationTypeFk: 1, description: 'one', itemFk: 1}
@ -98,12 +98,12 @@ describe('ticket', () => {
controller.oldObservations = {1: {id: 1, observationTypeFk: 1, description: 'one', itemFk: 1}}; controller.oldObservations = {1: {id: 1, observationTypeFk: 1, description: 'one', itemFk: 1}};
controller.submit(); controller.submit();
expect(controller.vnApp.showMessage).toHaveBeenCalledWith('Some fields are invalid'); expect(controller.vnApp.showError).toHaveBeenCalledWith('Some fields are invalid');
}); });
it("should return an error message 'The observation type must be unique'", () => { it("should return an error message 'The observation type must be unique'", () => {
controller.$scope.form = {}; controller.$scope.form = {};
spyOn(controller.vnApp, 'showMessage').and.callThrough(); spyOn(controller.vnApp, 'showError').and.callThrough();
controller.ticketObservations = [ controller.ticketObservations = [
{id: 1, observationTypeFk: 1, description: 'one', itemFk: 1}, {id: 1, observationTypeFk: 1, description: 'one', itemFk: 1},
{observationTypeFk: 1, description: 'one', itemFk: 1} {observationTypeFk: 1, description: 'one', itemFk: 1}
@ -111,7 +111,7 @@ describe('ticket', () => {
controller.oldObservations = {1: {id: 1, observationTypeFk: 1, description: 'one', itemFk: 1}}; controller.oldObservations = {1: {id: 1, observationTypeFk: 1, description: 'one', itemFk: 1}};
controller.submit(); controller.submit();
expect(controller.vnApp.showMessage).toHaveBeenCalledWith('The observation type must be unique'); expect(controller.vnApp.showError).toHaveBeenCalledWith('The observation type must be unique');
}); });
it("should perfom a query to delete observations", () => { it("should perfom a query to delete observations", () => {
@ -149,7 +149,7 @@ describe('ticket', () => {
it("should return a message 'No changes to save' when there are no changes to apply", () => { it("should return a message 'No changes to save' when there are no changes to apply", () => {
controller.$scope.form = {$setPristine: () => {}}; controller.$scope.form = {$setPristine: () => {}};
spyOn(controller.vnApp, 'showMessage').and.callThrough(); spyOn(controller.vnApp, 'showError').and.callThrough();
controller.oldObservations = [ controller.oldObservations = [
{id: 1, observationTypeFk: 1, description: 'one', showAddIcon: false}, {id: 1, observationTypeFk: 1, description: 'one', showAddIcon: false},
{id: 2, observationTypeFk: 2, description: 'two', showAddIcon: true} {id: 2, observationTypeFk: 2, description: 'two', showAddIcon: true}
@ -157,7 +157,7 @@ describe('ticket', () => {
controller.ticketObservations = []; controller.ticketObservations = [];
controller.submit(); controller.submit();
expect(controller.vnApp.showMessage).toHaveBeenCalledWith('No changes to save'); expect(controller.vnApp.showError).toHaveBeenCalledWith('No changes to save');
}); });
}); });
}); });

View File

@ -26,10 +26,10 @@ class Controller {
}); });
if (this.$.form.$invalid) if (this.$.form.$invalid)
return this.vnApp.showMessage(this.$translate.instant('Some fields are invalid')); return this.vnApp.showError(this.$translate.instant('Some fields are invalid'));
if (!this.hasChanges(packagesObj)) if (!this.hasChanges(packagesObj))
return this.vnApp.showMessage(this.$translate.instant('No changes to save')); return this.vnApp.showError(this.$translate.instant('No changes to save'));
this.$http.post(query, packagesObj).then(res => { this.$http.post(query, packagesObj).then(res => {
this.$.index.accept(); this.$.index.accept();

View File

@ -107,7 +107,7 @@
</td> </td>
<td number>{{(sale.quantity * sale.price) - ((sale.discount * (sale.quantity * sale.price))/100) | currency:' €':2}}</td> <td number>{{(sale.quantity * sale.price) - ((sale.discount * (sale.quantity * sale.price))/100) | currency:' €':2}}</td>
</tr> </tr>
<tr ng-if="index.model.count === 0" class="list list-element"> <tr ng-if="$ctrl.sales.length === 0 || !$ctrl.sales" class="list list-element">
<td colspan="8" style="text-align: center" translate>No results</td> <td colspan="8" style="text-align: center" translate>No results</td>
</tr> </tr>
<tfoot> <tfoot>
@ -197,7 +197,7 @@
</vn-textfield> </vn-textfield>
<div class="simulator"> <div class="simulator">
<p class="simulatorTitle" translate>New price</p> <p class="simulatorTitle" translate>New price</p>
<p>{{($ctrl.sale.quantity * $ctrl.sale.price) <p>{{($ctrl.sale.quantity * $ctrl.editedPrice)
- (($ctrl.sale.discount * ($ctrl.sale.quantity * $ctrl.editedPrice))/100) - (($ctrl.sale.discount * ($ctrl.sale.quantity * $ctrl.editedPrice))/100)
| currency:' €':2}}</p> | currency:' €':2}}</p>
<vn-button <vn-button
@ -273,11 +273,18 @@
ng-click="$ctrl.moveLines($ctrl.moveToTicketFk)"> ng-click="$ctrl.moveLines($ctrl.moveToTicketFk)">
</vn-icon-button> </vn-icon-button>
</vn-horizontal> </vn-horizontal>
<vn-button <vn-horizontal>
pointer <vn-button
label="New ticket" pointer
ng-click="$ctrl.linesToNewTicket()"> label="New ticket"
</vn-button> ng-click="$ctrl.linesToNewTicket()">
</vn-button>
<vn-icon
medium-grey
vn-tooltip="You have to allow pop-ups in your web browser to use this functionality"
icon="info">
</vn-icon>
</vn-horizontal>
</div> </div>
</vn-popover> </vn-popover>
</vn-vertical> </vn-vertical>

View File

@ -51,10 +51,8 @@ class Controller {
getVAT() { getVAT() {
this.$http.get(`/ticket/api/Tickets/${this.ticket.id}/getVAT`).then(res => { this.$http.get(`/ticket/api/Tickets/${this.ticket.id}/getVAT`).then(res => {
if (res.data) { this.VAT = res.data || 0;
this.VAT = res.data; this.total = this.subTotal + this.VAT;
this.total = this.subTotal + this.VAT;
}
}); });
} }
@ -117,6 +115,7 @@ class Controller {
let params = {ticketFk: this.$state.params.id, weekDay: day}; let params = {ticketFk: this.$state.params.id, weekDay: day};
this.$http.patch(`/ticket/api/TicketWeeklies`, params).then(() => { this.$http.patch(`/ticket/api/TicketWeeklies`, params).then(() => {
this.$.addTurn.hide(); this.$.addTurn.hide();
this.vnApp.showSuccess(this.translate.instant('Data saved!'));
}); });
} }
@ -204,6 +203,19 @@ class Controller {
this.$state.go("ticket.card.sale", {id: ticketID}); this.$state.go("ticket.card.sale", {id: ticketID});
} }
// Focus First Input
focusFirstInput(e) {
let firstFocusable = e.querySelector('input, textarea');
if (firstFocusable) {
firstFocusable.addEventListener('focus', () => {
firstFocusable.select();
});
setTimeout(() => {
firstFocusable.focus();
}, 200);
}
}
// Slesperson Mana // Slesperson Mana
getManaSalespersonMana() { getManaSalespersonMana() {
this.$http.get(`/api/Tickets/${this.$state.params.id}/getSalesPersonMana`).then(res => { this.$http.get(`/api/Tickets/${this.$state.params.id}/getSalesPersonMana`).then(res => {
@ -232,6 +244,7 @@ class Controller {
}; };
this.$.editPricePopover.parent = event.target; this.$.editPricePopover.parent = event.target;
this.$.editPricePopover.show(); this.$.editPricePopover.show();
this.focusFirstInput(this.$.editPricePopover.$element[0]);
} }
updatePrice() { updatePrice() {
@ -255,11 +268,13 @@ class Controller {
}]; }];
this.$.editPopover.parent = event.target; this.$.editPopover.parent = event.target;
this.$.editPopover.show(); this.$.editPopover.show();
this.focusFirstInput(this.$.editPopover.$element[0]);
} }
async showEditDialog() { showEditDialog() {
this.edit = this.getCheckedLines(); this.edit = this.getCheckedLines();
this.$.editDialog.show(); this.$.editDialog.show();
this.focusFirstInput(this.$.editDialog.$element[0]);
} }
hideEditDialog() { hideEditDialog() {
@ -281,27 +296,6 @@ class Controller {
}); });
} }
/* updateLine() {
if (this.edit.quantity != this.sale.quantity) {
this.$http.post(`/ticket/api/Sales/updateQuantity`, {id: this.edit.id, quantity: this.edit.quantity}).then(() => {
this.sale.quantity = this.edit.quantity;
});
}
if (this.edit.price != this.sale.price) {
this.$http.post(`/ticket/api/Sales/updatePrice`, {id: this.edit.id, price: this.edit.price}).then(() => {
this.sale.price = this.edit.price;
});
}
if (this.edit.discount != this.sale.discount) {
this.$http.post(`/ticket/api/Sales/updateDiscount`, {id: this.edit.id, discount: this.edit.discount}).then(() => {
this.sale.discount = this.edit.discount;
});
}
this.$.edit.hide();
}*/
/** /**
* Unmark sale as reserved * Unmark sale as reserved
*/ */

View File

@ -11,4 +11,6 @@ New ticket: Nuevo ticket
Edit price: Editar precio Edit price: Editar precio
You are going to delete lines of the ticket: Vas a borrar lineas del ticket You are going to delete lines of the ticket: Vas a borrar lineas del ticket
Continue anyway?: ¿Estás seguro? Continue anyway?: ¿Estás seguro?
The new quantity should be smaller than the old one: La nueva cantidad debe de ser menor que la anterior The new quantity should be smaller than the old one: La nueva cantidad debe de ser menor que la anterior
You have to allow pop-ups in your web browser to use this functionality:
Debes permitir los pop-pups en tu navegador para que esta herramienta funcione correctamente

View File

@ -52,13 +52,13 @@ vn-ticket-sale {
} }
vn-popover.transfer{ vn-popover.transfer{
& table { table {
min-width: 650px; min-width: 650px;
margin-bottom: 10px; margin-bottom: 10px;
} }
& i { vn-icon:nth-child(1) {
padding-top: 0.2em; padding-top: 0.2em;
font-size: 1.8em; font-size: 1.7em;
} }
} }

View File

@ -83,6 +83,9 @@
<td number>{{::sale.discount}} %</td> <td number>{{::sale.discount}} %</td>
<td number>{{::sale.quantity * sale.price | currency:'€':2}}</td> <td number>{{::sale.quantity * sale.price | currency:'€':2}}</td>
</tr> </tr>
<tr ng-if="!$ctrl.summary.sales" class="list list-element">
<td colspan="8" style="text-align: center" translate>No results</td>
</tr>
</tbody> </tbody>
</table> </table>
</vn-horizontal> </vn-horizontal>

View File

@ -3,6 +3,7 @@ export * from './module';
import './search-panel'; import './search-panel';
import './index'; import './index';
import './create'; import './create';
import './create/card';
import './card'; import './card';
import './descriptor'; import './descriptor';
import './summary'; import './summary';

View File

@ -64,11 +64,10 @@ describe('Ticket', () => {
.wait(selectors.ticketSales.secondSaleText) .wait(selectors.ticketSales.secondSaleText)
.getInnerText(selectors.ticketSales.secondSaleText) .getInnerText(selectors.ticketSales.secondSaleText)
.then(value => { .then(value => {
expect(value).toContain('Yellow'); expect(value).toContain('Red');
expect(value).toContain('2'); expect(value).toContain('€4.50');
expect(value).toContain('€23.50');
expect(value).toContain('0 %'); expect(value).toContain('0 %');
expect(value).toContain('€47.00'); expect(value).toContain('€45.00');
}); });
}); });
}); });

View File

@ -33,7 +33,7 @@
"model": "Client", "model": "Client",
"foreignKey": "client" "foreignKey": "client"
}, },
"creditInsurances": { "insurances": {
"type": "hasMany", "type": "hasMany",
"model": "CreditInsurance", "model": "CreditInsurance",
"foreignKey": "creditClassification" "foreignKey": "creditClassification"

View File

@ -0,0 +1,18 @@
USE `vn`;
CREATE TABLE `vn`.`alertLevel` (
`code` VARCHAR(45) CHARACTER SET 'utf8' NOT NULL,
`alertLevel` INT(11) NOT NULL,
PRIMARY KEY (`code`));
ALTER TABLE `vn`.`alertLevel`
ADD CONSTRAINT `fk_code_1`
FOREIGN KEY (`code`)
REFERENCES `vn2008`.`state` (`code`)
ON DELETE CASCADE
ON UPDATE CASCADE;
INSERT INTO `vn`.`alertLevel` (`code`, `alertLevel`) VALUES ('FREE', '0');
INSERT INTO `vn`.`alertLevel` (`code`, `alertLevel`) VALUES ('ON_PREPARATION', '1');
INSERT INTO `vn`.`alertLevel` (`code`, `alertLevel`) VALUES ('PACKED', '2');
INSERT INTO `vn`.`alertLevel` (`code`, `alertLevel`) VALUES ('DELIVERED', '3');

View File

@ -0,0 +1,105 @@
USE `vn`;
DROP procedure IF EXISTS `itemDiary`;
DELIMITER $$
USE `vn`$$
CREATE DEFINER=`root`@`%` PROCEDURE `itemDiary`(IN vItemId INT, IN vWarehouse INT)
BEGIN
DECLARE vDateInventory DATETIME;
DECLARE vCurdate DATE DEFAULT CURDATE();
-- traduccion: date, alertLevel, origin, reference, name, In, Out, Balance
SELECT Fechainventario INTO vDateInventory FROM vn2008.tblContadores;
SET @a = 0;
SELECT DATE(date) AS date,
alertLevel,
stateName,
origin,
reference,
name,
`in`,
`out`,
@a := @a + IFNULL(`in`,0) - IFNULL(`out`,0) as balance
FROM
( SELECT tr.landed as date,
b.quantity as `in`,
NULL as `out`,
IF(tr.isReceived != FALSE,3, IF(tr.isDelivered,1,0)) as alertLevel,
st.name AS stateName,
s.name as name,
e.ref as reference,
e.id as origin
FROM vn.buy b
JOIN vn.entry e ON e.id = b.entryFk
JOIN vn.travel tr ON tr.id = e.travelFk
JOIN vn.supplier s ON s.id = e.supplierFk
JOIN vn.alertLevel al ON al.alertLevel =
CASE
WHEN tr.isReceived != FALSE THEN 3
WHEN tr.isDelivered THEN 1
ELSE 0
END
JOIN vn.state st ON st.code = al.code
WHERE tr.landed >= vDateInventory
AND vWarehouse = tr.warehouseInFk
AND b.itemFk = vItemId
AND e.isInventory = 0
UNION ALL
SELECT tr.shipped as date,
NULL as `in`,
b.quantity as `out`,
IF(tr.isReceived != FALSE,3, IF(tr.isDelivered,1,0)) as alertLevel,
st.name AS stateName,
s.name as name,
e.ref as reference,
e.id as origin
FROM vn.buy b
JOIN vn.entry e ON e.id = b.entryFk
JOIN vn.travel tr ON tr.id = e.travelFk
JOIN vn.warehouse w ON w.id = tr.warehouseOutFk
JOIN vn.supplier s ON s.id = e.supplierFk
JOIN vn.alertLevel al ON al.alertLevel =
CASE
WHEN tr.isReceived != FALSE THEN 3
WHEN tr.isDelivered THEN 1
ELSE 0
END
JOIN vn.state st ON st.code = al.code
WHERE tr.shipped >= vDateInventory
AND vWarehouse =tr.warehouseOutFk
AND s.id <> 4
AND b.itemFk = vItemId
AND e.isInventory = 0
AND w.isFeedStock = 0
UNION ALL
SELECT t.shipped as date,
NULL as `in`,
s.quantity as `out`,
IF(t.shipped < vCurdate,3,IF(t.shipped > vCurdate, 0, IFNULL(ts.alertLevel,0))) as alertLevel,
st.name AS stateName,
t.nickname as name,
t.refFk as reference,
t.id as origin
FROM vn.sale s
JOIN vn.ticket t ON t.id = s.ticketFk
LEFT JOIN vn.ticketState ts ON ts.ticket = t.id
JOIN vn.client c ON c.id = t.clientFk
JOIN vn.alertLevel al ON al.alertLevel =
CASE
WHEN t.shipped < vCurdate THEN 3
WHEN t.shipped > vCurdate THEN 0
ELSE IFNULL(ts.alertLevel, 0)
END
JOIN vn.state st ON st.code = al.code
WHERE t.shipped >= vDateInventory
AND s.itemFk = vItemId
AND vWarehouse =t.warehouseFk
) AS itemDiary
ORDER BY date, alertLevel, `in` DESC;
END$$
DELIMITER ;

View File

@ -0,0 +1,27 @@
module.exports = Self => {
Self.remoteMethod('landsThatDay', {
description: 'Returns a list of agencies that can land a shipment on a day for an address',
accessType: '',
accepts: [{
arg: 'filter',
type: 'object',
required: true,
description: 'addressFk'
}],
returns: {
type: 'object',
root: true
},
http: {
path: `/landsThatDay`,
verb: 'get'
}
});
Self.landsThatDay = async filter => {
let query = `CALL vn.agencyHourGetAgency(?, ?)`;
let result = await Self.rawSql(query, [filter.addressFk, filter.landed]);
return result;
};
};

View File

@ -47,6 +47,19 @@ module.exports = Self => {
where: {isDefaultAddress: true}, where: {isDefaultAddress: true},
fields: ['nickname', 'street', 'city', 'postalCode'] fields: ['nickname', 'street', 'city', 'postalCode']
} }
},
{
relation: 'classifications',
scope: {
include: {
relation: 'insurances',
scope: {
fields: ['id', 'grade', 'created'],
order: 'created DESC'
}
},
where: {finished: null}
}
} }
], ],
where: {id: clientId} where: {id: clientId}

View File

@ -1,5 +1,5 @@
module.exports = Self => { module.exports = Self => {
Self.defineScope({where: {isManaged: {neq: 0}}}); Self.defineScope({where: {isManaged: {neq: 0}}});
//require('../methods/agency/sendsThatDay')(Self); require('../methods/agency/landsThatDay')(Self);
require('../methods/agency/getFirstShipped')(Self); require('../methods/agency/getFirstShipped')(Self);
}; };

View File

@ -160,7 +160,7 @@
"model": "Greuge", "model": "Greuge",
"foreignKey": "clientFk" "foreignKey": "clientFk"
}, },
"creditClassifications": { "classifications": {
"type": "hasMany", "type": "hasMany",
"model": "CreditClassification", "model": "CreditClassification",
"foreignKey": "client" "foreignKey": "client"

View File

@ -0,0 +1,55 @@
var mysql = require('mysql');
var SqlConnector = require('loopback-connector').SqlConnector;
var MySQL = require('loopback-connector-mysql').MySQL;
var EnumFactory = require('loopback-connector-mysql').EnumFactory;
exports.initialize = function(dataSource, callback) {
dataSource.driver = mysql;
dataSource.connector = new VnMySQL(dataSource.settings);
dataSource.connector.dataSource = dataSource;
var modelBuilder = dataSource.modelBuilder;
var defineType = modelBuilder.defineValueType ?
modelBuilder.defineValueType.bind(modelBuilder) :
modelBuilder.constructor.registerType.bind(modelBuilder.constructor);
defineType(function Point() {});
dataSource.EnumFactory = EnumFactory;
if (callback) {
if (dataSource.settings.lazyConnect) {
process.nextTick(function() {
callback();
});
} else {
dataSource.connector.connect(callback);
}
}
};
exports.VnMySQL = VnMySQL;
function VnMySQL(settings) {
SqlConnector.call(this, 'mysql', settings);
}
VnMySQL.prototype = Object.create(MySQL.prototype);
VnMySQL.constructor = VnMySQL;
VnMySQL.prototype.toColumnValue = function(prop, val) {
if (val == null || !prop || prop.type !== Date)
return MySQL.prototype.toColumnValue.call(this, prop, val);
return val.getFullYear() + '-' +
fillZeros(val.getMonth() + 1) + '-' +
fillZeros(val.getDate()) + ' ' +
fillZeros(val.getHours()) + ':' +
fillZeros(val.getMinutes()) + ':' +
fillZeros(val.getSeconds());
function fillZeros(v) {
return v < 10 ? '0' + v : v;
}
};

View File

@ -3,7 +3,8 @@
"connector": "memory" "connector": "memory"
}, },
"vn": { "vn": {
"connector": "mysql", "connector": "vn-mysql",
"timezone": "CET",
"database": "vn", "database": "vn",
"debug": false, "debug": false,
"host": "${salixHost}", "host": "${salixHost}",
@ -14,7 +15,7 @@
"acquireTimeout": 20000 "acquireTimeout": 20000
}, },
"salix": { "salix": {
"connector": "mysql", "connector": "vn-mysql",
"database": "salix", "database": "salix",
"debug": false, "debug": false,
"host": "${salixHost}", "host": "${salixHost}",
@ -25,7 +26,7 @@
"acquireTimeout": 20000 "acquireTimeout": 20000
}, },
"account": { "account": {
"connector": "mysql", "connector": "vn-mysql",
"database": "account", "database": "account",
"debug": false, "debug": false,
"host": "${salixHost}", "host": "${salixHost}",
@ -36,7 +37,7 @@
"acquireTimeout": 20000 "acquireTimeout": 20000
}, },
"edi": { "edi": {
"connector": "mysql", "connector": "vn-mysql",
"database": "edi", "database": "edi",
"debug": false, "debug": false,
"host": "${salixHost}", "host": "${salixHost}",
@ -47,7 +48,7 @@
"acquireTimeout": 20000 "acquireTimeout": 20000
}, },
"bs": { "bs": {
"connector": "mysql", "connector": "vn-mysql",
"database": "bs", "database": "bs",
"debug": false, "debug": false,
"host": "${salixHost}", "host": "${salixHost}",
@ -58,7 +59,7 @@
"acquireTimeout": 20000 "acquireTimeout": 20000
}, },
"hedera": { "hedera": {
"connector": "mysql", "connector": "vn-mysql",
"database": "hedera", "database": "hedera",
"debug": false, "debug": false,
"host": "${salixHost}", "host": "${salixHost}",

View File

@ -1,9 +1,24 @@
let loopback = require('loopback'); let loopback = require('loopback');
let boot = require('loopback-boot'); let boot = require('loopback-boot');
let DataSource = require('loopback-datasource-juggler').DataSource;
let fs = require('fs-extra'); let fs = require('fs-extra');
let i18n = require('i18n'); let i18n = require('i18n');
let path = require('path'); let path = require('path');
let _resolveConnector = DataSource._resolveConnector;
DataSource._resolveConnector = function(name) {
let testPath = `${__dirname}/connectors/${name}.js`;
if (fs.existsSync(testPath))
return {
connector: require(testPath),
error: null
};
return _resolveConnector.apply(this, arguments);
};
module.exports = { module.exports = {
loopback: loopback, loopback: loopback,
boot: vnBoot boot: vnBoot

View File

@ -3,8 +3,8 @@
"port": 3000, "port": 3000,
"debug": false, "debug": false,
"defaultLanguage": "es", "defaultLanguage": "es",
"senderMail": "noreply@localhost", "senderMail": "joan@verdnatura.es",
"senderName": "MySender" "senderName": "VerdNatura"
}, },
"mysql": { "mysql": {
"host": "localhost", "host": "localhost",
@ -14,12 +14,12 @@
"password": "root" "password": "root"
}, },
"smtp": { "smtp": {
"host": "localhost", "host": "smtp.verdnatura.es",
"port": 465, "port": 465,
"secure": true, "secure": true,
"auth": { "auth": {
"user": "noreply", "user": "joan",
"pass": "" "pass": "CLed3ejl$"
}, },
"tls": { "tls": {
"rejectUnauthorized": false "rejectUnauthorized": false

View File

@ -0,0 +1,51 @@
module.exports = Self => {
Self.remoteMethod('new', {
description: 'Create a new order and returns the new ID',
accessType: 'WRITE',
accepts: [{
arg: 'params',
type: 'object',
http: {source: 'body'}
}],
returns: {
type: 'number',
root: true
},
http: {
path: `/new`,
verb: 'post'
}
});
Self.new = async params => {
let cli = await Self.app.models.Address.findOne({where: {id: params.addressFk}, fields: 'clientFk'});
let client = await Self.app.models.Client.findOne({
where: {id: cli.clientFk},
fields: ['isTaxDataChecked', 'isFreezed', 'isActive']
});
if (client.isFreezed)
throw new Error(`You can't create an order for a frozen client`);
if (!client.isActive)
throw new Error(`You can't create an order for a inactive client`);
if (!client.isTaxDataChecked)
throw new Error(`You can't create an order for a client that doesn't has tax data verified`);
let query = `SELECT vn.clientGetDebt(?, CURDATE()) AS debt`;
let clientDebt = await Self.rawSql(query, [cli.clientFk]);
if (clientDebt[0].debt > 0)
throw new Error(`You can't create an order for a client that has a debt`);
query = `CALL vn.orderListCreate(?, ?, ?, ?);`;
result = await Self.rawSql(query, [
params.landed,
params.agencyModeFk,
params.addressFk,
"SALIX"
]);
return result[0].vOrderId;
};
};

View File

@ -0,0 +1,3 @@
module.exports = Self => {
require('../methods/new')(Self);
};