Merge branch '1368-ticket_sale_refactor' of https://gitea.verdnatura.es/verdnatura/salix into 1368-ticket_sale_refactor
This commit is contained in:
commit
1dfd0c26ef
|
@ -13,8 +13,15 @@ Required applications.
|
||||||
|
|
||||||
You will need to install globally the following items.
|
You will need to install globally the following items.
|
||||||
```
|
```
|
||||||
# sudo npm install -g jest gulp-cli
|
$ sudo npm install -g jest gulp-cli
|
||||||
```
|
```
|
||||||
|
|
||||||
|
For the usage of jest --watch on macOs.
|
||||||
|
```
|
||||||
|
$ brew install watchman
|
||||||
|
```
|
||||||
|
* [watchman](https://facebook.github.io/watchman/)
|
||||||
|
|
||||||
## Linux Only Prerequisites
|
## Linux Only Prerequisites
|
||||||
|
|
||||||
Your user must be on the docker group to use it so you will need to run this command:
|
Your user must be on the docker group to use it so you will need to run this command:
|
||||||
|
|
|
@ -626,7 +626,7 @@ export default {
|
||||||
},
|
},
|
||||||
ordersIndex: {
|
ordersIndex: {
|
||||||
searchResult: 'vn-order-index vn-card > vn-table > div > vn-tbody > a.vn-tr',
|
searchResult: 'vn-order-index vn-card > vn-table > div > vn-tbody > a.vn-tr',
|
||||||
firstSearchResultTotal: 'vn-order-index vn-card > vn-table > div > vn-tbody vn-tr vn-td:nth-child(9)',
|
firstSearchResultTotal: 'vn-order-index vn-card > vn-table > div > vn-tbody vn-tr vn-td:nth-child(7)',
|
||||||
searchResultDate: 'vn-order-index vn-table vn-tbody > a:nth-child(1) > vn-td:nth-child(4)',
|
searchResultDate: 'vn-order-index vn-table vn-tbody > a:nth-child(1) > vn-td:nth-child(4)',
|
||||||
searchResultAddress: 'vn-order-index vn-table vn-tbody > a:nth-child(1) > vn-td:nth-child(6)',
|
searchResultAddress: 'vn-order-index vn-table vn-tbody > a:nth-child(1) > vn-td:nth-child(6)',
|
||||||
searchButton: 'vn-searchbar vn-icon[icon="search"]',
|
searchButton: 'vn-searchbar vn-icon[icon="search"]',
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
describe('Component vnField', () => {
|
describe('Component vnField', () => {
|
||||||
let $element;
|
|
||||||
let controller;
|
let controller;
|
||||||
|
let $element;
|
||||||
|
|
||||||
beforeEach(ngModule('vnCore'));
|
beforeEach(ngModule('vnCore'));
|
||||||
|
|
||||||
|
@ -13,12 +13,84 @@ describe('Component vnField', () => {
|
||||||
$element.remove();
|
$element.remove();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Remove this block
|
describe('field get/set', () => {
|
||||||
describe('clearDisabled binding', () => {
|
it('should do nothing when trying to set the same value again', () => {
|
||||||
it(`should enable the show property`, () => {
|
controller.field = '';
|
||||||
controller.clearDisabled = true;
|
jest.spyOn(controller, 'validateValue');
|
||||||
|
|
||||||
expect(controller.clearDisabled).toEqual(true);
|
controller.field = '';
|
||||||
|
|
||||||
|
expect(controller.validateValue).toHaveBeenCalledTimes(0);
|
||||||
|
expect(controller.classList).not.toContain('not-empty');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add the class no empty and then call validateValue()', () => {
|
||||||
|
controller.field = '';
|
||||||
|
jest.spyOn(controller, 'validateValue');
|
||||||
|
|
||||||
|
controller.field = 'someField';
|
||||||
|
|
||||||
|
expect(controller.validateValue).toHaveBeenCalledTimes(1);
|
||||||
|
expect(controller.classList).toContain('not-empty');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('refreshHint()', () => {
|
||||||
|
it('should add the class invalid if there is an error in the controller', () => {
|
||||||
|
controller._error = true;
|
||||||
|
|
||||||
|
controller.refreshHint();
|
||||||
|
|
||||||
|
expect(controller.classList).toContain('invalid');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('onFocus()', () => {
|
||||||
|
it('should add the class focus', () => {
|
||||||
|
controller.onFocus(true);
|
||||||
|
|
||||||
|
expect(controller.classList).toContain('focused');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not add the class focus', () => {
|
||||||
|
controller.onFocus(false);
|
||||||
|
|
||||||
|
expect(controller.classList).not.toContain('focuses');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('buildInput()', () => {
|
||||||
|
it('should build an input based on the received type', () => {
|
||||||
|
controller.buildInput('number');
|
||||||
|
|
||||||
|
expect(controller.input.tagName).toEqual('INPUT');
|
||||||
|
expect(controller.input.type).toEqual('number');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('validateValue()', () => {
|
||||||
|
it('should do nothing if there is no new error to show', () => {
|
||||||
|
jest.spyOn(controller, 'refreshHint');
|
||||||
|
controller.inputError = 'old validation message';
|
||||||
|
controller.buildInput('number');
|
||||||
|
controller.input.setCustomValidity('old validation message');
|
||||||
|
|
||||||
|
controller.validateValue();
|
||||||
|
|
||||||
|
expect(controller.refreshHint).not.toHaveBeenCalled();
|
||||||
|
expect(controller.inputError).toEqual('old validation message');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update the input error and call refreshHint', () => {
|
||||||
|
jest.spyOn(controller, 'refreshHint');
|
||||||
|
controller.inputError = 'OLD validation message';
|
||||||
|
controller.buildInput('number');
|
||||||
|
controller.input.setCustomValidity('NEW validation message');
|
||||||
|
|
||||||
|
controller.validateValue();
|
||||||
|
|
||||||
|
expect(controller.refreshHint).toHaveBeenCalled();
|
||||||
|
expect(controller.inputError).toEqual('NEW validation message');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -68,6 +68,7 @@ export default class MultiCheck extends FormInput {
|
||||||
this.checkAll = value;
|
this.checkAll = value;
|
||||||
|
|
||||||
this.toggle();
|
this.toggle();
|
||||||
|
this.emit('change', value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -69,7 +69,7 @@
|
||||||
vn-tooltip="Remove sale"
|
vn-tooltip="Remove sale"
|
||||||
ng-if ="$ctrl.isRewritable"
|
ng-if ="$ctrl.isRewritable"
|
||||||
icon="delete"
|
icon="delete"
|
||||||
ng-click="$ctrl.deleteClaimedSale($index)"
|
ng-click="$ctrl.showDeleteConfirm($index)"
|
||||||
tabindex="-1">
|
tabindex="-1">
|
||||||
</vn-icon-button>
|
</vn-icon-button>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
|
@ -165,3 +165,8 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</vn-popover>
|
</vn-popover>
|
||||||
|
<vn-confirm
|
||||||
|
vn-id="confirm"
|
||||||
|
question="Delete sale from claim?"
|
||||||
|
on-accept="$ctrl.deleteClaimedSale()">
|
||||||
|
</vn-confirm>
|
|
@ -73,12 +73,16 @@ class Controller extends Section {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteClaimedSale(index) {
|
showDeleteConfirm(index) {
|
||||||
let sale = this.salesClaimed[index];
|
this.sale = this.salesClaimed[index];
|
||||||
let query = `ClaimBeginnings/${sale.id}`;
|
this.$.confirm.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteClaimedSale() {
|
||||||
|
let query = `ClaimBeginnings/${this.sale.id}`;
|
||||||
this.$http.delete(query).then(() => {
|
this.$http.delete(query).then(() => {
|
||||||
this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
|
this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
|
||||||
this.$.model.remove(index);
|
this.$.model.remove(this.sale);
|
||||||
this.calculateTotals();
|
this.calculateTotals();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,14 +71,16 @@ describe('claim', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('deleteClaimedSale(index)', () => {
|
describe('deleteClaimedSale()', () => {
|
||||||
it('should make a delete and call refresh and showSuccess', () => {
|
it('should make a delete and call refresh and showSuccess', () => {
|
||||||
|
controller.sale = {id: 1};
|
||||||
jest.spyOn(controller.$.model, 'remove');
|
jest.spyOn(controller.$.model, 'remove');
|
||||||
$httpBackend.expectDELETE(`ClaimBeginnings/1`).respond({});
|
jest.spyOn(controller.vnApp, 'showSuccess');
|
||||||
controller.deleteClaimedSale(0);
|
$httpBackend.expectDELETE(`ClaimBeginnings/1`).respond('ok');
|
||||||
|
controller.deleteClaimedSale();
|
||||||
$httpBackend.flush();
|
$httpBackend.flush();
|
||||||
|
|
||||||
expect(controller.$.model.remove).toHaveBeenCalledWith(0);
|
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -7,4 +7,5 @@ Claimable sales from ticket: Lineas reclamables del ticket
|
||||||
Detail: Detalles
|
Detail: Detalles
|
||||||
Add sale item: Añadir artículo
|
Add sale item: Añadir artículo
|
||||||
Insuficient permisos: Permisos insuficientes
|
Insuficient permisos: Permisos insuficientes
|
||||||
Total claimed price: Precio total reclamado
|
Total claimed price: Precio total reclamado
|
||||||
|
Delete sale from claim?: ¿Borrar la linea de la reclamación?
|
|
@ -156,6 +156,7 @@ module.exports = Self => {
|
||||||
c.name clientName,
|
c.name clientName,
|
||||||
c.salesPersonFk,
|
c.salesPersonFk,
|
||||||
u.nickname workerNickname,
|
u.nickname workerNickname,
|
||||||
|
u.name name,
|
||||||
co.code companyCode
|
co.code companyCode
|
||||||
FROM hedera.order o
|
FROM hedera.order o
|
||||||
LEFT JOIN address a ON a.id = o.address_id
|
LEFT JOIN address a ON a.id = o.address_id
|
||||||
|
|
|
@ -13,10 +13,8 @@
|
||||||
<vn-th field="clientFk">Client</vn-th>
|
<vn-th field="clientFk">Client</vn-th>
|
||||||
<vn-th field="salesPersonFk">Sales person</vn-th>
|
<vn-th field="salesPersonFk">Sales person</vn-th>
|
||||||
<vn-th field="isConfirmed" center>Confirmed</vn-th>
|
<vn-th field="isConfirmed" center>Confirmed</vn-th>
|
||||||
<vn-th field="sourceApp">Created from</vn-th>
|
|
||||||
<vn-th field="created" center>Created</vn-th>
|
<vn-th field="created" center>Created</vn-th>
|
||||||
<vn-th field="landed" default-order="DESC" center>Landed</vn-th>
|
<vn-th field="landed" default-order="DESC" center>Landed</vn-th>
|
||||||
<vn-th field="companyFk">Company</vn-th>
|
|
||||||
<vn-th center>Total</vn-th>
|
<vn-th center>Total</vn-th>
|
||||||
</vn-tr>
|
</vn-tr>
|
||||||
</vn-thead>
|
</vn-thead>
|
||||||
|
@ -37,7 +35,7 @@
|
||||||
<span
|
<span
|
||||||
vn-click-stop="workerDescriptor.show($event, order.salesPersonFk)"
|
vn-click-stop="workerDescriptor.show($event, order.salesPersonFk)"
|
||||||
class="link" >
|
class="link" >
|
||||||
{{::order.workerNickname | dashIfEmpty}}
|
{{::order.name | dashIfEmpty}}
|
||||||
</span>
|
</span>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td center>
|
<vn-td center>
|
||||||
|
@ -46,10 +44,8 @@
|
||||||
disabled="true">
|
disabled="true">
|
||||||
</vn-check>
|
</vn-check>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td>{{::order.sourceApp}}</vn-td>
|
|
||||||
<vn-td center>{{::order.created | date: 'dd/MM/yyyy HH:mm'}}</vn-td>
|
<vn-td center>{{::order.created | date: 'dd/MM/yyyy HH:mm'}}</vn-td>
|
||||||
<vn-td center>{{::order.landed | date:'dd/MM/yyyy'}}</vn-td>
|
<vn-td center>{{::order.landed | date:'dd/MM/yyyy'}}</vn-td>
|
||||||
<vn-td>{{::order.companyCode}}</vn-td>
|
|
||||||
<vn-td number>{{::order.total | currency: 'EUR': 2 | dashIfEmpty}}</vn-td>
|
<vn-td number>{{::order.total | currency: 'EUR': 2 | dashIfEmpty}}</vn-td>
|
||||||
<vn-td shrink>
|
<vn-td shrink>
|
||||||
<vn-icon-button
|
<vn-icon-button
|
||||||
|
|
|
@ -11,6 +11,9 @@
|
||||||
<vn-check label="Confirmed" disabled="true"
|
<vn-check label="Confirmed" disabled="true"
|
||||||
ng-model="$ctrl.summary.isConfirmed">
|
ng-model="$ctrl.summary.isConfirmed">
|
||||||
</vn-check>
|
</vn-check>
|
||||||
|
<vn-label-value label="Company"
|
||||||
|
value="{{$ctrl.summary.address.companyFk}}">
|
||||||
|
</vn-label-value>
|
||||||
</vn-one>
|
</vn-one>
|
||||||
<vn-one>
|
<vn-one>
|
||||||
<vn-label-value label="Created"
|
<vn-label-value label="Created"
|
||||||
|
@ -21,6 +24,7 @@
|
||||||
</vn-label-value>
|
</vn-label-value>
|
||||||
<vn-label-value label="Address"
|
<vn-label-value label="Address"
|
||||||
value="{{$ctrl.formattedAddress}}">
|
value="{{$ctrl.formattedAddress}}">
|
||||||
|
</vn-label-value>
|
||||||
<vn-label-value label="Phone"
|
<vn-label-value label="Phone"
|
||||||
value="{{$ctrl.summary.address.phone}}">
|
value="{{$ctrl.summary.address.phone}}">
|
||||||
</vn-label-value>
|
</vn-label-value>
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
<vn-item
|
<vn-item
|
||||||
ng-click="addTurn.show()"
|
ng-click="addTurn.show()"
|
||||||
vn-acl="buyer"
|
vn-acl="buyer"
|
||||||
|
ng-show="$ctrl.isEditable"
|
||||||
vn-acl-action="remove"
|
vn-acl-action="remove"
|
||||||
name="addTurn"
|
name="addTurn"
|
||||||
translate>
|
translate>
|
||||||
|
@ -60,7 +61,7 @@
|
||||||
</vn-item>
|
</vn-item>
|
||||||
<vn-item
|
<vn-item
|
||||||
ng-click="makeInvoiceConfirmation.show()"
|
ng-click="makeInvoiceConfirmation.show()"
|
||||||
ng-show="!$ctrl.isInvoiced"
|
ng-show="$ctrl.isEditable"
|
||||||
vn-acl="invoicing"
|
vn-acl="invoicing"
|
||||||
vn-acl-action="remove"
|
vn-acl-action="remove"
|
||||||
name="makeInvoice"
|
name="makeInvoice"
|
||||||
|
|
|
@ -8,6 +8,7 @@ class Controller extends Descriptor {
|
||||||
|
|
||||||
set ticket(value) {
|
set ticket(value) {
|
||||||
this.entity = value;
|
this.entity = value;
|
||||||
|
this.isTicketEditable();
|
||||||
}
|
}
|
||||||
|
|
||||||
get entity() {
|
get entity() {
|
||||||
|
@ -22,14 +23,6 @@ class Controller extends Descriptor {
|
||||||
this.showSMSDialog();
|
this.showSMSDialog();
|
||||||
}
|
}
|
||||||
|
|
||||||
get isEditable() {
|
|
||||||
try {
|
|
||||||
return !this.ticket.tracking.state.alertLevel;
|
|
||||||
} catch (e) {}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
get isInvoiced() {
|
get isInvoiced() {
|
||||||
return this.ticket.refFk !== null;
|
return this.ticket.refFk !== null;
|
||||||
}
|
}
|
||||||
|
@ -45,6 +38,12 @@ class Controller extends Descriptor {
|
||||||
return this.ticket.stowaway || this.ticket.ship;
|
return this.ticket.stowaway || this.ticket.ship;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isTicketEditable() {
|
||||||
|
this.$http.get(`Tickets/${this.$state.params.id}/isEditable`).then(res => {
|
||||||
|
this.isEditable = res.data;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
showChangeShipped() {
|
showChangeShipped() {
|
||||||
this.newShipped = this.ticket.shipped;
|
this.newShipped = this.ticket.shipped;
|
||||||
this.$.changeShippedDialog.show();
|
this.$.changeShippedDialog.show();
|
||||||
|
|
|
@ -28,8 +28,10 @@ describe('Ticket Component vnTicketDescriptor', () => {
|
||||||
beforeEach(angular.mock.inject(($componentController, _$httpBackend_, _$state_) => {
|
beforeEach(angular.mock.inject(($componentController, _$httpBackend_, _$state_) => {
|
||||||
$httpBackend = _$httpBackend_;
|
$httpBackend = _$httpBackend_;
|
||||||
$httpBackend.whenGET(`Tickets/${ticket.id}/canHaveStowaway`).respond(true);
|
$httpBackend.whenGET(`Tickets/${ticket.id}/canHaveStowaway`).respond(true);
|
||||||
|
$httpBackend.whenGET(`Tickets/1/isEditable`).respond(true);
|
||||||
|
|
||||||
$state = _$state_;
|
$state = _$state_;
|
||||||
|
$state.params.id = 1;
|
||||||
$state.getCurrentPath = () => [null, {state: {name: 'ticket'}}];
|
$state.getCurrentPath = () => [null, {state: {name: 'ticket'}}];
|
||||||
|
|
||||||
controller = $componentController('vnTicketDescriptor', {$element: null}, {ticket});
|
controller = $componentController('vnTicketDescriptor', {$element: null}, {ticket});
|
||||||
|
|
|
@ -24,29 +24,19 @@
|
||||||
url="States/editableStates"
|
url="States/editableStates"
|
||||||
on-change="$ctrl.changeState(value)">
|
on-change="$ctrl.changeState(value)">
|
||||||
</vn-button-menu>
|
</vn-button-menu>
|
||||||
<!-- <vn-button-menu
|
|
||||||
ng-show="$ctrl.isChecked"
|
|
||||||
vn-id="more-button"
|
|
||||||
label="More"
|
|
||||||
show-filter="false"
|
|
||||||
value-field="callback"
|
|
||||||
translate-fields="['name']"
|
|
||||||
on-change="$ctrl.onMoreChange(value)"
|
|
||||||
on-open="$ctrl.onMoreOpen()">
|
|
||||||
</vn-button-menu> -->
|
|
||||||
<vn-button icon="keyboard_arrow_down"
|
<vn-button icon="keyboard_arrow_down"
|
||||||
label="More"
|
label="More"
|
||||||
ng-click="moreOptions.show($event)"
|
ng-click="moreOptions.show($event)"
|
||||||
ng-show="$ctrl.hasCheckedLines()">
|
ng-show="$ctrl.hasSelectedSales()">
|
||||||
</vn-button>
|
</vn-button>
|
||||||
<vn-button
|
<vn-button
|
||||||
disabled="!$ctrl.hasCheckedLines() || !$ctrl.isEditable"
|
disabled="!$ctrl.hasSelectedSales() || !$ctrl.isEditable"
|
||||||
ng-click="deleteLines.show()"
|
ng-click="deleteLines.show()"
|
||||||
vn-tooltip="Remove lines"
|
vn-tooltip="Remove lines"
|
||||||
icon="delete">
|
icon="delete">
|
||||||
</vn-button>
|
</vn-button>
|
||||||
<vn-button
|
<vn-button
|
||||||
disabled="!$ctrl.hasCheckedLines() || !$ctrl.isEditable"
|
disabled="!$ctrl.hasSelectedSales() || !$ctrl.isEditable"
|
||||||
ng-click="$ctrl.showTransferPopover($event)"
|
ng-click="$ctrl.showTransferPopover($event)"
|
||||||
vn-tooltip="Transfer lines"
|
vn-tooltip="Transfer lines"
|
||||||
icon="call_split">
|
icon="call_split">
|
||||||
|
@ -62,8 +52,8 @@
|
||||||
<vn-thead>
|
<vn-thead>
|
||||||
<vn-tr>
|
<vn-tr>
|
||||||
<vn-th shrink>
|
<vn-th shrink>
|
||||||
<vn-multi-check
|
<vn-multi-check model="model"
|
||||||
model="model">
|
on-change="$ctrl.resetChanges()">
|
||||||
</vn-multi-check>
|
</vn-multi-check>
|
||||||
</vn-th>
|
</vn-th>
|
||||||
<vn-th shrink></vn-th>
|
<vn-th shrink></vn-th>
|
||||||
|
@ -79,7 +69,7 @@
|
||||||
<vn-tbody>
|
<vn-tbody>
|
||||||
<vn-tr ng-repeat="sale in $ctrl.sales">
|
<vn-tr ng-repeat="sale in $ctrl.sales">
|
||||||
<vn-td shrink>
|
<vn-td shrink>
|
||||||
<vn-check
|
<vn-check tabindex="-1"
|
||||||
ng-model="sale.checked">
|
ng-model="sale.checked">
|
||||||
</vn-check>
|
</vn-check>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
|
@ -107,13 +97,12 @@
|
||||||
zoom-image="{{::$root.imagePath}}/catalog/1600x900/{{sale.image}}"
|
zoom-image="{{::$root.imagePath}}/catalog/1600x900/{{sale.image}}"
|
||||||
on-error-src/>
|
on-error-src/>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td vn-focus number>
|
<vn-td number>
|
||||||
<span class="link" ng-if="sale.id"
|
<span class="link" ng-if="sale.id"
|
||||||
ng-click="descriptor.show($event, sale.itemFk, sale.id)">
|
ng-click="descriptor.show($event, sale.itemFk, sale.id)">
|
||||||
{{sale.itemFk}}
|
{{sale.itemFk}}
|
||||||
</span>
|
</span>
|
||||||
<vn-autocomplete
|
<vn-autocomplete ng-if="!sale.id"
|
||||||
ng-if="!sale.id"
|
|
||||||
vn-focus
|
vn-focus
|
||||||
vn-one
|
vn-one
|
||||||
url="Items"
|
url="Items"
|
||||||
|
@ -125,11 +114,11 @@
|
||||||
order="id DESC"
|
order="id DESC"
|
||||||
tabindex="1">
|
tabindex="1">
|
||||||
<tpl-item>
|
<tpl-item>
|
||||||
{{id}} - {{name}}
|
{{::id}} - {{::name}}
|
||||||
</tpl-item>
|
</tpl-item>
|
||||||
</vn-autocomplete>
|
</vn-autocomplete>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td-editable ng-if="sale.id" disabled="!$ctrl.isEditable" number>
|
<vn-td-editable disabled="!$ctrl.isEditable" number>
|
||||||
<text>{{sale.quantity}}</text>
|
<text>{{sale.quantity}}</text>
|
||||||
<field>
|
<field>
|
||||||
<vn-input-number class="dense"
|
<vn-input-number class="dense"
|
||||||
|
@ -139,20 +128,13 @@
|
||||||
</vn-input-number>
|
</vn-input-number>
|
||||||
</field>
|
</field>
|
||||||
</vn-td-editable>
|
</vn-td-editable>
|
||||||
<vn-td ng-if="!sale.id" number>
|
|
||||||
<vn-input-number
|
|
||||||
ng-model="sale.quantity"
|
|
||||||
on-change="$ctrl.changeQuantity(sale)"
|
|
||||||
tabindex="2">
|
|
||||||
</vn-input-number>
|
|
||||||
</vn-td>
|
|
||||||
<vn-td-editable disabled="!sale.id || !$ctrl.isEditable" expand>
|
<vn-td-editable disabled="!sale.id || !$ctrl.isEditable" expand>
|
||||||
<text>
|
<text>
|
||||||
<vn-fetched-tags
|
<vn-fetched-tags
|
||||||
max-length="6"
|
max-length="6"
|
||||||
item="sale.item"
|
item="::sale.item"
|
||||||
name="sale.concept"
|
name="sale.concept"
|
||||||
sub-name="sale.subName">
|
sub-name="::sale.subName">
|
||||||
</vn-fetched-tags>
|
</vn-fetched-tags>
|
||||||
</text>
|
</text>
|
||||||
<field>
|
<field>
|
||||||
|
@ -200,7 +182,7 @@
|
||||||
ng-show="$ctrl.isEditable"
|
ng-show="$ctrl.isEditable"
|
||||||
ng-click="$ctrl.newOrderFromTicket()"
|
ng-click="$ctrl.newOrderFromTicket()"
|
||||||
icon="add"
|
icon="add"
|
||||||
vn-tooltip="Add item"
|
vn-tooltip="Add item to basket"
|
||||||
vn-bind="+"
|
vn-bind="+"
|
||||||
fixed-bottom-right>
|
fixed-bottom-right>
|
||||||
</vn-float-button>
|
</vn-float-button>
|
||||||
|
@ -221,7 +203,7 @@
|
||||||
</vn-spinner>
|
</vn-spinner>
|
||||||
<div ng-if="$ctrl.edit.mana != null">
|
<div ng-if="$ctrl.edit.mana != null">
|
||||||
<section class="header vn-pa-md">
|
<section class="header vn-pa-md">
|
||||||
<h5>MANÁ: {{$ctrl.edit.mana | currency: 'EUR': 0}}</h5>
|
<h5>MANÁ: {{::$ctrl.edit.mana | currency: 'EUR': 0}}</h5>
|
||||||
</section>
|
</section>
|
||||||
<div class="vn-pa-md">
|
<div class="vn-pa-md">
|
||||||
<vn-input-number
|
<vn-input-number
|
||||||
|
@ -254,7 +236,7 @@
|
||||||
</vn-spinner>
|
</vn-spinner>
|
||||||
<div ng-if="$ctrl.edit.mana != null">
|
<div ng-if="$ctrl.edit.mana != null">
|
||||||
<section class="header vn-pa-md">
|
<section class="header vn-pa-md">
|
||||||
<h5>Mana: {{$ctrl.edit.mana | currency: 'EUR':0}}</h5>
|
<h5>Mana: {{::$ctrl.edit.mana | currency: 'EUR':0}}</h5>
|
||||||
</section>
|
</section>
|
||||||
<div class="vn-pa-md">
|
<div class="vn-pa-md">
|
||||||
<vn-input-number
|
<vn-input-number
|
||||||
|
@ -272,13 +254,6 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- <vn-ticket-sale-edit-discount
|
|
||||||
ng-if="$ctrl.edit.mana != null"
|
|
||||||
mana="$ctrl.edit.mana"
|
|
||||||
bulk="false"
|
|
||||||
edit="$ctrl.edit"
|
|
||||||
on-hide="$ctrl.hideEditPopover()">
|
|
||||||
</vn-ticket-sale-edit-discount> -->
|
|
||||||
</div>
|
</div>
|
||||||
</vn-popover>
|
</vn-popover>
|
||||||
|
|
||||||
|
@ -301,7 +276,7 @@
|
||||||
</vn-input-number>
|
</vn-input-number>
|
||||||
</div>
|
</div>
|
||||||
<section class="header vn-pa-md">
|
<section class="header vn-pa-md">
|
||||||
<span>Mana: <strong>{{$ctrl.edit.mana | currency: 'EUR': 0}}</strong></span>
|
<span>Mana: <strong>{{::$ctrl.edit.mana | currency: 'EUR': 0}}</strong></span>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</tpl-body>
|
</tpl-body>
|
||||||
|
@ -409,7 +384,7 @@
|
||||||
vn-id="delete-lines"
|
vn-id="delete-lines"
|
||||||
question="You are going to delete lines of the ticket"
|
question="You are going to delete lines of the ticket"
|
||||||
message="Continue anyway?"
|
message="Continue anyway?"
|
||||||
on-response="$ctrl.onRemoveLinesClick($response)">
|
on-response="$ctrl.removeSales()">
|
||||||
</vn-confirm>
|
</vn-confirm>
|
||||||
|
|
||||||
<vn-confirm
|
<vn-confirm
|
||||||
|
|
|
@ -5,32 +5,6 @@ import './style.scss';
|
||||||
class Controller extends Section {
|
class Controller extends Section {
|
||||||
constructor($element, $) {
|
constructor($element, $) {
|
||||||
super($element, $);
|
super($element, $);
|
||||||
// this.edit = {};
|
|
||||||
/* this.moreOptions = [
|
|
||||||
{
|
|
||||||
name: 'Send shortage SMS',
|
|
||||||
callback: this.showSMSDialog
|
|
||||||
}, {
|
|
||||||
name: 'Mark as reserved',
|
|
||||||
callback: this.markAsReserved,
|
|
||||||
show: () => this.isEditable
|
|
||||||
}, {
|
|
||||||
name: 'Unmark as reserved',
|
|
||||||
callback: this.unmarkAsReserved,
|
|
||||||
show: () => this.isEditable
|
|
||||||
}, {
|
|
||||||
name: 'Update discount',
|
|
||||||
callback: this.showEditDialog,
|
|
||||||
show: () => this.isEditable
|
|
||||||
}, {
|
|
||||||
name: 'Add claim',
|
|
||||||
callback: this.createClaim
|
|
||||||
}, {
|
|
||||||
name: 'Recalculate price',
|
|
||||||
callback: this.calculateSalePrice,
|
|
||||||
show: () => this.hasOneSaleSelected()
|
|
||||||
},
|
|
||||||
]; */
|
|
||||||
this._sales = [];
|
this._sales = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,24 +27,14 @@ class Controller extends Section {
|
||||||
this.refreshTotal();
|
this.refreshTotal();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get editedPrice() {
|
|
||||||
return this._editedPrice;
|
|
||||||
}
|
|
||||||
|
|
||||||
set editedPrice(value) {
|
|
||||||
this._editedPrice = value;
|
|
||||||
this.updateNewPrice();
|
|
||||||
} */
|
|
||||||
|
|
||||||
get ticketState() {
|
get ticketState() {
|
||||||
if (!this.ticket) return null;
|
if (!this.ticket) return null;
|
||||||
|
|
||||||
return this.ticket.ticketState.state.code;
|
return this.ticket.ticketState.state.code;
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshTotal() {
|
get total() {
|
||||||
this.getSubTotal();
|
return this.subtotal + this.VAT;
|
||||||
this.getVat();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getSubTotal() {
|
getSubTotal() {
|
||||||
|
@ -90,6 +54,11 @@ class Controller extends Section {
|
||||||
return price - discount;
|
return price - discount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getMana() {
|
||||||
|
this.$http.get(`Tickets/${this.$params.id}/getSalesPersonMana`)
|
||||||
|
.then(res => this.edit.mana = res.data);
|
||||||
|
}
|
||||||
|
|
||||||
getVat() {
|
getVat() {
|
||||||
this.VAT = 0.0;
|
this.VAT = 0.0;
|
||||||
if (!this.$params.id || !this.sales) return;
|
if (!this.$params.id || !this.sales) return;
|
||||||
|
@ -98,40 +67,17 @@ class Controller extends Section {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
get total() {
|
refreshTotal() {
|
||||||
return this.subtotal + this.VAT;
|
this.getSubTotal();
|
||||||
|
this.getVat();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* onMoreOpen() {
|
|
||||||
let options = this.moreOptions.filter(option => {
|
|
||||||
const hasShowProperty = Object.hasOwnProperty.call(option, 'show');
|
|
||||||
const shouldShow = !hasShowProperty || option.show === true ||
|
|
||||||
typeof option.show === 'function' && option.show();
|
|
||||||
|
|
||||||
return (shouldShow && (option.always || this.isChecked));
|
|
||||||
});
|
|
||||||
this.$.moreButton.data = options;
|
|
||||||
}
|
|
||||||
|
|
||||||
onMoreChange(callback) {
|
|
||||||
callback.call(this);
|
|
||||||
} */
|
|
||||||
|
|
||||||
/* get isChecked() {
|
|
||||||
if (this.sales) {
|
|
||||||
for (let instance of this.sales)
|
|
||||||
if (instance.checked) return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
} */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns checked instances
|
* Returns checked instances
|
||||||
*
|
*
|
||||||
* @return {Array} Checked instances
|
* @return {Array} Checked instances
|
||||||
*/
|
*/
|
||||||
checkedLines() {
|
selectedSales() {
|
||||||
if (!this.sales) return;
|
if (!this.sales) return;
|
||||||
|
|
||||||
return this.sales.filter(sale => {
|
return this.sales.filter(sale => {
|
||||||
|
@ -139,30 +85,34 @@ class Controller extends Section {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
selectedValidSales() {
|
||||||
|
if (!this.sales) return;
|
||||||
|
|
||||||
|
const selectedSales = this.selectedSales();
|
||||||
|
return selectedSales.filter(sale => {
|
||||||
|
return sale.id != undefined;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the total of checked instances
|
* Returns the total of checked instances
|
||||||
*
|
*
|
||||||
* @return {Number} Total checked instances
|
* @return {Number} Total checked instances
|
||||||
*/
|
*/
|
||||||
checkedLinesCount() {
|
selectedSalesCount() {
|
||||||
const checkedLines = this.checkedLines();
|
const selectedSales = this.selectedSales();
|
||||||
if (checkedLines)
|
if (selectedSales)
|
||||||
return checkedLines.length;
|
return selectedSales.length;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
hasCheckedLines() {
|
hasSelectedSales() {
|
||||||
const checkedLines = this.checkedLines();
|
return this.selectedSalesCount() > 0;
|
||||||
|
|
||||||
if (checkedLines)
|
|
||||||
return checkedLines.length > 0;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hasOneSaleSelected() {
|
hasOneSaleSelected() {
|
||||||
if (this.checkedLinesCount() === 1)
|
if (this.selectedSalesCount() === 1)
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -181,77 +131,68 @@ class Controller extends Section {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an array of indexes
|
* Returns an array of index
|
||||||
* from checked instances
|
* from checked instances
|
||||||
*
|
*
|
||||||
* @return {Array} Indexes of checked instances
|
* @return {Array} Index list of checked instances
|
||||||
*/
|
*/
|
||||||
checkedLinesIndex() {
|
selectedSalesIndex() {
|
||||||
if (!this.sales) return;
|
if (!this.sales) return;
|
||||||
|
|
||||||
let indexes = [];
|
const indexList = [];
|
||||||
this.sales.forEach((sale, index) => {
|
this.sales.forEach((sale, index) => {
|
||||||
if (sale.checked) indexes.push(index);
|
if (sale.checked) indexList.push(index);
|
||||||
});
|
});
|
||||||
|
|
||||||
return indexes;
|
return indexList;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* firstCheckedLine() {
|
resetChanges() {
|
||||||
const checkedLines = this.checkedLines();
|
if (this.newInstances().length === 0)
|
||||||
if (checkedLines)
|
this.$.watcher.updateOriginalData();
|
||||||
return checkedLines[0];
|
}
|
||||||
} */
|
|
||||||
|
|
||||||
removeCheckedLines() {
|
changeState(value) {
|
||||||
const sales = this.checkedLines();
|
const params = {ticketFk: this.$params.id, code: value};
|
||||||
|
return this.$http.post('TicketTrackings/changeState', params).then(() => {
|
||||||
|
this.vnApp.showSuccess(this.$t('Data saved!'));
|
||||||
|
this.card.reload();
|
||||||
|
}).finally(() => this.resetChanges());
|
||||||
|
}
|
||||||
|
|
||||||
|
removeSales() {
|
||||||
|
const sales = this.selectedValidSales();
|
||||||
|
const params = {sales: sales, actualTicketFk: this.ticket.id};
|
||||||
|
this.$http.post(`Sales/removes`, params).then(() => {
|
||||||
|
this.removeSelectedSales();
|
||||||
|
this.vnApp.showSuccess(this.$t('Data saved!'));
|
||||||
|
}).finally(() => this.resetChanges());
|
||||||
|
}
|
||||||
|
|
||||||
|
removeSelectedSales() {
|
||||||
|
const sales = this.selectedSales();
|
||||||
sales.forEach(sale => {
|
sales.forEach(sale => {
|
||||||
const index = this.sales.indexOf(sale);
|
const index = this.sales.indexOf(sale);
|
||||||
this.sales.splice(index, 1);
|
this.sales.splice(index, 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.newInstances().length === 0)
|
|
||||||
this.$.watcher.updateOriginalData();
|
|
||||||
|
|
||||||
this.refreshTotal();
|
this.refreshTotal();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* onStateOkClick() {
|
createClaim() {
|
||||||
let filter = {where: {code: 'OK'}, fields: ['id']};
|
const sales = this.selectedValidSales();
|
||||||
let json = encodeURIComponent(JSON.stringify(filter));
|
const params = {
|
||||||
return this.$http.get(`States?filter=${json}`).then(res => {
|
claim: {
|
||||||
this.changeState(res.data[0].id);
|
ticketFk: this.ticket.id,
|
||||||
});
|
clientFk: this.ticket.clientFk,
|
||||||
}
|
ticketCreated: this.ticket.shipped
|
||||||
*/
|
},
|
||||||
changeState(value) {
|
sales: sales
|
||||||
let params = {ticketFk: this.$params.id, code: value};
|
};
|
||||||
this.$http.post('TicketTrackings/changeState', params).then(() => {
|
|
||||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
|
||||||
this.card.reload();
|
|
||||||
}).finally(() => {
|
|
||||||
if (this.newInstances().length === 0)
|
|
||||||
this.$.watcher.updateOriginalData();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onRemoveLinesClick(response) {
|
this.resetChanges();
|
||||||
if (response === 'accept') {
|
this.$http.post(`Claims/createFromSales`, params)
|
||||||
let sales = this.checkedLines();
|
.then(res => this.$state.go('claim.card.basicData', {id: res.data.id}));
|
||||||
|
|
||||||
// Remove unsaved instances
|
|
||||||
sales.forEach((sale, index) => {
|
|
||||||
if (!sale.id) sales.splice(index);
|
|
||||||
});
|
|
||||||
|
|
||||||
let params = {sales: sales, actualTicketFk: this.ticket.id};
|
|
||||||
let query = `Sales/removes`;
|
|
||||||
this.$http.post(query, params).then(() => {
|
|
||||||
this.removeCheckedLines();
|
|
||||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
showTransferPopover(event) {
|
showTransferPopover(event) {
|
||||||
|
@ -261,7 +202,7 @@ class Controller extends Section {
|
||||||
}
|
}
|
||||||
|
|
||||||
setTransferParams() {
|
setTransferParams() {
|
||||||
const checkedSales = JSON.stringify(this.checkedLines());
|
const checkedSales = JSON.stringify(this.selectedValidSales());
|
||||||
const sales = JSON.parse(checkedSales);
|
const sales = JSON.parse(checkedSales);
|
||||||
this.transfer = {
|
this.transfer = {
|
||||||
lastActiveTickets: [],
|
lastActiveTickets: [],
|
||||||
|
@ -288,29 +229,6 @@ class Controller extends Section {
|
||||||
.then(res => this.$state.go('ticket.card.sale', {id: res.data.id}));
|
.then(res => this.$state.go('ticket.card.sale', {id: res.data.id}));
|
||||||
}
|
}
|
||||||
|
|
||||||
createClaim() {
|
|
||||||
const sales = this.checkedLines();
|
|
||||||
const params = {
|
|
||||||
claim: {
|
|
||||||
ticketFk: this.ticket.id,
|
|
||||||
clientFk: this.ticket.clientFk,
|
|
||||||
ticketCreated: this.ticket.shipped
|
|
||||||
},
|
|
||||||
sales: sales
|
|
||||||
};
|
|
||||||
|
|
||||||
if (this.newInstances().length === 0)
|
|
||||||
this.$.watcher.updateOriginalData();
|
|
||||||
|
|
||||||
this.$http.post(`Claims/createFromSales`, params)
|
|
||||||
.then(res => this.$state.go('claim.card.basicData', {id: res.data.id}));
|
|
||||||
}
|
|
||||||
|
|
||||||
getMana() {
|
|
||||||
this.$http.get(`Tickets/${this.$params.id}/getSalesPersonMana`)
|
|
||||||
.then(res => this.edit.mana = res.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
showEditPricePopover(event, sale) {
|
showEditPricePopover(event, sale) {
|
||||||
if (!this.isEditable) return;
|
if (!this.isEditable) return;
|
||||||
|
|
||||||
|
@ -330,19 +248,12 @@ class Controller extends Section {
|
||||||
sale.price = res.data.price;
|
sale.price = res.data.price;
|
||||||
this.edit = null;
|
this.edit = null;
|
||||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
this.vnApp.showSuccess(this.$t('Data saved!'));
|
||||||
}).finally(() => {
|
}).finally(() => this.resetChanges());
|
||||||
if (this.newInstances().length === 0)
|
|
||||||
this.$.watcher.updateOriginalData();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$.editPricePopover.hide();
|
this.$.editPricePopover.hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* updateNewPrice() {
|
|
||||||
this.newPrice = this.sale.quantity * this.newPrice - ((this.sale.discount * (this.sale.quantity * this.newPrice)) / 100);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
showEditDiscountPopover(event, sale) {
|
showEditDiscountPopover(event, sale) {
|
||||||
if (this.isLocked) return;
|
if (this.isLocked) return;
|
||||||
|
|
||||||
|
@ -359,7 +270,7 @@ class Controller extends Section {
|
||||||
|
|
||||||
this.edit = {
|
this.edit = {
|
||||||
discount: null,
|
discount: null,
|
||||||
sales: this.checkedLines()
|
sales: this.selectedValidSales()
|
||||||
};
|
};
|
||||||
|
|
||||||
this.$.editDiscountDialog.show(event);
|
this.$.editDiscountDialog.show(event);
|
||||||
|
@ -401,9 +312,7 @@ class Controller extends Section {
|
||||||
sale.discount = this.edit.discount;
|
sale.discount = this.edit.discount;
|
||||||
|
|
||||||
this.edit = null;
|
this.edit = null;
|
||||||
}).catch(e => {
|
}).finally(() => this.resetChanges());
|
||||||
this.vnApp.showError(e.message);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getNewPrice() {
|
getNewPrice() {
|
||||||
|
@ -427,21 +336,6 @@ class Controller extends Section {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* showEditDialog() {
|
|
||||||
this.edit = this.checkedLines();
|
|
||||||
this.$.editDialog.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
hideEditDialog() {
|
|
||||||
this.$.model.refresh();
|
|
||||||
this.$.editDialog.hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
hideEditPopover() {
|
|
||||||
this.$.model.refresh();
|
|
||||||
this.$.editPopover.hide();
|
|
||||||
} */
|
|
||||||
|
|
||||||
hasReserves() {
|
hasReserves() {
|
||||||
return this.sales.some(sale => {
|
return this.sales.some(sale => {
|
||||||
return sale.reserved == true;
|
return sale.reserved == true;
|
||||||
|
@ -463,7 +357,7 @@ class Controller extends Section {
|
||||||
}
|
}
|
||||||
|
|
||||||
setReserved(reserved) {
|
setReserved(reserved) {
|
||||||
let selectedSales = this.checkedLines();
|
let selectedSales = this.selectedValidSales();
|
||||||
let params = {sales: selectedSales, ticketFk: this.ticket.id, reserved: reserved};
|
let params = {sales: selectedSales, ticketFk: this.ticket.id, reserved: reserved};
|
||||||
|
|
||||||
let reservedSales = new Map();
|
let reservedSales = new Map();
|
||||||
|
@ -479,10 +373,7 @@ class Controller extends Section {
|
||||||
if (reservedSale)
|
if (reservedSale)
|
||||||
sale.reserved = reservedSale.reserved;
|
sale.reserved = reservedSale.reserved;
|
||||||
});
|
});
|
||||||
}).finally(() => {
|
}).finally(() => this.resetChanges());
|
||||||
if (this.newInstances().length === 0)
|
|
||||||
this.$.watcher.updateOriginalData();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
newOrderFromTicket() {
|
newOrderFromTicket() {
|
||||||
|
@ -499,7 +390,7 @@ class Controller extends Section {
|
||||||
const client = this.ticket.client;
|
const client = this.ticket.client;
|
||||||
const phone = address.mobile || address.phone ||
|
const phone = address.mobile || address.phone ||
|
||||||
client.mobile || client.phone;
|
client.mobile || client.phone;
|
||||||
const sales = this.checkedLines();
|
const sales = this.selectedValidSales();
|
||||||
const items = sales.map(sale => {
|
const items = sales.map(sale => {
|
||||||
return `${sale.quantity} ${sale.concept}`;
|
return `${sale.quantity} ${sale.concept}`;
|
||||||
});
|
});
|
||||||
|
@ -529,7 +420,7 @@ class Controller extends Section {
|
||||||
* Updates the sale quantity for existing instance
|
* Updates the sale quantity for existing instance
|
||||||
*/
|
*/
|
||||||
changeQuantity(sale) {
|
changeQuantity(sale) {
|
||||||
if (!sale.quantity) return;
|
if (!sale.itemFk || !sale.quantity) return;
|
||||||
|
|
||||||
if (!sale.id)
|
if (!sale.id)
|
||||||
return this.addSale(sale);
|
return this.addSale(sale);
|
||||||
|
@ -542,16 +433,12 @@ class Controller extends Section {
|
||||||
*/
|
*/
|
||||||
updateQuantity(sale) {
|
updateQuantity(sale) {
|
||||||
const data = {quantity: sale.quantity};
|
const data = {quantity: sale.quantity};
|
||||||
const query = `Sales/${sale.id}/updateQuantity`;
|
this.$http.post(`Sales/${sale.id}/updateQuantity`, data).then(() => {
|
||||||
this.$http.post(query, data).then(() => {
|
|
||||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
this.vnApp.showSuccess(this.$t('Data saved!'));
|
||||||
}).catch(e => {
|
}).catch(e => {
|
||||||
this.$.model.refresh();
|
this.$.model.refresh();
|
||||||
throw e;
|
throw e;
|
||||||
}).finally(() => {
|
}).finally(() => this.resetChanges());
|
||||||
if (this.newInstances().length === 0)
|
|
||||||
this.$.watcher.updateOriginalData();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -559,16 +446,12 @@ class Controller extends Section {
|
||||||
*/
|
*/
|
||||||
changeConcept(sale) {
|
changeConcept(sale) {
|
||||||
const data = {newConcept: sale.concept};
|
const data = {newConcept: sale.concept};
|
||||||
const query = `Sales/${sale.id}/updateConcept`;
|
this.$http.post(`Sales/${sale.id}/updateConcept`, data).then(() => {
|
||||||
this.$http.post(query, data).then(() => {
|
|
||||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
this.vnApp.showSuccess(this.$t('Data saved!'));
|
||||||
}).catch(e => {
|
}).catch(e => {
|
||||||
this.$.model.refresh();
|
this.$.model.refresh();
|
||||||
throw e;
|
throw e;
|
||||||
}).finally(() => {
|
}).finally(() => this.resetChanges());
|
||||||
if (this.newInstances().length === 0)
|
|
||||||
this.$.watcher.updateOriginalData();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -584,7 +467,6 @@ class Controller extends Section {
|
||||||
if (!res.data) return;
|
if (!res.data) return;
|
||||||
|
|
||||||
const newSale = res.data;
|
const newSale = res.data;
|
||||||
|
|
||||||
sale.id = newSale.id;
|
sale.id = newSale.id;
|
||||||
sale.image = newSale.item.image;
|
sale.image = newSale.item.image;
|
||||||
sale.subName = newSale.item.subName;
|
sale.subName = newSale.item.subName;
|
||||||
|
@ -595,26 +477,22 @@ class Controller extends Section {
|
||||||
sale.item = newSale.item;
|
sale.item = newSale.item;
|
||||||
|
|
||||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
this.vnApp.showSuccess(this.$t('Data saved!'));
|
||||||
}).finally(() => {
|
}).finally(() => this.resetChanges());
|
||||||
if (this.newInstances().length === 0)
|
|
||||||
this.$.watcher.updateOriginalData();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isTicketEditable() {
|
isTicketEditable() {
|
||||||
this.$http.get(`Tickets/${this.$state.params.id}/isEditable`).then(res => {
|
this.$http.get(`Tickets/${this.$state.params.id}/isEditable`)
|
||||||
this.isEditable = res.data;
|
.then(res => this.isEditable = res.data);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isTicketLocked() {
|
isTicketLocked() {
|
||||||
this.$http.get(`Tickets/${this.$state.params.id}/isLocked`).then(res => {
|
this.$http.get(`Tickets/${this.$state.params.id}/isLocked`)
|
||||||
this.isLocked = res.data;
|
.then(res => this.isLocked = res.data);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
calculateSalePrice() {
|
calculateSalePrice() {
|
||||||
const sale = this.checkedLines()[0];
|
const sale = this.selectedValidSales()[0];
|
||||||
|
if (!sale) return;
|
||||||
const query = `Sales/${sale.id}/recalculatePrice`;
|
const query = `Sales/${sale.id}/recalculatePrice`;
|
||||||
this.$http.post(query).then(() => {
|
this.$http.post(query).then(() => {
|
||||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
this.vnApp.showSuccess(this.$t('Data saved!'));
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
New price: Nuevo precio
|
New price: Nuevo precio
|
||||||
Add item: Añadir artículo
|
Add item: Añadir artículo
|
||||||
|
Add item to basket: Añadir artículo a la cesta
|
||||||
Add turn: Añadir a turno
|
Add turn: Añadir a turno
|
||||||
Delete ticket: Eliminar ticket
|
Delete ticket: Eliminar ticket
|
||||||
Mark as reserved: Marcar como reservado
|
Mark as reserved: Marcar como reservado
|
||||||
|
|
|
@ -166,22 +166,20 @@
|
||||||
<vn-table model="model">
|
<vn-table model="model">
|
||||||
<vn-thead>
|
<vn-thead>
|
||||||
<vn-tr>
|
<vn-tr>
|
||||||
<vn-th shrink></vn-th>
|
|
||||||
<vn-th class="identifier" number shrink>Id</vn-th>
|
|
||||||
<vn-th number shrink>Quantity</vn-th>
|
<vn-th number shrink>Quantity</vn-th>
|
||||||
<vn-th expand>Description</vn-th>
|
<vn-th expand>Description</vn-th>
|
||||||
<vn-th number shrink>Price</vn-th>
|
<vn-th number shrink>Price</vn-th>
|
||||||
<vn-th class="tax-class">Tax class</vn-th>
|
<vn-th class="tax-class">Tax class</vn-th>
|
||||||
|
<vn-th number>Amount</vn-th>
|
||||||
</vn-tr>
|
</vn-tr>
|
||||||
</vn-thead>
|
</vn-thead>
|
||||||
<vn-tbody>
|
<vn-tbody>
|
||||||
<vn-tr ng-repeat="service in $ctrl.summary.services">
|
<vn-tr ng-repeat="service in $ctrl.summary.services">
|
||||||
<vn-td></vn-td>
|
|
||||||
<vn-td class="identifier" number shrink>{{::service.id}}</vn-td>
|
|
||||||
<vn-td number shrink>{{::service.quantity}}</vn-td>
|
<vn-td number shrink>{{::service.quantity}}</vn-td>
|
||||||
<vn-td expand>{{::service.description}}</vn-td>
|
<vn-td expand>{{::service.description}}</vn-td>
|
||||||
<vn-td number shrink>{{::service.price}}</vn-td>
|
<vn-td number shrink>{{::service.price | currency: 'EUR':2}}</vn-td>
|
||||||
<vn-td class="tax-class">{{::service.taxClass.description}}</vn-td>
|
<vn-td class="tax-class"><span title="{{::service.taxClass.description}}">{{::service.taxClass.description}}</span></vn-td>
|
||||||
|
<vn-td number>{{::service.quantity * service.price | currency: 'EUR':2}}</vn-td>
|
||||||
</vn-tr>
|
</vn-tr>
|
||||||
</vn-tbody>
|
</vn-tbody>
|
||||||
</vn-table>
|
</vn-table>
|
||||||
|
|
|
@ -53,7 +53,7 @@ vn-ticket-summary .summary {
|
||||||
|
|
||||||
.vn-table > vn-thead .tax-class,
|
.vn-table > vn-thead .tax-class,
|
||||||
.vn-table > vn-tbody .tax-class {
|
.vn-table > vn-tbody .tax-class {
|
||||||
min-width: 176px;
|
min-width: 90px;
|
||||||
width: 1px;
|
width: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethod('deleteZone', {
|
Self.remoteMethodCtx('deleteZone', {
|
||||||
description: 'Delete a zone',
|
description: 'Delete a zone',
|
||||||
accessType: 'WRITE',
|
accessType: 'WRITE',
|
||||||
accepts: {
|
accepts: {
|
||||||
|
@ -18,18 +18,44 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.deleteZone = async id => {
|
Self.deleteZone = async(ctx, id) => {
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
|
const token = ctx.req.accessToken;
|
||||||
|
const userId = token.userId;
|
||||||
|
const today = new Date();
|
||||||
|
today.setHours(0, 0, 0, 0);
|
||||||
const tx = await Self.beginTransaction({});
|
const tx = await Self.beginTransaction({});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
const filter = {where: {zoneFk: id}};
|
const filter = {
|
||||||
|
where: {
|
||||||
|
zoneFk: id
|
||||||
|
},
|
||||||
|
include: {
|
||||||
|
relation: 'state',
|
||||||
|
scope: {
|
||||||
|
fields: ['id', 'alertLevel', 'code']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
const promises = [];
|
const promises = [];
|
||||||
|
|
||||||
const ticketList = await models.Ticket.find(filter, options);
|
const ticketList = await models.Ticket.find(filter, options);
|
||||||
|
const fixingState = await models.State.findOne({where: {code: 'FIXING'}}, options);
|
||||||
|
const worker = await models.Worker.findOne({
|
||||||
|
where: {userFk: userId}
|
||||||
|
}, options);
|
||||||
|
|
||||||
ticketList.forEach(ticket => {
|
ticketList.forEach(ticket => {
|
||||||
promises.push(ticket.updateAttributes({zoneFk: null}, options));
|
promises.push(ticket.updateAttributes({zoneFk: null}, options));
|
||||||
|
|
||||||
|
if (ticket.state().alertLevel == 0 && ticket.shipped >= today) {
|
||||||
|
promises.push(models.TicketTracking.create({
|
||||||
|
ticketFk: ticket.id,
|
||||||
|
stateFk: fixingState.id,
|
||||||
|
workerFk: worker.id
|
||||||
|
}, options));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
await Promise.all(promises);
|
await Promise.all(promises);
|
||||||
await models.Zone.destroyById(id, options);
|
await models.Zone.destroyById(id, options);
|
||||||
|
|
|
@ -1,16 +1,21 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const app = require('vn-loopback/server/server');
|
||||||
|
|
||||||
// 2302
|
|
||||||
describe('zone deletezone()', () => {
|
describe('zone deletezone()', () => {
|
||||||
let zoneId = 9;
|
let zoneId = 9;
|
||||||
let originalZoneTickets;
|
let originalZoneTickets;
|
||||||
let originalZone;
|
let originalZone;
|
||||||
let originalZoneIncluded;
|
let originalZoneIncluded;
|
||||||
|
let ticketsId;
|
||||||
|
let originalTicketsState;
|
||||||
|
|
||||||
beforeAll(async done => {
|
beforeAll(async done => {
|
||||||
originalZone = await app.models.Zone.findById(zoneId);
|
originalZone = await app.models.Zone.findById(zoneId);
|
||||||
originalZoneTickets = await app.models.Ticket.find({where: {zoneFk: zoneId}});
|
originalZoneTickets = await app.models.Ticket.find({where: {zoneFk: zoneId}});
|
||||||
originalZoneIncluded = await app.models.ZoneIncluded.find({where: {zoneFk: zoneId}});
|
originalZoneIncluded = await app.models.ZoneIncluded.find({where: {zoneFk: zoneId}});
|
||||||
|
ticketsId = originalZoneTickets.map(originalZoneTickets => originalZoneTickets.id);
|
||||||
|
originalTicketsState = await app.models.TicketState.find({where: {
|
||||||
|
ticketFk: {inq: ticketsId},
|
||||||
|
code: 'FIXING'}});
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -27,13 +32,20 @@ describe('zone deletezone()', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should delete a zone and update their tickets', async() => {
|
it('should delete a zone and update their tickets', async() => {
|
||||||
await app.models.Zone.deleteZone(zoneId);
|
const ctx = {req: {accessToken: {userId: 9}}};
|
||||||
|
await app.models.Zone.deleteZone(ctx, zoneId);
|
||||||
|
|
||||||
let updatedZone = await app.models.Zone.findById(zoneId);
|
let updatedZone = await app.models.Zone.findById(zoneId);
|
||||||
let zoneUpdatedTicket = await app.models.Ticket.findById(originalZoneTickets[0].id);
|
let zoneUpdatedTicket = await app.models.Ticket.findById(originalZoneTickets[0].id);
|
||||||
|
let ticketsId = originalZoneTickets.map(originalZoneTickets => originalZoneTickets.id);
|
||||||
|
|
||||||
|
let updatedTicketState = await app.models.TicketState.find({where: {
|
||||||
|
ticketFk: {inq: ticketsId},
|
||||||
|
code: 'FIXING'}});
|
||||||
|
|
||||||
expect(updatedZone).toBeNull();
|
expect(updatedZone).toBeNull();
|
||||||
expect(zoneUpdatedTicket.zoneFk).not.toBe(zoneId);
|
expect(zoneUpdatedTicket.zoneFk).not.toBe(zoneId);
|
||||||
|
expect(originalTicketsState.length).not.toBeGreaterThan(updatedTicketState.length);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,7 @@ class Controller extends Component {
|
||||||
let events = value.events;
|
let events = value.events;
|
||||||
|
|
||||||
if (events) {
|
if (events) {
|
||||||
for (event of events) {
|
for (let event of events) {
|
||||||
event.dated = toStamp(event.dated);
|
event.dated = toStamp(event.dated);
|
||||||
event.ended = toStamp(event.ended);
|
event.ended = toStamp(event.ended);
|
||||||
event.started = toStamp(event.started);
|
event.started = toStamp(event.started);
|
||||||
|
|
|
@ -0,0 +1,155 @@
|
||||||
|
import './index';
|
||||||
|
import crudModel from 'core/mocks/crud-model';
|
||||||
|
|
||||||
|
describe('component vnZoneCalendar', () => {
|
||||||
|
let $scope;
|
||||||
|
let controller;
|
||||||
|
let $httpBackend;
|
||||||
|
|
||||||
|
beforeEach(ngModule('zone'));
|
||||||
|
|
||||||
|
beforeEach(angular.mock.inject(($componentController, $rootScope, _$httpBackend_) => {
|
||||||
|
$httpBackend = _$httpBackend_;
|
||||||
|
$scope = $rootScope.$new();
|
||||||
|
const $element = angular.element(`<vn-zone-calendar></vn-zone-calendar>`);
|
||||||
|
controller = $componentController('vnZoneCalendar', {$element, $scope});
|
||||||
|
controller.$.model = crudModel;
|
||||||
|
controller.zone = {id: 1};
|
||||||
|
controller.days = [];
|
||||||
|
controller.exclusions = [];
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('date() setter', () => {
|
||||||
|
it('should set the month property and then call the refreshEvents() method', () => {
|
||||||
|
jest.spyOn(controller, 'refreshEvents').mockReturnThis();
|
||||||
|
|
||||||
|
controller.date = new Date();
|
||||||
|
|
||||||
|
expect(controller.refreshEvents).toHaveBeenCalledWith();
|
||||||
|
expect(controller.months.length).toEqual(4);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('step()', () => {
|
||||||
|
it('should set the date month to 4 months backwards', () => {
|
||||||
|
const now = new Date();
|
||||||
|
now.setMonth(now.getMonth() - 4);
|
||||||
|
|
||||||
|
controller.step(-1);
|
||||||
|
|
||||||
|
const expectedMonth = now.getMonth();
|
||||||
|
const currentMonth = controller.date.getMonth();
|
||||||
|
|
||||||
|
expect(currentMonth).toEqual(expectedMonth);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set the date month to 4 months forwards', () => {
|
||||||
|
const now = new Date();
|
||||||
|
now.setMonth(now.getMonth() + 4);
|
||||||
|
|
||||||
|
controller.step(1);
|
||||||
|
|
||||||
|
const expectedMonth = now.getMonth();
|
||||||
|
const currentMonth = controller.date.getMonth();
|
||||||
|
|
||||||
|
expect(currentMonth).toEqual(expectedMonth);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('data() setter', () => {
|
||||||
|
it('should set the events and exclusions and then call the refreshEvents() method', () => {
|
||||||
|
jest.spyOn(controller, 'refreshEvents').mockReturnThis();
|
||||||
|
|
||||||
|
controller.data = {
|
||||||
|
exclusions: [{
|
||||||
|
dated: new Date()
|
||||||
|
}],
|
||||||
|
events: [{
|
||||||
|
dated: new Date()
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(controller.refreshEvents).toHaveBeenCalledWith();
|
||||||
|
expect(controller.events).toBeDefined();
|
||||||
|
expect(controller.events.length).toEqual(1);
|
||||||
|
expect(controller.exclusions).toBeDefined();
|
||||||
|
expect(Object.keys(controller.exclusions).length).toEqual(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('refreshEvents()', () => {
|
||||||
|
it('should fill the days property with the events.', () => {
|
||||||
|
controller.data = [];
|
||||||
|
controller.firstDay = new Date();
|
||||||
|
|
||||||
|
const lastDay = new Date();
|
||||||
|
lastDay.setDate(lastDay.getDate() + 10);
|
||||||
|
controller.lastDay = lastDay;
|
||||||
|
|
||||||
|
const firstEventStamp = controller.firstDay.getTime();
|
||||||
|
const lastEventStamp = controller.lastDay.getTime();
|
||||||
|
controller.events = [{
|
||||||
|
type: 'day',
|
||||||
|
dated: firstEventStamp
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'day',
|
||||||
|
dated: lastEventStamp
|
||||||
|
}];
|
||||||
|
|
||||||
|
controller.refreshEvents();
|
||||||
|
const expectedDays = Object.keys(controller.days);
|
||||||
|
|
||||||
|
expect(expectedDays.length).toEqual(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('onSelection()', () => {
|
||||||
|
it('should call the emit() method', () => {
|
||||||
|
jest.spyOn(controller, 'emit');
|
||||||
|
|
||||||
|
const $event = {};
|
||||||
|
const $days = [new Date()];
|
||||||
|
const $type = 'day';
|
||||||
|
const $weekday = 1;
|
||||||
|
|
||||||
|
controller.onSelection($event, $days, $type, $weekday);
|
||||||
|
|
||||||
|
expect(controller.emit).toHaveBeenCalledWith('selection',
|
||||||
|
{
|
||||||
|
$days: $days,
|
||||||
|
$event: {},
|
||||||
|
$events: [],
|
||||||
|
$exclusions: [],
|
||||||
|
$type: 'day',
|
||||||
|
$weekday: 1
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('hasEvents()', () => {
|
||||||
|
it('should return true for an existing event on a date', () => {
|
||||||
|
const dated = new Date();
|
||||||
|
|
||||||
|
controller.days[dated.getTime()] = true;
|
||||||
|
|
||||||
|
const result = controller.hasEvents(dated);
|
||||||
|
|
||||||
|
expect(result).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getClass()', () => {
|
||||||
|
it('should return the className "excluded" for an excluded date', () => {
|
||||||
|
const dated = new Date();
|
||||||
|
|
||||||
|
controller.exclusions = [];
|
||||||
|
controller.exclusions[dated.getTime()] = true;
|
||||||
|
|
||||||
|
const result = controller.getClass(dated);
|
||||||
|
|
||||||
|
expect(result).toEqual('excluded');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -33,6 +33,7 @@ class Controller extends Descriptor {
|
||||||
this.vnApp.showSuccess(this.$t('Zone deleted'));
|
this.vnApp.showSuccess(this.$t('Zone deleted'));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onCloneAccept() {
|
onCloneAccept() {
|
||||||
return this.$http.post(`Zones/${this.id}/clone`).
|
return this.$http.post(`Zones/${this.id}/clone`).
|
||||||
then(res => this.$state.go('zone.card.basicData', {id: res.data.id}));
|
then(res => this.$state.go('zone.card.basicData', {id: res.data.id}));
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
import './index.js';
|
||||||
|
|
||||||
|
describe('Zone descriptor', () => {
|
||||||
|
let $httpBackend;
|
||||||
|
let controller;
|
||||||
|
let $element;
|
||||||
|
|
||||||
|
beforeEach(ngModule('zone'));
|
||||||
|
|
||||||
|
beforeEach(angular.mock.inject(($componentController, _$httpBackend_) => {
|
||||||
|
$httpBackend = _$httpBackend_;
|
||||||
|
$element = angular.element('<vn-zone-descriptor></vn-zone-descriptor');
|
||||||
|
controller = $componentController('vnZoneDescriptor', {$element});
|
||||||
|
controller.zone = {id: 1};
|
||||||
|
controller.id = 1;
|
||||||
|
controller.$.deleteZone = {
|
||||||
|
hide: () => {},
|
||||||
|
show: () => {}
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('onDelete()', () => {
|
||||||
|
it('should make an HTTP POST query and then call the deleteZone show() method', () => {
|
||||||
|
jest.spyOn(controller.$.deleteZone, 'show');
|
||||||
|
|
||||||
|
const expectedData = [{id: 16}];
|
||||||
|
$httpBackend.when('GET', 'Tickets').respond(expectedData);
|
||||||
|
controller.onDelete();
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.$.deleteZone.show).toHaveBeenCalledWith();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should make an HTTP POST query and then call the deleteZone() method', () => {
|
||||||
|
jest.spyOn(controller, 'deleteZone').mockReturnThis();
|
||||||
|
|
||||||
|
const expectedData = [];
|
||||||
|
$httpBackend.when('GET', 'Tickets').respond(expectedData);
|
||||||
|
controller.onDelete();
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.deleteZone).toHaveBeenCalledWith();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('deleteZone()', () => {
|
||||||
|
it('should make an HTTP POST query and then call the showMessage() method', () => {
|
||||||
|
jest.spyOn(controller.$state, 'go').mockReturnThis();
|
||||||
|
jest.spyOn(controller.vnApp, 'showSuccess');
|
||||||
|
|
||||||
|
const stateName = 'zone.index';
|
||||||
|
$httpBackend.when('POST', 'Zones/1/deleteZone').respond(200);
|
||||||
|
controller.deleteZone();
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.$state.go).toHaveBeenCalledWith(stateName);
|
||||||
|
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Zone deleted');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('onCloneAccept()', () => {
|
||||||
|
it('should make an HTTP POST query and then call the state go() method', () => {
|
||||||
|
jest.spyOn(controller.$state, 'go').mockReturnThis();
|
||||||
|
|
||||||
|
const stateName = 'zone.card.basicData';
|
||||||
|
const expectedData = {id: 1};
|
||||||
|
$httpBackend.when('POST', 'Zones/1/clone').respond(expectedData);
|
||||||
|
controller.onCloneAccept();
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.$state.go).toHaveBeenCalledWith(stateName, expectedData);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -6,12 +6,20 @@ class Controller extends Section {
|
||||||
super($element, $);
|
super($element, $);
|
||||||
this.vnWeekDays = vnWeekDays;
|
this.vnWeekDays = vnWeekDays;
|
||||||
this.editMode = 'include';
|
this.editMode = 'include';
|
||||||
|
}
|
||||||
|
|
||||||
this.path = `Zones/${this.$params.id}/events`;
|
$onInit() {
|
||||||
this.exclusionsPath = `Zones/${this.$params.id}/exclusions`;
|
|
||||||
this.refresh();
|
this.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get path() {
|
||||||
|
return `Zones/${this.$params.id}/events`;
|
||||||
|
}
|
||||||
|
|
||||||
|
get exclusionsPath() {
|
||||||
|
return `Zones/${this.$params.id}/exclusions`;
|
||||||
|
}
|
||||||
|
|
||||||
refresh() {
|
refresh() {
|
||||||
let data = {};
|
let data = {};
|
||||||
this.$q.all([
|
this.$q.all([
|
||||||
|
|
|
@ -0,0 +1,216 @@
|
||||||
|
import './index';
|
||||||
|
|
||||||
|
describe('component vnZoneEvents', () => {
|
||||||
|
let $scope;
|
||||||
|
let controller;
|
||||||
|
let $httpBackend;
|
||||||
|
|
||||||
|
beforeEach(ngModule('zone'));
|
||||||
|
|
||||||
|
beforeEach(angular.mock.inject(($componentController, $rootScope, _$httpBackend_) => {
|
||||||
|
$httpBackend = _$httpBackend_;
|
||||||
|
$scope = $rootScope.$new();
|
||||||
|
const $element = angular.element(`<vn-zone-events></vn-zone-events>`);
|
||||||
|
controller = $componentController('vnZoneEvents', {$element, $scope});
|
||||||
|
controller.$params = {id: 1};
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('refresh()', () => {
|
||||||
|
it('should set the zone and then call both getSummary() and getWarehouses()', () => {
|
||||||
|
$httpBackend.expectGET(`Zones/1/events`).respond({id: 1});
|
||||||
|
$httpBackend.expectGET(`Zones/1/exclusions`).respond({id: 1});
|
||||||
|
controller.refresh();
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
const data = controller.$.data;
|
||||||
|
|
||||||
|
expect(data.events).toBeDefined();
|
||||||
|
expect(data.exclusions).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('onSelection()', () => {
|
||||||
|
it('should call the edit() method', () => {
|
||||||
|
jest.spyOn(controller, 'edit').mockReturnThis();
|
||||||
|
|
||||||
|
const weekday = {};
|
||||||
|
const days = [];
|
||||||
|
const type = 'EventType';
|
||||||
|
const events = [{name: 'Event'}];
|
||||||
|
const exclusions = [];
|
||||||
|
controller.editMode = 'include';
|
||||||
|
controller.onSelection(days, type, weekday, events, exclusions);
|
||||||
|
|
||||||
|
expect(controller.edit).toHaveBeenCalledWith({name: 'Event'});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call the create() method', () => {
|
||||||
|
jest.spyOn(controller, 'create').mockReturnThis();
|
||||||
|
|
||||||
|
const weekday = {dated: new Date()};
|
||||||
|
const days = [weekday];
|
||||||
|
const type = 'EventType';
|
||||||
|
const events = [];
|
||||||
|
const exclusions = [];
|
||||||
|
controller.editMode = 'include';
|
||||||
|
controller.onSelection(days, type, weekday, events, exclusions);
|
||||||
|
|
||||||
|
expect(controller.create).toHaveBeenCalledWith(type, days, weekday);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call the exclusionDelete() method', () => {
|
||||||
|
jest.spyOn(controller, 'exclusionDelete').mockReturnThis();
|
||||||
|
|
||||||
|
const weekday = {};
|
||||||
|
const days = [];
|
||||||
|
const type = 'EventType';
|
||||||
|
const events = [];
|
||||||
|
const exclusions = [{id: 1}];
|
||||||
|
controller.editMode = 'delete';
|
||||||
|
controller.onSelection(days, type, weekday, events, exclusions);
|
||||||
|
|
||||||
|
expect(controller.exclusionDelete).toHaveBeenCalledWith(exclusions);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call the exclusionCreate() method', () => {
|
||||||
|
jest.spyOn(controller, 'exclusionCreate').mockReturnThis();
|
||||||
|
|
||||||
|
const weekday = {};
|
||||||
|
const days = [{dated: new Date()}];
|
||||||
|
const type = 'EventType';
|
||||||
|
const events = [];
|
||||||
|
const exclusions = [];
|
||||||
|
controller.editMode = 'delete';
|
||||||
|
controller.onSelection(days, type, weekday, events, exclusions);
|
||||||
|
|
||||||
|
expect(controller.exclusionCreate).toHaveBeenCalledWith(days);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('create()', () => {
|
||||||
|
it('shoud set the selected property and then call the dialog show() method', () => {
|
||||||
|
controller.$.dialog = {show: jest.fn()};
|
||||||
|
|
||||||
|
const type = 'weekday';
|
||||||
|
const days = [new Date()];
|
||||||
|
const weekday = 1;
|
||||||
|
controller.create(type, days, weekday);
|
||||||
|
|
||||||
|
const selection = controller.selected;
|
||||||
|
const firstWeekday = selection.wdays[weekday];
|
||||||
|
|
||||||
|
expect(selection.type).toEqual('indefinitely');
|
||||||
|
expect(firstWeekday).toBeTruthy();
|
||||||
|
expect(controller.isNew).toBeTruthy();
|
||||||
|
expect(controller.$.dialog.show).toHaveBeenCalledWith();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shoud set the selected property with the first day and then call the dialog show() method', () => {
|
||||||
|
controller.$.dialog = {show: jest.fn()};
|
||||||
|
|
||||||
|
const type = 'nonListedType';
|
||||||
|
const days = [new Date()];
|
||||||
|
const weekday = 1;
|
||||||
|
controller.create(type, days, weekday);
|
||||||
|
|
||||||
|
const selection = controller.selected;
|
||||||
|
|
||||||
|
expect(selection.type).toEqual('day');
|
||||||
|
expect(selection.dated).toEqual(days[0]);
|
||||||
|
expect(controller.isNew).toBeTruthy();
|
||||||
|
expect(controller.$.dialog.show).toHaveBeenCalledWith();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('onIncludeResponse()', () => {
|
||||||
|
it('shoud call the onDelete() method', () => {
|
||||||
|
jest.spyOn(controller, 'onDelete').mockReturnValue(
|
||||||
|
new Promise(accept => accept())
|
||||||
|
);
|
||||||
|
|
||||||
|
controller.selected = {id: 1};
|
||||||
|
controller.onIncludeResponse('delete');
|
||||||
|
|
||||||
|
expect(controller.onDelete).toHaveBeenCalledWith(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shoud make an HTTP POST query to create a new one and then call the refresh() method', () => {
|
||||||
|
jest.spyOn(controller, 'refresh').mockReturnThis();
|
||||||
|
|
||||||
|
controller.selected = {id: 1};
|
||||||
|
controller.isNew = true;
|
||||||
|
|
||||||
|
$httpBackend.when('POST', `Zones/1/events`).respond(200);
|
||||||
|
controller.onIncludeResponse('accept');
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.refresh).toHaveBeenCalledWith();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shoud make an HTTP PUT query and then call the refresh() method', () => {
|
||||||
|
jest.spyOn(controller, 'refresh').mockReturnThis();
|
||||||
|
|
||||||
|
controller.selected = {id: 1};
|
||||||
|
controller.isNew = false;
|
||||||
|
|
||||||
|
const eventId = 1;
|
||||||
|
$httpBackend.when('PUT', `Zones/1/events/${eventId}`).respond(200);
|
||||||
|
controller.onIncludeResponse('accept');
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.refresh).toHaveBeenCalledWith();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('onDeleteResponse()', () => {
|
||||||
|
it('shoud make an HTTP DELETE query and then call the refresh() method', () => {
|
||||||
|
jest.spyOn(controller, 'refresh').mockReturnThis();
|
||||||
|
|
||||||
|
const eventId = 1;
|
||||||
|
$httpBackend.expect('DELETE', `Zones/1/events/1`).respond({id: 1});
|
||||||
|
controller.onDeleteResponse('accept', eventId);
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.refresh).toHaveBeenCalledWith();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('exclusionCreate()', () => {
|
||||||
|
it('shoud make an HTTP POST query and then call the refresh() method', () => {
|
||||||
|
jest.spyOn(controller, 'refresh').mockReturnThis();
|
||||||
|
|
||||||
|
const dates = [new Date()];
|
||||||
|
$httpBackend.expect('POST', `Zones/1/exclusions`).respond({id: 1});
|
||||||
|
controller.exclusionCreate(dates);
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.refresh).toHaveBeenCalledWith();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('exclusionDelete()', () => {
|
||||||
|
it('shoud make an HTTP DELETE query once and then call the refresh() method', () => {
|
||||||
|
jest.spyOn(controller, 'refresh').mockReturnThis();
|
||||||
|
|
||||||
|
const exclusions = [{id: 1}];
|
||||||
|
const firstExclusionId = 1;
|
||||||
|
$httpBackend.when('DELETE', `Zones/1/exclusions/${firstExclusionId}`).respond(200);
|
||||||
|
controller.exclusionDelete(exclusions);
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.refresh).toHaveBeenCalledWith();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shoud make an HTTP DELETE query for every event and then call the refresh() method', () => {
|
||||||
|
jest.spyOn(controller, 'refresh').mockReturnThis();
|
||||||
|
jest.spyOn(controller.$http, 'delete').mockReturnValue(200);
|
||||||
|
|
||||||
|
const exclusions = [{id: 1}, {id: 2}, {id: 3}, {id: 4}];
|
||||||
|
controller.exclusionDelete(exclusions);
|
||||||
|
$scope.$apply();
|
||||||
|
|
||||||
|
expect(controller.$http.delete).toHaveBeenCalledTimes(4);
|
||||||
|
expect(controller.refresh).toHaveBeenCalledWith();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,50 @@
|
||||||
|
import './index';
|
||||||
|
import crudModel from 'core/mocks/crud-model';
|
||||||
|
|
||||||
|
describe('component vnZoneLocation', () => {
|
||||||
|
let $scope;
|
||||||
|
let controller;
|
||||||
|
let $httpBackend;
|
||||||
|
|
||||||
|
beforeEach(ngModule('zone'));
|
||||||
|
|
||||||
|
beforeEach(angular.mock.inject(($componentController, $rootScope, _$httpBackend_) => {
|
||||||
|
$httpBackend = _$httpBackend_;
|
||||||
|
$scope = $rootScope.$new();
|
||||||
|
const $element = angular.element(`<vn-zone-location></vn-zone-location>`);
|
||||||
|
controller = $componentController('vnZoneLocation', {$element, $scope});
|
||||||
|
controller.$.model = crudModel;
|
||||||
|
controller.zone = {id: 1};
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('onSearch()', () => {
|
||||||
|
it('should call the applyFilter() method and then set the data', () => {
|
||||||
|
controller.$.treeview = {};
|
||||||
|
controller.onSearch({});
|
||||||
|
|
||||||
|
const treeviewData = controller.$.treeview.data;
|
||||||
|
|
||||||
|
expect(treeviewData).toBeDefined();
|
||||||
|
expect(treeviewData.length).toEqual(3);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('onFetch()', () => {
|
||||||
|
it('should call the applyFilter() method and then return the model data', () => {
|
||||||
|
const result = controller.onFetch();
|
||||||
|
|
||||||
|
expect(result.length).toEqual(3);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('onSelection()', () => {
|
||||||
|
it('should make an HTTP POST query', () => {
|
||||||
|
const item = {id: 123};
|
||||||
|
|
||||||
|
const expectedParams = {geoId: 123, isIncluded: true};
|
||||||
|
$httpBackend.expect('POST', `zones/1/toggleIsIncluded`, expectedParams).respond(200);
|
||||||
|
controller.onSelection(true, item);
|
||||||
|
$httpBackend.flush();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -51,4 +51,26 @@ describe('component vnZoneSummary', () => {
|
||||||
expect(controller.summary).toBeDefined();
|
expect(controller.summary).toBeDefined();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('getWarehouses()', () => {
|
||||||
|
it('should make an HTTP get query and then store data on the controller', () => {
|
||||||
|
controller._zone = {id: 1};
|
||||||
|
const params = {
|
||||||
|
filter: {
|
||||||
|
include: {
|
||||||
|
relation: 'warehouse',
|
||||||
|
fields: ['name']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const serializedParams = $httpParamSerializer(params);
|
||||||
|
const query = `Zones/1/warehouses?${serializedParams}`;
|
||||||
|
$httpBackend.expect('GET', query).respond([{id: 1}]);
|
||||||
|
controller.getWarehouses();
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.zoneWarehouses.length).toEqual(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,13 +2,14 @@ import ngModule from '../module';
|
||||||
import Section from 'salix/components/section';
|
import Section from 'salix/components/section';
|
||||||
|
|
||||||
class Controller extends Section {
|
class Controller extends Section {
|
||||||
constructor($element, $) {
|
$onInit() {
|
||||||
super($element, $);
|
|
||||||
|
|
||||||
this.path = `Zones/${this.$params.id}/warehouses`;
|
|
||||||
this.refresh();
|
this.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get path() {
|
||||||
|
return `Zones/${this.$params.id}/warehouses`;
|
||||||
|
}
|
||||||
|
|
||||||
refresh() {
|
refresh() {
|
||||||
let filter = {include: 'warehouse'};
|
let filter = {include: 'warehouse'};
|
||||||
this.$http.get(this.path, {params: {filter}})
|
this.$http.get(this.path, {params: {filter}})
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
import './index.js';
|
||||||
|
|
||||||
|
describe('Zone warehouses', () => {
|
||||||
|
let $httpBackend;
|
||||||
|
let $httpParamSerializer;
|
||||||
|
let controller;
|
||||||
|
let $element;
|
||||||
|
|
||||||
|
beforeEach(ngModule('zone'));
|
||||||
|
|
||||||
|
beforeEach(angular.mock.inject(($componentController, _$httpBackend_, _$httpParamSerializer_) => {
|
||||||
|
$httpBackend = _$httpBackend_;
|
||||||
|
$httpParamSerializer = _$httpParamSerializer_;
|
||||||
|
$element = angular.element('<vn-zone-warehouses></vn-zone-warehouses');
|
||||||
|
controller = $componentController('vnZoneWarehouses', {$element});
|
||||||
|
controller.zone = {id: 1};
|
||||||
|
controller.$params = {id: 1};
|
||||||
|
controller.$.dialog = {hide: jest.fn()};
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('refresh()', () => {
|
||||||
|
it('should make an HTTP GET query and then set the data', () => {
|
||||||
|
const params = {filter: {include: 'warehouse'}};
|
||||||
|
const serializedParams = $httpParamSerializer(params);
|
||||||
|
const path = `Zones/1/warehouses?${serializedParams}`;
|
||||||
|
$httpBackend.expect('GET', path).respond([{id: 1, name: 'Warehouse one'}]);
|
||||||
|
controller.refresh();
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.$.data).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('onSave()', () => {
|
||||||
|
it('should make an HTTP POST query and then call the refresh() method', () => {
|
||||||
|
jest.spyOn(controller, 'refresh').mockReturnThis();
|
||||||
|
|
||||||
|
$httpBackend.expect('POST', `Zones/1/warehouses`).respond(200);
|
||||||
|
controller.onSave('accept');
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.selected).toBeNull();
|
||||||
|
expect(controller.isNew).toBeNull();
|
||||||
|
expect(controller.$.dialog.hide).toHaveBeenCalledWith();
|
||||||
|
expect(controller.refresh).toHaveBeenCalledWith();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('delete()', () => {
|
||||||
|
it('should make an HTTP DELETE query and then set deleteRow property to null value', () => {
|
||||||
|
controller.deleteRow = {id: 1};
|
||||||
|
controller.$.data = [{id: 1}];
|
||||||
|
$httpBackend.expect('DELETE', `Zones/1/warehouses/1`).respond(200);
|
||||||
|
controller.delete();
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.deleteRow).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
File diff suppressed because it is too large
Load Diff
|
@ -42,7 +42,7 @@
|
||||||
"@babel/preset-env": "^7.7.7",
|
"@babel/preset-env": "^7.7.7",
|
||||||
"@babel/register": "^7.7.7",
|
"@babel/register": "^7.7.7",
|
||||||
"angular-mocks": "^1.7.9",
|
"angular-mocks": "^1.7.9",
|
||||||
"babel-jest": "^24.9.0",
|
"babel-jest": "^26.0.1",
|
||||||
"babel-loader": "^8.0.6",
|
"babel-loader": "^8.0.6",
|
||||||
"babel-preset-es2015": "^6.24.1",
|
"babel-preset-es2015": "^6.24.1",
|
||||||
"css-loader": "^2.1.0",
|
"css-loader": "^2.1.0",
|
||||||
|
@ -70,7 +70,7 @@
|
||||||
"jasmine": "^3.5.0",
|
"jasmine": "^3.5.0",
|
||||||
"jasmine-reporters": "^2.3.2",
|
"jasmine-reporters": "^2.3.2",
|
||||||
"jasmine-spec-reporter": "^4.2.1",
|
"jasmine-spec-reporter": "^4.2.1",
|
||||||
"jest": "^24.9.0",
|
"jest": "^26.0.1",
|
||||||
"jest-junit": "^8.0.0",
|
"jest-junit": "^8.0.0",
|
||||||
"json-loader": "^0.5.7",
|
"json-loader": "^0.5.7",
|
||||||
"merge-stream": "^1.0.1",
|
"merge-stream": "^1.0.1",
|
||||||
|
|
Loading…
Reference in New Issue