merge
gitea/salix/dev There was a failure building this commit Details

This commit is contained in:
Carlos Jimenez Ruiz 2019-09-06 11:45:55 +02:00
commit 56c291a160
44 changed files with 417 additions and 102 deletions

View File

@ -21,6 +21,9 @@
},
"isManaged":{
"type": "boolean"
},
"hasStowaway":{
"type": "boolean"
}
},
"acls": [

View File

@ -0,0 +1,26 @@
ALTER TABLE `vn2008`.`warehouse`
ADD COLUMN `hasStowaway` TINYINT(1) NOT NULL DEFAULT 0 AFTER `hasConfectionTeam`;
-- UPDATE `vn2008`.`warehouse` SET `hasStowaway` = '1' WHERE (`id` = '1');
CREATE
OR REPLACE ALGORITHM = UNDEFINED
DEFINER = `root`@`%`
SQL SECURITY DEFINER
VIEW `vn`.`warehouse` AS
SELECT
`t`.`id` AS `id`,
`t`.`name` AS `name`,
`t`.`inventario` AS `isInventory`,
`t`.`fuente` AS `isFeedStock`,
`t`.`is_comparative` AS `isComparative`,
`t`.`comisionantes` AS `hasComission`,
`t`.`reserve` AS `hasAvailable`,
`t`.`isManaged` AS `isManaged`,
`t`.`tpv` AS `isForTicket`,
`t`.`hasStowaway` AS `hasStowaway`
FROM
`vn2008`.`warehouse` `t`;

View File

@ -56,13 +56,13 @@ INSERT INTO `vn`.`country`(`id`, `country`, `isUeeMember`, `code`, `currencyFk`,
(19,'Francia', 1, 'FR', 1, 25),
(30,'Canarias', 1, 'IC', 1, 22);
INSERT INTO `vn`.`warehouse`(`id`, `name`, `isComparative`, `isInventory`, `hasAvailable`, `isManaged`)
INSERT INTO `vn`.`warehouse`(`id`, `name`, `isComparative`, `isInventory`, `hasAvailable`, `isManaged`, `hasStowaway`)
VALUES
(1, 'Warehouse One', 1, 1, 1, 1),
(2, 'Warehouse Two', 1, 1, 1, 1),
(3, 'Warehouse Three', 1, 1, 1, 1),
(4, 'Warehouse Four', 1, 1, 1, 1),
(5, 'Warehouse Five', 1, 1, 1, 1);
(1, 'Warehouse One', 1, 1, 1, 1, 1),
(2, 'Warehouse Two', 1, 1, 1, 1, 0),
(3, 'Warehouse Three', 1, 1, 1, 1, 0),
(4, 'Warehouse Four', 1, 1, 1, 1, 0),
(5, 'Warehouse Five', 1, 1, 1, 1, 0);
INSERT INTO `vn`.`warehouseAlias`(`id`, `name`)
VALUES

View File

@ -110,6 +110,7 @@ describe('Ticket descriptor path', () => {
it('should open the add stowaway dialog', async() => {
const isVisible = await nightmare
.waitForSpinnerLoad()
.waitToClick(selectors.ticketDescriptor.moreMenu)
.waitToClick(selectors.ticketDescriptor.moreMenuAddStowaway)
.wait(selectors.ticketDescriptor.addStowawayDialogFirstTicket)

View File

@ -45,4 +45,4 @@ import './input-file';
import './treeview';
import './treeview/child';
import './calendar';
import './scroll-up/scroll-up';

View File

@ -3,7 +3,7 @@ import Input from '../../lib/input';
import './style.scss';
/**
* Draw checkbox with a drop-down and multi options
* Multicheck component for checking all form instances at once
* @param {SmallInt} checkAll Primary input-check state: 0 -> uncheck, 1 -> checked
* @param {Array} data List of options shown in drop-down
* @param {Array} models Elements to check / unCheck

View File

@ -0,0 +1,5 @@
<button class="mdl-button mdl-js-button mdl-button--fab mdl-button--mini-fab mdl-js-ripple-effect mdl-button--colored"
ng-click="$ctrl.goUp()"
vn-tooltip="Go up">
<vn-icon icon="keyboard_arrow_up"></vn-icon>
</button>

View File

@ -0,0 +1,35 @@
import ngModule from '../../module';
import Component from '../../lib/component';
import './style.scss';
export default class Controller extends Component {
constructor($element, $scope, $window) {
super($element, $scope);
this.$window = $window;
$window.addEventListener('scroll', () => {
console.log($element[0]);
if ($window.scrollY > 0)
$element[0].style.display = 'block';
else
$element[0].style.display = 'none';
});
}
goUp() {
this.$window.scrollTo(0, 0);
}
}
Controller.$inject = ['$element', '$scope', '$window'];
ngModule.component('vnScrollUp', {
template: require('./scroll-up.html'),
controller: Controller,
bindings: {
field: '=?',
options: '<?',
disabled: '<?',
checked: '<?'
}
});

View File

@ -0,0 +1,6 @@
vn-scroll-up {
top: 5em;
right: 2.5em;
display: none;
position: fixed;
}

View File

@ -50,4 +50,5 @@ Fields to show: Campos a mostrar
Create new one: Crear nuevo
Toggle: Desplegar/Plegar
Check all: Seleccionar todo
Select a file: Selecciona un fichero
Select a file: Selecciona un fichero
Go up: Ir arriba

View File

@ -101,5 +101,6 @@
"This ticket is already on weekly tickets": "Este ticket ya está en tickets programados",
"Ticket id cannot be blank": "El id de ticket no puede quedar en blanco",
"Weekday cannot be blank": "El día de la semana no puede quedar en blanco",
"You can't delete a confirmed order": "No puedes borrar un pedido confirmado"
"You can't delete a confirmed order": "No puedes borrar un pedido confirmado",
"Can't create stowaway for this ticket": "No se puede crear un polizon para este ticket"
}

View File

@ -81,4 +81,5 @@
vn-acl="deliveryBoss"
vn-acl-action="remove">
</vn-float-button>
</a>
</a>
<vn-scroll-up></vn-scroll-up>

View File

@ -68,9 +68,6 @@ class Controller {
this.$scope.confirmPickupOrder.show();
}
confirmDeleteClaim() {
this.$scope.confirmDeleteClaim.show();
}
sendPickupOrder(response) {
if (response === 'ACCEPT') {
this.$http.post(`/api/email/claim-pickup-order`, {claimFk: this.claim.id}).then(
@ -78,6 +75,11 @@ class Controller {
);
}
}
confirmDeleteClaim() {
this.$scope.confirmDeleteClaim.show();
}
deleteClaim(response) {
if (response === 'ACCEPT') {
this.$http.delete(`/claim/api/Claims/${this.claim.id}`).then(() => {

View File

@ -75,4 +75,5 @@
<tpl-body>
<vn-claim-summary claim="$ctrl.claimSelected"></vn-claim-summary>
</tpl-body>
</vn-dialog>
</vn-dialog>
<vn-scroll-up></vn-scroll-up>

View File

@ -66,4 +66,5 @@
<tpl-body>
<vn-client-summary client="$ctrl.clientSelected"></vn-client-summary>
</tpl-body>
</vn-dialog>
</vn-dialog>
<vn-scroll-up></vn-scroll-up>

View File

@ -78,3 +78,4 @@
</tpl-body>
</vn-dialog>
<vn-client-descriptor-popover vn-id="clientDescriptor"></vn-client-descriptor-popover>
<vn-scroll-up></vn-scroll-up>

View File

@ -81,4 +81,6 @@
</vn-ticket-descriptor-popover>
<vn-client-descriptor-popover
vn-id="clientDescriptor">
</vn-client-descriptor-popover>
</vn-client-descriptor-popover>
<vn-scroll-up></vn-scroll-up>

View File

@ -145,4 +145,5 @@
<vn-worker-descriptor-popover
vn-id="workerDescriptor"
worker-fk="$ctrl.selectedWorker">
</vn-worker-descriptor-popover>
</vn-worker-descriptor-popover>
<vn-scroll-up></vn-scroll-up>

View File

@ -90,4 +90,5 @@
<tpl-body>
<vn-order-summary order="$ctrl.selectedOrder"></vn-order-summary>
</tpl-body>
</vn-dialog>
</vn-dialog>
<vn-scroll-up></vn-scroll-up>

View File

@ -74,4 +74,5 @@
</vn-worker-descriptor-popover>
<a ui-sref="route.create" vn-tooltip="New route" vn-bind="+" fixed-bottom-right>
<vn-float-button icon="add"></vn-float-button>
</a>
</a>
<vn-scroll-up></vn-scroll-up>

View File

@ -0,0 +1,31 @@
module.exports = Self => {
Self.remoteMethod('canBeStowawayed', {
description: 'Returns if a ticket can be stowawayed',
accessType: 'READ',
accepts: [{
arg: 'id',
type: 'number',
required: true,
description: 'ticket id',
http: {source: 'path'}
}],
returns: {
root: true
},
http: {
path: `/:id/canBeStowawayed`,
verb: 'GET'
}
});
Self.canBeStowawayed = async id => {
const ticket = await Self.app.models.Ticket.findById(id);
const warehouse = await Self.app.models.Warehouse.findById(ticket.warehouseFk);
if (warehouse && warehouse.hasStowaway)
return true;
return false;
};
};

View File

@ -1,3 +1,5 @@
const UserError = require('vn-loopback/util/user-error');
module.exports = Self => {
Self.remoteMethod('getPossibleStowaways', {
description: 'Returns mana of a salesperson of a ticket',
@ -19,6 +21,11 @@ module.exports = Self => {
});
Self.getPossibleStowaways = async ticketFk => {
let canStowaway = await Self.app.models.Ticket.canBeStowawayed(ticketFk);
if (!canStowaway)
throw new UserError(`Can't create stowaway for this ticket`);
let ship = await Self.app.models.Ticket.findById(ticketFk);
if (!ship || !ship.shipped)

View File

@ -0,0 +1,17 @@
const app = require('vn-loopback/server/server');
describe('ticket canBeStowawayed()', () => {
it('should return true if the ticket warehouse have hasStowaway equal 1', async() => {
const ticketId = 16;
let canStowaway = await app.models.Ticket.canBeStowawayed(ticketId);
expect(canStowaway).toBeTruthy();
});
it('should return false if the ticket warehouse dont have hasStowaway equal 0', async() => {
const ticketId = 10;
let canStowaway = await app.models.Ticket.canBeStowawayed(ticketId);
expect(canStowaway).toBeFalsy();
});
});

View File

@ -1,6 +1,13 @@
const LoopBackContext = require('loopback-context');
const UserError = require('vn-loopback/util/user-error');
module.exports = function(Self) {
Self.observe('before save', async function(ctx) {
let isStowaway = await Self.app.models.Ticket.canBeStowawayed(ctx.instance.id);
if (!isStowaway)
throw new UserError(`Can't create stowaway for this ticket`);
if (ctx.isNewInstance) {
let where = {
code: 'BOARDING'

View File

@ -25,6 +25,7 @@ module.exports = Self => {
require('../methods/ticket/uploadFile')(Self);
require('../methods/ticket/addSale')(Self);
require('../methods/ticket/transferSales')(Self);
require('../methods/ticket/canBeStowawayed')(Self);
Self.observe('before save', async function(ctx) {
if (ctx.isNewInstance) return;

View File

@ -156,7 +156,6 @@ describe('Ticket', () => {
$httpBackend.when('GET', `/api/Clients/${clientId}/addresses?filter=${filter}`).respond(200);
$httpBackend.expect('GET', `/api/Clients/${clientId}/addresses?filter=${filter}`);
controller.onChangeClient(clientId);
$httpBackend.flush();
});
@ -175,66 +174,11 @@ describe('Ticket', () => {
$httpBackend.when('GET', `/api/Zones/${zoneId}`).respond(200);
$httpBackend.expect('GET', `/api/Zones/${zoneId}`);
controller.onChangeZone(zoneId);
$httpBackend.flush();
});
});
/* it('should return an available agency', async() => {
const landed = new Date();
const agencyModeId = 7;
controller._ticket = {
id: 1,
landed: landed,
addressFk: 121,
agencyModeFk: agencyModeId,
warehouseFk: 1
};
let params = {
landed: landed,
addressFk: 121,
agencyModeFk: agencyModeId,
warehouseFk: 1
};
let serializedParams = $httpParamSerializer(params);
$httpBackend.when('GET', `/api/Agencies/getShipped?${serializedParams}`).respond(200);
$httpBackend.expect('GET', `/api/Agencies/getShipped?${serializedParams}`);
controller.onChangeAgencyMode(agencyModeId);
$httpBackend.flush();
});
it('should throw a user error', async() => {
spyOn(controller.vnApp, 'showMessage');
const landed = new Date();
const agencyModeId = 7;
controller._ticket = {
id: 1,
landed: landed,
addressFk: 121,
agencyModeFk: agencyModeId,
warehouseFk: 1
};
let params = {
landed: landed,
addressFk: 121,
agencyModeFk: agencyModeId,
warehouseFk: 1
};
let serializedParams = $httpParamSerializer(params);
$httpBackend.when('GET', `/api/Agencies/getShipped?${serializedParams}`).respond(null);
$httpBackend.expect('GET', `/api/Agencies/getShipped?${serializedParams}`);
controller.onChangeAgencyMode(agencyModeId);
$httpBackend.flush();
expect(controller.vnApp.showMessage).toHaveBeenCalledWith('No delivery zone available for this parameters');
}); */
describe('isFormInvalid()', () => {
it('should check if all form fields are valid', () => {
controller.ticket = {

View File

@ -203,4 +203,11 @@
<!-- SMS Dialog -->
<vn-client-sms vn-id="sms" sms="$ctrl.newSMS"></vn-client-sms>
<!-- SMS Dialog -->
<!-- SMS Dialog -->
<vn-confirm
vn-id="confirm-delivery-note"
on-response="$ctrl.sendDeliveryNote(response)"
question="Send Delivery Note"
message="Are you sure you want to send it?">
</vn-confirm>

View File

@ -11,6 +11,7 @@ class Controller {
this.moreOptions = [
{name: 'Add turn', callback: this.showAddTurnDialog},
{name: 'Show Delivery Note', callback: this.showDeliveryNote},
{name: 'Send Delivery Note', callback: this.confirmDeliveryNote},
{name: 'Delete ticket', callback: this.showDeleteTicketDialog},
{name: 'Change shipped hour', callback: this.showChangeShipped},
{name: 'Send SMS', callback: this.showSMSDialog},
@ -18,7 +19,7 @@ class Controller {
{
name: 'Add stowaway',
callback: this.showAddStowaway,
show: () => this.isTicketModule()
show: () => this.canShowStowaway
},
{
name: 'Remove stowaway',
@ -40,6 +41,14 @@ class Controller {
];
}
set canShowStowaway(value) {
this._canShowStowaway = value;
}
get canShowStowaway() {
return this._canShowStowaway;
}
showChangeShipped() {
if (!this.isEditable) {
this.vnApp.showError(this.$translate.instant('This ticket can\'t be modified'));
@ -62,12 +71,24 @@ class Controller {
isTicketModule() {
let path = this.$state.getCurrentPath();
if (path[1].state.name === 'ticket')
const isTicket = path[1].state.name === 'ticket';
if (isTicket)
return true;
return false;
}
canStowaway() {
if (!this.isTicketModule()) return;
this.$http.get(`/api/Tickets/${this.ticket.id}/canBeStowawayed`).then(response => {
if (response.data === true)
return this.canShowStowaway = true;
return this.canShowStowaway = false;
});
}
shouldShowRemoveStowaway() {
if (!this._ticket || !this.isTicketModule())
return false;
@ -153,6 +174,8 @@ class Controller {
set ticket(value) {
this._ticket = value;
if (value)
this.canStowaway();
if (!value) return;
@ -262,6 +285,18 @@ class Controller {
hasInvoice() {
return this.ticket.refFk !== null;
}
confirmDeliveryNote() {
this.$scope.confirmDeliveryNote.show();
}
sendDeliveryNote(response) {
if (response === 'ACCEPT') {
this.$http.post(`/api/email/delivery-note`, {ticketFk: this.ticket.id}).then(
() => this.vnApp.showMessage(this.$translate.instant('Notification sent!'))
);
}
}
}
Controller.$inject = ['$state', '$scope', '$http', 'vnApp', '$translate', 'aclService'];

View File

@ -3,13 +3,21 @@ import './index.js';
describe('Ticket Component vnTicketDescriptor', () => {
let $httpBackend;
let controller;
let $state;
beforeEach(ngModule('ticket'));
beforeEach(angular.mock.inject(($componentController, _$httpBackend_) => {
beforeEach(angular.mock.inject(($componentController, _$state_, _$httpBackend_) => {
$state = _$state_;
$state.getCurrentPath = () => {
return [
{state: {}},
{state: {name: 'ticket'}}
];
};
$httpBackend = _$httpBackend_;
controller = $componentController('vnTicketDescriptor');
controller.ticket = {id: 2, invoiceOut: {id: 1}};
controller = $componentController('vnTicketDescriptor', {$state});
controller._ticket = {id: 2, invoiceOut: {id: 1}};
controller.cardReload = ()=> {
return true;
};
@ -25,7 +33,7 @@ describe('Ticket Component vnTicketDescriptor', () => {
});
});
describe('addTurn(day)', () => {
describe('addTurn()', () => {
it('should make a query and call $.addTurn.hide() and vnApp.showSuccess()', () => {
controller.$scope.addTurn = {hide: () => {}};
spyOn(controller.$scope.addTurn, 'hide');
@ -57,7 +65,7 @@ describe('Ticket Component vnTicketDescriptor', () => {
});
});
describe('deleteTicket(response)', () => {
describe('deleteTicket()', () => {
it('should make a query and call vnApp.showSuccess() if the response is ACCEPT', () => {
spyOn(controller.$state, 'go');
spyOn(controller.vnApp, 'showSuccess');
@ -81,7 +89,7 @@ describe('Ticket Component vnTicketDescriptor', () => {
});
});
describe('makeInvoice(response)', () => {
describe('makeInvoice()', () => {
it('should make a query and call $state.reload() method if the response is ACCEPT', () => {
spyOn(controller.$state, 'reload');
spyOn(controller.vnApp, 'showSuccess');
@ -96,7 +104,7 @@ describe('Ticket Component vnTicketDescriptor', () => {
});
});
describe('regenerateInvoice(response)', () => {
describe('regenerateInvoice()', () => {
it('should make a query and show a success snackbar if the response is ACCEPT', () => {
spyOn(controller.vnApp, 'showSuccess');
@ -109,7 +117,7 @@ describe('Ticket Component vnTicketDescriptor', () => {
});
});
describe('changeShipped(response)', () => {
describe('changeShipped()', () => {
it('should make a query and change the shipped hour if the response is ACCEPT', () => {
controller.ticket.id = 12;
spyOn(controller.vnApp, 'showSuccess');
@ -124,4 +132,33 @@ describe('Ticket Component vnTicketDescriptor', () => {
expect(controller.cardReload).toHaveBeenCalledWith();
});
});
describe('canStowaway()', () => {
it('should make a query and return if the ticket can be stowawayed', () => {
controller.ticket.id = 16;
spyOn(controller, 'isTicketModule').and.callThrough();
$httpBackend.when('GET', '/api/Tickets/16/canBeStowawayed').respond(true);
$httpBackend.expect('GET', '/api/Tickets/16/canBeStowawayed').respond(true);
controller.canStowaway();
$httpBackend.flush();
expect(controller.canShowStowaway).toBeTruthy();
expect(controller.isTicketModule).toHaveBeenCalledWith();
});
it('should not make a query if is not on the ticket module', () => {
controller.ticket.id = 16;
$state.getCurrentPath = () => {
return [
{state: {}},
{state: {name: 'client'}}
];
};
spyOn(controller, 'isTicketModule').and.callThrough();
controller.canStowaway();
expect(controller.canShowStowaway).toBeUndefined();
expect(controller.isTicketModule).toHaveBeenCalledWith();
});
});
});

View File

@ -7,7 +7,9 @@ Stowaways of the ticket: Polizones del ticket
Add stowaway: Añadir polizón
Remove stowaway: Borrar polizón
Are you sure you want to delete this stowaway?: ¿Seguro que quieres borrar este polizón?
Are you sure you want to send it?: ¿Seguro que quieres enviarlo?
Show Delivery Note: Ver albarán
Send Delivery Note: Enviar albarán
Show pallet report: Ver hoja de pallet
Change shipped hour: Cambiar hora de envío
Shipped hour: Hora de envío

View File

@ -160,4 +160,5 @@
</vn-worker-descriptor-popover>
<vn-client-balance-create
vn-id="balanceCreateDialog">
</vn-client-balance-create>
</vn-client-balance-create>
<vn-scroll-up></vn-scroll-up>

View File

@ -3,6 +3,10 @@
url="/api/Tickets/{{$ctrl.$stateParams.id}}/getSales"
data="$ctrl.sales">
</vn-crud-model>
<vn-watcher
vn-id="watcher"
data="$ctrl.sales">
</vn-watcher>
<vn-vertical>
<vn-card pad-large>
<vn-vertical>
@ -272,17 +276,17 @@
<vn-thead>
<vn-tr>
<vn-th number shrink>Id</vn-th>
<vn-th shrink>Item</vn-th>
<vn-th>Item</vn-th>
<vn-th number shrink>Quantity</vn-th>
</vn-tr>
</vn-thead>
<vn-tbody>
<vn-tr ng-repeat="sale in $ctrl.transfer.sales">
<vn-td number shrink>{{::sale.itemFk | zeroFill:6}}</vn-td>
<vn-td shrink>
<vn-td>
<span title="{{::sale.concept}}">{{::sale.concept}}</span>
</vn-td>
<vn-td-editable number>
<vn-td-editable number shrink>
<text>{{sale.quantity}}</text>
<field>
<vn-input-number vn-focus
@ -303,7 +307,7 @@
icon="info">
</vn-icon>
</vn-horizontal>
<vn-table class="vn-grid">
<table class="vn-grid">
<thead>
<tr>
<th number>ID</th>
@ -326,7 +330,7 @@
<td number>{{::ticket.warehouseName}}</td>
</tr>
</tbody>
</vn-table>
</table>
<vn-horizontal pad-medium-v>
<vn-textfield vn-one

View File

@ -116,6 +116,18 @@ class Controller {
});
}
/**
* Returns new instances
*
* @return {Array} New instances
*/
newInstances() {
if (!this.sales) return;
return this.sales.filter(sale => {
return !sale.id;
});
}
/**
* Returns an array of indexes
@ -151,6 +163,7 @@ class Controller {
return checkedLines.length;
}
removeCheckedLines() {
const sales = this.checkedLines();
@ -159,6 +172,9 @@ class Controller {
this.sales.splice(index, 1);
});
if (this.newInstances().length === 0)
this.$scope.watcher.updateOriginalData();
this.refreshTotal();
}
@ -295,8 +311,8 @@ class Controller {
updatePrice() {
if (this.editedPrice != this.sale.price) {
this.$http.post(`/api/Sales/${this.edit.id}/updatePrice`, {newPrice: this.editedPrice}).then(res => {
if (res.data)
this.sale.price = res.data.price;
this.sale.price = res.data.price;
this.$scope.watcher.updateOriginalData();
this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
});
@ -434,6 +450,8 @@ class Controller {
const data = {quantity: parseInt(sale.quantity)};
const query = `/api/Sales/${sale.id}/updateQuantity`;
this.$http.post(query, data).then(() => {
this.$scope.watcher.updateOriginalData();
this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
}).catch(e => {
this.$scope.model.refresh();
@ -448,6 +466,7 @@ class Controller {
const data = {newConcept: sale.concept};
const query = `/api/Sales/${sale.id}/updateConcept`;
this.$http.post(query, data).then(() => {
this.$scope.watcher.updateOriginalData();
this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
}).catch(e => {
this.$scope.model.refresh();
@ -478,6 +497,9 @@ class Controller {
sale.price = newSale.price;
sale.item = newSale.item;
if (this.newInstances().length === 0)
this.$scope.watcher.updateOriginalData();
this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
});
}

View File

@ -1,4 +1,5 @@
import '../index.js';
import watcher from 'core/mocks/watcher';
describe('Ticket', () => {
describe('Component vnTicketSale', () => {
@ -42,6 +43,7 @@ describe('Ticket', () => {
$scope = $rootScope.$new();
$scope.ticket = ticket;
$scope.watcher = watcher;
$httpBackend = _$httpBackend_;
$httpBackend.whenGET(/api\/Tickets\/1\/getSales.*/).respond(sales);
@ -188,6 +190,7 @@ describe('Ticket', () => {
describe('updateQuantity()', () => {
it('should make a POST query saving sale quantity', () => {
spyOn(controller.$scope.watcher, 'updateOriginalData');
const data = {quantity: 10};
const sale = sales[0];
sale.quantity = 10;
@ -196,11 +199,14 @@ describe('Ticket', () => {
$httpBackend.expect('POST', `/api/Sales/1/updateQuantity`, data).respond();
controller.updateQuantity(sale);
$httpBackend.flush();
expect(controller.$scope.watcher.updateOriginalData).toHaveBeenCalledWith();
});
});
describe('updateConcept()', () => {
it('should make a POST query saving sale concept', () => {
spyOn(controller.$scope.watcher, 'updateOriginalData');
const data = {concept: 'My new weapon'};
const sale = sales[0];
sale.concept = 'My new weapon';
@ -209,11 +215,14 @@ describe('Ticket', () => {
$httpBackend.expect('PATCH', `/api/Sales/1`, data).respond();
controller.updateConcept(sale);
$httpBackend.flush();
expect(controller.$scope.watcher.updateOriginalData).toHaveBeenCalledWith();
});
});
describe('addSale()', () => {
it('should make a POST query adding a new sale', () => {
spyOn(controller.$scope.watcher, 'updateOriginalData');
const newSale = {itemFk: 4, quantity: 10};
const params = {itemId: 4, quantity: 10};
@ -233,6 +242,8 @@ describe('Ticket', () => {
$httpBackend.expect('POST', `/api/tickets/1/addSale`, params).respond(expectedResult);
controller.addSale(newSale);
$httpBackend.flush();
expect(controller.$scope.watcher.updateOriginalData).toHaveBeenCalledWith();
});
});

View File

@ -80,9 +80,10 @@ vn-ticket-sale {
}
vn-table {
overflow-x: hidden;
overflow-y: auto;
max-height: 25em;
width: 20em;
width: 30em;
}
table {

View File

@ -4,6 +4,7 @@
filter="::$ctrl.filter"
limit="20"
data="weeklies"
order="ticketFk"
primary-key="ticketFk">
</vn-crud-model>
<div class="content-block">

View File

@ -51,4 +51,5 @@
</vn-table>
</vn-card>
<vn-pagination model="model"></vn-pagination>
</div>
</div>
<vn-scroll-up></vn-scroll-up>

View File

@ -72,4 +72,5 @@
<tpl-body>
<vn-worker-summary worker="$ctrl.selectedWorker"></vn-worker-summary>
</tpl-body>
</vn-dialog>
</vn-dialog>
<vn-scroll-up></vn-scroll-up>

View File

@ -8,6 +8,7 @@
{"type": "email", "name": "sepa-core"},
{"type": "email", "name": "client-lcr"},
{"type": "email", "name": "driver-route"},
{"type": "email", "name": "delivery-note"},
{"type": "report", "name": "rpt-delivery-note"},
{"type": "report", "name": "rpt-claim-pickup-order"},
{"type": "report", "name": "rpt-letter-debtor"},

View File

@ -0,0 +1,7 @@
const CssReader = require(`${appPath}/lib/cssReader`);
module.exports = new CssReader([
`${appPath}/common/css/layout.css`,
`${appPath}/common/css/email.css`,
`${appPath}/common/css/misc.css`])
.mergeStyles();

View File

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html lang="es">
<head>
<title>{{ $t('subject') }}</title>
</head>
<body>
<section class="container">
<!-- Header component -->
<email-header></email-header>
<!-- End header component -->
<section class="main">
<!-- Title block -->
<div class="title">
<h1>{{ $t('title') }}</h1>
</div>
<!-- Title block end -->
<p>{{$t('dearClient')}},</p>
<p v-html="$t('clientData')"></p>
<p v-html="$t('help')"></p>
</section>
<!-- Footer component -->
<email-footer :locale="locale"></email-footer>
<!-- End footer component -->
</section>
</body>
</html>

View File

@ -0,0 +1,50 @@
const database = require(`${appPath}/lib/database`);
const reportEngine = require(`${appPath}/lib/reportEngine.js`);
const UserException = require(`${appPath}/lib/exceptions/userException`);
module.exports = {
name: 'delivery-note',
async asyncData(ctx, params) {
const promises = [];
const data = {
isPreview: ctx.method === 'GET',
};
if (!params.ticketFk)
throw new UserException('No ticket id specified');
promises.push(reportEngine.toPdf('rpt-delivery-note', ctx));
promises.push(this.methods.fetchTicket(params.ticketFk));
return Promise.all(promises).then(result => {
const stream = result[0];
const [[ticket]] = result[1];
Object.assign(data, ticket);
Object.assign(data, {attachments: [{filename: 'rpt-delivery-note.pdf', content: stream}]});
return data;
});
},
created() {
if (this.locale)
this.$i18n.locale = this.locale;
},
methods: {
fetchTicket(ticketFk) {
return database.pool.query(`
SELECT
t.id,
u.lang locale,
c.email recipient
FROM ticket t
JOIN client c ON c.id = t.clientFk
JOIN account.user u ON u.id = c.id
WHERE t.id = ?`, [ticketFk]);
},
},
components: {
'email-header': require('../email-header'),
'email-footer': require('../email-footer'),
},
};

View File

@ -0,0 +1,11 @@
module.exports = {
messages: {
es: {
subject: 'Aquí tienes tu albarán',
title: '¡Este es tu albarán!',
dearClient: 'Estimado cliente',
clientData: `A continuación adjuntamos tu albarán.`,
help: 'Cualquier duda que te surja, no dudes en consultarla, <strong>¡estamos para atenderte!</strong>'
},
},
};

View File

@ -6,16 +6,16 @@ module.exports = {
sections: {
introduction: {
title: 'Estimado cliente',
description: `Le informamos que han cambiado las condiciones de pago de su cuenta.
<br/>A continuación le indicamos las nuevas condiciones`,
description: `Te informamos que han cambiado las condiciones de pago de tu cuenta.
<br/>A continuación te indicamos las nuevas condiciones`,
},
pay: {
method: 'Método de pago',
day: 'Día de pago',
dueDay: '{0} de cada mes',
cardImplicates: `Su modo de pago actual implica que deberá abonar el
cardImplicates: `Tu modo de pago actual implica que deberás abonar el
importe de los pedidos realizados en el mismo día para que se puedan enviar.`,
accountImplicates: `Su modo de pago actual implica que se le pasará un cargo a la
accountImplicates: `Tu modo de pago actual implica que se te pasará un cargo a la
cuenta terminada en <strong>"{0}"</strong> por el importe pendiente, al vencimiento establecido en las condiciones.`,
},
},