Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 2145_e2e_linux_fix
This commit is contained in:
commit
91b58eb56b
|
@ -823,7 +823,7 @@ export default {
|
||||||
travelThermograph: {
|
travelThermograph: {
|
||||||
add: 'vn-travel-thermograph-index vn-float-button[icon="add"]',
|
add: 'vn-travel-thermograph-index vn-float-button[icon="add"]',
|
||||||
thermographID: 'vn-travel-thermograph-create vn-autocomplete[ng-model="$ctrl.dms.thermographId"]',
|
thermographID: 'vn-travel-thermograph-create vn-autocomplete[ng-model="$ctrl.dms.thermographId"]',
|
||||||
uploadIcon: 'vn-travel-thermograph-create vn-icon[icon="attach_file"]',
|
uploadIcon: 'vn-travel-thermograph-create vn-icon[icon="icon-attach"]',
|
||||||
createdThermograph: 'vn-travel-thermograph-index vn-tbody > vn-tr',
|
createdThermograph: 'vn-travel-thermograph-index vn-tbody > vn-tr',
|
||||||
upload: 'vn-travel-thermograph-create button[type=submit]'
|
upload: 'vn-travel-thermograph-create button[type=submit]'
|
||||||
},
|
},
|
||||||
|
|
|
@ -13,7 +13,7 @@ export default class Datalist extends Textfield {
|
||||||
this._selection = null;
|
this._selection = null;
|
||||||
|
|
||||||
this.buildInput('text');
|
this.buildInput('text');
|
||||||
this.input.setAttribute('autocomplete', 'off');
|
this.autocomplete = 'off';
|
||||||
}
|
}
|
||||||
|
|
||||||
get field() {
|
get field() {
|
||||||
|
@ -258,7 +258,8 @@ export default class Datalist extends Textfield {
|
||||||
fragment.appendChild(option);
|
fragment.appendChild(option);
|
||||||
}
|
}
|
||||||
|
|
||||||
list.appendChild(fragment);
|
this.$.$applyAsync(() =>
|
||||||
|
list.appendChild(fragment));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -100,7 +100,9 @@ export default class Watcher extends Component {
|
||||||
*/
|
*/
|
||||||
submit() {
|
submit() {
|
||||||
try {
|
try {
|
||||||
this.check();
|
if (this.requestMethod() !== 'post')
|
||||||
|
this.check();
|
||||||
|
else this.isInvalid();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return this.$q.reject(err);
|
return this.$q.reject(err);
|
||||||
}
|
}
|
||||||
|
@ -120,12 +122,12 @@ export default class Watcher extends Component {
|
||||||
if (this.form)
|
if (this.form)
|
||||||
this.form.$setSubmitted();
|
this.form.$setSubmitted();
|
||||||
|
|
||||||
if (!this.dataChanged()) {
|
const isPost = (this.requestMethod() === 'post');
|
||||||
|
if (!this.dataChanged() && !isPost) {
|
||||||
this.updateOriginalData();
|
this.updateOriginalData();
|
||||||
return this.$q.resolve();
|
return this.$q.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
let isPost = (this.$attrs.save && this.$attrs.save.toLowerCase() === 'post');
|
|
||||||
let changedData = isPost
|
let changedData = isPost
|
||||||
? this.data
|
? this.data
|
||||||
: getModifiedData(this.data, this.orgData);
|
: getModifiedData(this.data, this.orgData);
|
||||||
|
@ -158,7 +160,6 @@ export default class Watcher extends Component {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return this.$q((resolve, reject) => {
|
return this.$q((resolve, reject) => {
|
||||||
this.$http.post(this.url, changedData).then(
|
this.$http.post(this.url, changedData).then(
|
||||||
json => this.writeData(json, resolve),
|
json => this.writeData(json, resolve),
|
||||||
|
@ -166,6 +167,13 @@ export default class Watcher extends Component {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* return the request method.
|
||||||
|
*/
|
||||||
|
|
||||||
|
requestMethod() {
|
||||||
|
return this.$attrs.save && this.$attrs.save.toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if data is ready to send.
|
* Checks if data is ready to send.
|
||||||
|
@ -177,6 +185,14 @@ export default class Watcher extends Component {
|
||||||
throw new UserError('No changes to save');
|
throw new UserError('No changes to save');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the form is valid.
|
||||||
|
*/
|
||||||
|
isInvalid() {
|
||||||
|
if (this.form && this.form.$invalid)
|
||||||
|
throw new UserError('Some fields are invalid');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notifies the user that the data has been saved.
|
* Notifies the user that the data has been saved.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -60,7 +60,7 @@ describe('Directive http-click', () => {
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
expect(finalValue).toEqual('called!');
|
expect(finalValue).toEqual('called!');
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
console.log(err);
|
throw err;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,10 +2,11 @@ import ngModule from '../module';
|
||||||
import getMainRoute from '../lib/get-main-route';
|
import getMainRoute from '../lib/get-main-route';
|
||||||
|
|
||||||
export default class Modules {
|
export default class Modules {
|
||||||
constructor(aclService, $window) {
|
constructor(aclService, $window, $translate) {
|
||||||
Object.assign(this, {
|
Object.assign(this, {
|
||||||
aclService,
|
aclService,
|
||||||
$window
|
$window,
|
||||||
|
$translate
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +18,7 @@ export default class Modules {
|
||||||
if (this.modules)
|
if (this.modules)
|
||||||
return this.modules;
|
return this.modules;
|
||||||
|
|
||||||
this.modules = [];
|
const modules = [];
|
||||||
for (let mod of this.$window.routes) {
|
for (let mod of this.$window.routes) {
|
||||||
if (!mod || !mod.routes) continue;
|
if (!mod || !mod.routes) continue;
|
||||||
|
|
||||||
|
@ -31,7 +32,7 @@ export default class Modules {
|
||||||
if (res) keyBind = res.key.toUpperCase();
|
if (res) keyBind = res.key.toUpperCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.modules.push({
|
modules.push({
|
||||||
name: mod.name || mod.module,
|
name: mod.name || mod.module,
|
||||||
icon: mod.icon || null,
|
icon: mod.icon || null,
|
||||||
route,
|
route,
|
||||||
|
@ -39,9 +40,16 @@ export default class Modules {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const sortedModules = modules.sort((a, b) => {
|
||||||
|
const translatedNameA = this.$translate.instant(a.name);
|
||||||
|
const translatedNameB = this.$translate.instant(b.name);
|
||||||
|
return translatedNameA.localeCompare(translatedNameB);
|
||||||
|
});
|
||||||
|
this.modules = sortedModules;
|
||||||
|
|
||||||
return this.modules;
|
return this.modules;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Modules.$inject = ['aclService', '$window'];
|
Modules.$inject = ['aclService', '$window', '$translate'];
|
||||||
|
|
||||||
ngModule.service('vnModules', Modules);
|
ngModule.service('vnModules', Modules);
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
<div>
|
<div>
|
||||||
<vn-icon icon="{{::mod.icon || 'photo'}}"></vn-icon>
|
<vn-icon icon="{{::mod.icon || 'photo'}}"></vn-icon>
|
||||||
</div>
|
</div>
|
||||||
<h4 ng-bind-html="::$ctrl.getModuleName(mod)"></h4>
|
<h4 ng-bind-html="$ctrl.getModuleName(mod)"></h4>
|
||||||
<span
|
<span
|
||||||
ng-show="::mod.keyBind"
|
ng-show="::mod.keyBind"
|
||||||
vn-tooltip="Ctrl + Alt + {{::mod.keyBind}}">
|
vn-tooltip="Ctrl + Alt + {{::mod.keyBind}}">
|
||||||
|
|
|
@ -128,5 +128,6 @@
|
||||||
"Client checked as validated despite of duplication": "Cliente comprobado a pesar de que existe el cliente id {{clientId}}",
|
"Client checked as validated despite of duplication": "Cliente comprobado a pesar de que existe el cliente id {{clientId}}",
|
||||||
"ORDER_ROW_UNAVAILABLE": "No hay disponibilidad de este producto",
|
"ORDER_ROW_UNAVAILABLE": "No hay disponibilidad de este producto",
|
||||||
"Distance must be lesser than 1000": "La distancia debe ser inferior a 1000",
|
"Distance must be lesser than 1000": "La distancia debe ser inferior a 1000",
|
||||||
"This ticket is deleted": "Este ticket está eliminado"
|
"This ticket is deleted": "Este ticket está eliminado",
|
||||||
|
"A travel with this data already exists": "Ya existe un travel con estos datos"
|
||||||
}
|
}
|
|
@ -175,5 +175,12 @@
|
||||||
"model": "ItemNiche",
|
"model": "ItemNiche",
|
||||||
"foreignKey": "itemFk"
|
"foreignKey": "itemFk"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"scope": {
|
||||||
|
"where": {
|
||||||
|
"name": {
|
||||||
|
"neq": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -16,7 +16,8 @@ class Controller extends Component {
|
||||||
{name: 'Send Delivery Note', callback: this.confirmDeliveryNote},
|
{name: 'Send Delivery Note', callback: this.confirmDeliveryNote},
|
||||||
{name: 'Delete ticket', callback: this.showDeleteTicketDialog},
|
{name: 'Delete ticket', callback: this.showDeleteTicketDialog},
|
||||||
{name: 'Change shipped hour', callback: this.showChangeShipped},
|
{name: 'Change shipped hour', callback: this.showChangeShipped},
|
||||||
{name: 'Send SMS', callback: this.showSMSDialog},
|
{name: 'SMS Pending payment', callback: this.sendPaymentSms},
|
||||||
|
{name: 'SMS Minimum import', callback: this.sendImportSms},
|
||||||
{
|
{
|
||||||
name: 'Add stowaway',
|
name: 'Add stowaway',
|
||||||
callback: this.showAddStowaway,
|
callback: this.showAddStowaway,
|
||||||
|
@ -240,17 +241,30 @@ class Controller extends Component {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sendImportSms() {
|
||||||
|
const params = {
|
||||||
|
ticketId: this.ticket.id,
|
||||||
|
created: this.ticket.created
|
||||||
|
};
|
||||||
|
const message = this.$params.message || this.$translate.instant('Minimum is needed', params);
|
||||||
|
this.newSMS = {message};
|
||||||
|
this.showSMSDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
sendPaymentSms() {
|
||||||
|
const message = this.$params.message || this.$translate.instant('Make a payment');
|
||||||
|
this.newSMS = {message};
|
||||||
|
this.showSMSDialog();
|
||||||
|
}
|
||||||
|
|
||||||
showSMSDialog() {
|
showSMSDialog() {
|
||||||
const address = this.ticket.address;
|
const address = this.ticket.address;
|
||||||
const client = this.ticket.client;
|
const client = this.ticket.client;
|
||||||
const phone = this.$params.phone || address.mobile || address.phone ||
|
const phone = this.$params.phone || address.mobile || address.phone ||
|
||||||
client.mobile || client.phone;
|
client.mobile || client.phone;
|
||||||
const message = this.$params.message || this.$translate.instant('SMSPayment');
|
|
||||||
this.newSMS = {
|
this.newSMS.destinationFk = this.ticket.clientFk;
|
||||||
destinationFk: this.ticket.clientFk,
|
this.newSMS.destination = phone;
|
||||||
destination: phone,
|
|
||||||
message: message
|
|
||||||
};
|
|
||||||
this.$.sms.open();
|
this.$.sms.open();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,13 @@ describe('Ticket Component vnTicketDescriptor', () => {
|
||||||
$httpBackend = _$httpBackend_;
|
$httpBackend = _$httpBackend_;
|
||||||
$httpParamSerializer = _$httpParamSerializer_;
|
$httpParamSerializer = _$httpParamSerializer_;
|
||||||
controller = $componentController('vnTicketDescriptor', {$element});
|
controller = $componentController('vnTicketDescriptor', {$element});
|
||||||
controller._ticket = {id: 2, invoiceOut: {id: 1}, client: {id: 101, email: 'client@email'}};
|
controller._ticket = {
|
||||||
|
id: 2,
|
||||||
|
clientFk: 101,
|
||||||
|
invoiceOut: {id: 1},
|
||||||
|
client: {id: 101, email: 'client@email'},
|
||||||
|
address: {id: 101, mobile: 111111111, phone: 2222222222}
|
||||||
|
};
|
||||||
controller.cardReload = ()=> {
|
controller.cardReload = ()=> {
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
@ -161,7 +167,6 @@ describe('Ticket Component vnTicketDescriptor', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
describe('showAddStowaway()', () => {
|
describe('showAddStowaway()', () => {
|
||||||
it('should show a dialog with a list of tickets available for an stowaway', () => {
|
it('should show a dialog with a list of tickets available for an stowaway', () => {
|
||||||
controller.$.addStowaway = {};
|
controller.$.addStowaway = {};
|
||||||
|
@ -223,4 +228,20 @@ describe('Ticket Component vnTicketDescriptor', () => {
|
||||||
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!');
|
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('showSMSDialog()', () => {
|
||||||
|
it('should set the destionationFk and destination properties and then call the sms open() method', () => {
|
||||||
|
controller.$.sms = {open: () => {}};
|
||||||
|
jest.spyOn(controller.$.sms, 'open');
|
||||||
|
|
||||||
|
const clientId = 101;
|
||||||
|
const expectedPhone = 111111111;
|
||||||
|
controller.newSMS = {};
|
||||||
|
controller.showSMSDialog();
|
||||||
|
|
||||||
|
expect(controller.newSMS.destinationFk).toEqual(clientId);
|
||||||
|
expect(controller.newSMS.destination).toEqual(expectedPhone);
|
||||||
|
expect(controller.$.sms.open).toHaveBeenCalledWith();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,3 +1,2 @@
|
||||||
SMSPayment: >-
|
Make a payment: "Verdnatura communicates:\rYour order is pending of payment.\rPlease, enter the web page and make the payment with card.\rThank you."
|
||||||
Verdnatura communicates: Your order is pending of payment.
|
Minimum is needed: "Verdnatura communicates:\rA minimum import of 50€ (Without BAT) is needed for your order {{ticketId}} from date {{created | date: 'dd/MM/yyyy'}} to receive it with no extra fees."
|
||||||
Please, enter the web page and make the payment with card. Thank you.
|
|
||||||
|
|
|
@ -13,7 +13,8 @@ Send Delivery Note: Enviar albarán
|
||||||
Show pallet report: Ver hoja de pallet
|
Show pallet report: Ver hoja de pallet
|
||||||
Change shipped hour: Cambiar hora de envío
|
Change shipped hour: Cambiar hora de envío
|
||||||
Shipped hour: Hora de envío
|
Shipped hour: Hora de envío
|
||||||
SMSPayment: "Verdnatura le comunica:\rSu pedido está pendiente de pago.\rPor favor, entre en la página web y efectue el pago con tarjeta.\rMuchas gracias."
|
Make a payment: "Verdnatura le comunica:\rSu pedido está pendiente de pago.\rPor favor, entre en la página web y efectue el pago con tarjeta.\rMuchas gracias."
|
||||||
|
Minimum is needed: "Verdnatura le recuerda:\rEs necesario llegar a un importe mínimo de 50€ (Sin IVA) en su pedido {{ticketId}} del día {{created | date: 'dd/MM/yyyy'}} para recibirlo sin portes adicionales."
|
||||||
Ticket invoiced: Ticket facturado
|
Ticket invoiced: Ticket facturado
|
||||||
Make invoice: Crear factura
|
Make invoice: Crear factura
|
||||||
Regenerate invoice: Regenerar factura
|
Regenerate invoice: Regenerar factura
|
||||||
|
@ -25,4 +26,6 @@ Invoice sent for a regeneration, will be available in a few minutes: La factura
|
||||||
Shipped hour updated: Hora de envio modificada
|
Shipped hour updated: Hora de envio modificada
|
||||||
Deleted ticket: Ticket eliminado
|
Deleted ticket: Ticket eliminado
|
||||||
Recalculate components: Recalcular componentes
|
Recalculate components: Recalcular componentes
|
||||||
Are you sure you want to recalculate the components?: ¿Seguro que quieres recalcular los componentes?
|
Are you sure you want to recalculate the components?: ¿Seguro que quieres recalcular los componentes?
|
||||||
|
SMS Minimum import: 'SMS Importe minimo'
|
||||||
|
SMS Pending payment: 'SMS Pago pendiente'
|
|
@ -2,4 +2,5 @@ Weekly tickets: Tickets programados
|
||||||
Go to lines: Ir a lineas
|
Go to lines: Ir a lineas
|
||||||
Not available: No disponible
|
Not available: No disponible
|
||||||
Payment on account...: Pago a cuenta...
|
Payment on account...: Pago a cuenta...
|
||||||
Closure: Cierre
|
Closure: Cierre
|
||||||
|
You cannot make a payment on account from multiple clients: No puedes realizar un pago a cuenta de clientes diferentes
|
|
@ -105,20 +105,22 @@
|
||||||
on-error-src/>
|
on-error-src/>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td vn-focus number>
|
<vn-td vn-focus number>
|
||||||
<span class="link" ng-if="sale.itemFk"
|
<span class="link" ng-if="sale.id"
|
||||||
ng-click="$ctrl.showDescriptor($event, sale.itemFk)">
|
ng-click="$ctrl.showDescriptor($event, sale.itemFk)">
|
||||||
{{sale.itemFk | zeroFill:6}}
|
{{sale.itemFk}}
|
||||||
</span>
|
</span>
|
||||||
<vn-autocomplete
|
<vn-autocomplete
|
||||||
ng-if="!sale.itemFk"
|
ng-if="!sale.id"
|
||||||
vn-focus
|
vn-focus
|
||||||
vn-one
|
vn-one
|
||||||
url="Items"
|
url="Items"
|
||||||
ng-model="sale.itemFk"
|
ng-model="sale.itemFk"
|
||||||
show-field="name"
|
show-field="name"
|
||||||
value-field="id"
|
value-field="id"
|
||||||
search-function="{or: [{id: $search}, {name: {like: '%' + $search + '%'}}]}"
|
search-function="$ctrl.itemSearchFunc($search)"
|
||||||
order="id DESC">
|
on-change="$ctrl.onChangeQuantity(sale)"
|
||||||
|
order="id DESC"
|
||||||
|
tabindex="1">
|
||||||
<tpl-item>
|
<tpl-item>
|
||||||
{{id}} - {{name}}
|
{{id}} - {{name}}
|
||||||
</tpl-item>
|
</tpl-item>
|
||||||
|
@ -137,7 +139,8 @@
|
||||||
<vn-td ng-if="!sale.id" number>
|
<vn-td ng-if="!sale.id" number>
|
||||||
<vn-input-number
|
<vn-input-number
|
||||||
ng-model="sale.quantity"
|
ng-model="sale.quantity"
|
||||||
on-change="$ctrl.onChangeQuantity(sale)">
|
on-change="$ctrl.onChangeQuantity(sale)"
|
||||||
|
tabindex="2">
|
||||||
</vn-input-number>
|
</vn-input-number>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td-editable disabled="!sale.id || !$ctrl.isEditable" expand>
|
<vn-td-editable disabled="!sale.id || !$ctrl.isEditable" expand>
|
||||||
|
@ -150,7 +153,7 @@
|
||||||
</vn-fetched-tags>
|
</vn-fetched-tags>
|
||||||
</text>
|
</text>
|
||||||
<field>
|
<field>
|
||||||
<vn-textfield
|
<vn-textfield class="dense"
|
||||||
vn-id="concept"
|
vn-id="concept"
|
||||||
ng-model="sale.concept"
|
ng-model="sale.concept"
|
||||||
on-change="$ctrl.updateConcept(sale)">
|
on-change="$ctrl.updateConcept(sale)">
|
||||||
|
@ -167,7 +170,8 @@
|
||||||
<vn-td number>
|
<vn-td number>
|
||||||
<span ng-class="{'link': !$ctrl.isLocked}"
|
<span ng-class="{'link': !$ctrl.isLocked}"
|
||||||
title="{{!$ctrl.isLocked ? 'Edit discount' : ''}}"
|
title="{{!$ctrl.isLocked ? 'Edit discount' : ''}}"
|
||||||
ng-click="$ctrl.showEditDiscountPopover($event, sale)">
|
ng-click="$ctrl.showEditDiscountPopover($event, sale)"
|
||||||
|
ng-if="sale.id">
|
||||||
{{(sale.discount / 100) | percentage}}
|
{{(sale.discount / 100) | percentage}}
|
||||||
</span>
|
</span>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
|
|
|
@ -12,7 +12,7 @@ class Controller {
|
||||||
this.edit = {};
|
this.edit = {};
|
||||||
this.moreOptions = [
|
this.moreOptions = [
|
||||||
{
|
{
|
||||||
name: 'Send SMS',
|
name: 'Send shortage SMS',
|
||||||
callback: this.showSMSDialog
|
callback: this.showSMSDialog
|
||||||
}, {
|
}, {
|
||||||
name: 'Mark as reserved',
|
name: 'Mark as reserved',
|
||||||
|
@ -182,7 +182,6 @@ class Controller {
|
||||||
return checkedLines.length;
|
return checkedLines.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
removeCheckedLines() {
|
removeCheckedLines() {
|
||||||
const sales = this.checkedLines();
|
const sales = this.checkedLines();
|
||||||
|
|
||||||
|
@ -448,7 +447,7 @@ class Controller {
|
||||||
this.newSMS = {
|
this.newSMS = {
|
||||||
destinationFk: this.ticket.clientFk,
|
destinationFk: this.ticket.clientFk,
|
||||||
destination: phone,
|
destination: phone,
|
||||||
message: this.$translate.instant('SMSAvailability', params)
|
message: this.$translate.instant('Product not available', params)
|
||||||
};
|
};
|
||||||
this.$scope.sms.open();
|
this.$scope.sms.open();
|
||||||
}
|
}
|
||||||
|
@ -465,10 +464,12 @@ class Controller {
|
||||||
* Updates the sale quantity for existing instance
|
* Updates the sale quantity for existing instance
|
||||||
*/
|
*/
|
||||||
onChangeQuantity(sale) {
|
onChangeQuantity(sale) {
|
||||||
|
if (!sale.quantity) return;
|
||||||
|
|
||||||
if (!sale.id)
|
if (!sale.id)
|
||||||
this.addSale(sale);
|
return this.addSale(sale);
|
||||||
else
|
|
||||||
this.updateQuantity(sale);
|
this.updateQuantity(sale);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -561,6 +562,12 @@ class Controller {
|
||||||
this.$scope.model.refresh();
|
this.$scope.model.refresh();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
itemSearchFunc($search) {
|
||||||
|
return /^\d+$/.test($search)
|
||||||
|
? {id: $search}
|
||||||
|
: {name: {like: '%' + $search + '%'}};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Controller.$inject = ['$scope', '$state', '$http', 'vnApp', '$translate'];
|
Controller.$inject = ['$scope', '$state', '$http', 'vnApp', '$translate'];
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
SMSAvailability: >-
|
Product not available: >-
|
||||||
Verdnatura communicates: Your order {{ticketFk}} created on {{created | date: "dd/MM/yyyy"}}.
|
Verdnatura communicates: Your order {{ticketFk}} created on {{created | date: "dd/MM/yyyy"}}.
|
||||||
{{notAvailables}} not available. Sorry for the inconvenience.
|
{{notAvailables}} not available. Sorry for the inconvenience.
|
|
@ -24,7 +24,8 @@ Sales to transfer: Líneas a transferir
|
||||||
Destination ticket: Ticket destinatario
|
Destination ticket: Ticket destinatario
|
||||||
Change ticket state to 'Ok': Cambiar estado del ticket a 'Ok'
|
Change ticket state to 'Ok': Cambiar estado del ticket a 'Ok'
|
||||||
Reserved: Reservado
|
Reserved: Reservado
|
||||||
SMSAvailability: "Verdnatura le comunica:\rPedido {{ticketFk}} día {{created | date: 'dd/MM/yyyy'}}.\r{{notAvailables}} no disponible/s.\rDisculpe las molestias."
|
Send shortage SMS: Enviar SMS faltas
|
||||||
|
Product not available: "Verdnatura le comunica:\rPedido {{ticketFk}} día {{created | date: 'dd/MM/yyyy'}}.\r{{notAvailables}} no disponible/s.\rDisculpe las molestias."
|
||||||
Continue anyway?: ¿Continuar de todas formas?
|
Continue anyway?: ¿Continuar de todas formas?
|
||||||
This ticket is now empty: El ticket ha quedado vacio
|
This ticket is now empty: El ticket ha quedado vacio
|
||||||
Do you want to delete it?: ¿Quieres eliminarlo?
|
Do you want to delete it?: ¿Quieres eliminarlo?
|
||||||
|
|
|
@ -207,6 +207,39 @@ describe('Ticket', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('onChangeQuantity()', () => {
|
||||||
|
it('should not call addSale() or updateQuantity() methods', () => {
|
||||||
|
jest.spyOn(controller, 'addSale');
|
||||||
|
jest.spyOn(controller, 'updateQuantity');
|
||||||
|
|
||||||
|
const sale = {itemFk: 4};
|
||||||
|
controller.onChangeQuantity(sale);
|
||||||
|
|
||||||
|
expect(controller.addSale).not.toHaveBeenCalled();
|
||||||
|
expect(controller.updateQuantity).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call addSale() method', () => {
|
||||||
|
jest.spyOn(controller, 'addSale');
|
||||||
|
|
||||||
|
const sale = {itemFk: 4, quantity: 5};
|
||||||
|
controller.onChangeQuantity(sale);
|
||||||
|
|
||||||
|
expect(controller.addSale).toHaveBeenCalledWith(sale);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call updateQuantity() method', () => {
|
||||||
|
jest.spyOn(controller, 'updateQuantity');
|
||||||
|
jest.spyOn(controller, 'addSale');
|
||||||
|
|
||||||
|
const sale = {id: 1, itemFk: 4, quantity: 5};
|
||||||
|
controller.onChangeQuantity(sale);
|
||||||
|
|
||||||
|
expect(controller.addSale).not.toHaveBeenCalled();
|
||||||
|
expect(controller.updateQuantity).toHaveBeenCalledWith(sale);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('updateQuantity()', () => {
|
describe('updateQuantity()', () => {
|
||||||
it('should make a POST query saving sale quantity', () => {
|
it('should make a POST query saving sale quantity', () => {
|
||||||
jest.spyOn(controller.$scope.watcher, 'updateOriginalData');
|
jest.spyOn(controller.$scope.watcher, 'updateOriginalData');
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
const UserError = require('vn-loopback/util/user-error');
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
require('../methods/travel/getTravel')(Self);
|
require('../methods/travel/getTravel')(Self);
|
||||||
require('../methods/travel/getEntries')(Self);
|
require('../methods/travel/getEntries')(Self);
|
||||||
|
@ -5,4 +7,10 @@ module.exports = Self => {
|
||||||
require('../methods/travel/createThermograph')(Self);
|
require('../methods/travel/createThermograph')(Self);
|
||||||
require('../methods/travel/deleteThermograph')(Self);
|
require('../methods/travel/deleteThermograph')(Self);
|
||||||
require('../methods/travel/updateThermograph')(Self);
|
require('../methods/travel/updateThermograph')(Self);
|
||||||
|
|
||||||
|
Self.rewriteDbError(function(err) {
|
||||||
|
if (err.code === 'ER_DUP_ENTRY')
|
||||||
|
return new UserError('A travel with this data already exists');
|
||||||
|
return err;
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,6 +2,16 @@ 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, $, $stateParams) {
|
||||||
|
super($element, $);
|
||||||
|
this.$stateParams = $stateParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
$onChanges() {
|
||||||
|
if (this.$stateParams && this.$stateParams.q)
|
||||||
|
this.travel = JSON.parse(this.$stateParams.q);
|
||||||
|
}
|
||||||
|
|
||||||
onSubmit() {
|
onSubmit() {
|
||||||
return this.$.watcher.submit().then(
|
return this.$.watcher.submit().then(
|
||||||
res => this.$state.go('travel.card.summary', {id: res.data.id})
|
res => this.$state.go('travel.card.summary', {id: res.data.id})
|
||||||
|
@ -9,6 +19,8 @@ class Controller extends Section {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Controller.$inject = ['$element', '$scope', '$stateParams'];
|
||||||
|
|
||||||
ngModule.component('vnTravelCreate', {
|
ngModule.component('vnTravelCreate', {
|
||||||
template: require('./index.html'),
|
template: require('./index.html'),
|
||||||
controller: Controller
|
controller: Controller
|
||||||
|
|
|
@ -26,5 +26,18 @@ describe('Travel Component vnTravelCreate', () => {
|
||||||
expect(controller.$state.go).toHaveBeenCalledWith('travel.card.summary', {id: 1234});
|
expect(controller.$state.go).toHaveBeenCalledWith('travel.card.summary', {id: 1234});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('$onChanges()', () => {
|
||||||
|
it('should update the travel data when stateParams.q is defined', () => {
|
||||||
|
controller.$stateParams = {q: '{"ref": 1,"agencyModeFk": 1}'};
|
||||||
|
|
||||||
|
const params = {q: '{"ref": 1, "agencyModeFk": 1}'};
|
||||||
|
const json = JSON.parse(params.q);
|
||||||
|
|
||||||
|
controller.$onChanges();
|
||||||
|
|
||||||
|
expect(controller.travel).toEqual(json);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -41,12 +41,19 @@
|
||||||
<vn-td expand>{{::travel.warehouseInName}}</vn-td>
|
<vn-td expand>{{::travel.warehouseInName}}</vn-td>
|
||||||
<vn-td center>{{::travel.landed | date:'dd/MM/yyyy'}}</vn-td>
|
<vn-td center>{{::travel.landed | date:'dd/MM/yyyy'}}</vn-td>
|
||||||
<vn-td center><vn-check ng-model="travel.isReceived" disabled="true"></vn-check></vn-td>
|
<vn-td center><vn-check ng-model="travel.isReceived" disabled="true"></vn-check></vn-td>
|
||||||
<vn-td>
|
<vn-td shrink>
|
||||||
<vn-icon-button
|
<vn-horizontal class="buttons">
|
||||||
ng-click="$ctrl.preview($event, travel)"
|
<vn-icon-button
|
||||||
vn-tooltip="Preview"
|
ng-click="$ctrl.cloneTravel($event, travel)"
|
||||||
icon="desktop_windows">
|
vn-tooltip="Clone"
|
||||||
</vn-icon-button>
|
icon="icon-clone">
|
||||||
|
</vn-icon-button>
|
||||||
|
<vn-icon-button
|
||||||
|
ng-click="$ctrl.preview($event, travel)"
|
||||||
|
vn-tooltip="Preview"
|
||||||
|
icon="desktop_windows">
|
||||||
|
</vn-icon-button>
|
||||||
|
</vn-horizontal>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
</a>
|
</a>
|
||||||
</vn-tbody>
|
</vn-tbody>
|
||||||
|
@ -65,4 +72,10 @@
|
||||||
fixed-bottom-right>
|
fixed-bottom-right>
|
||||||
<vn-float-button icon="add"></vn-float-button>
|
<vn-float-button icon="add"></vn-float-button>
|
||||||
</a>
|
</a>
|
||||||
|
<vn-confirm
|
||||||
|
vn-id="clone"
|
||||||
|
on-response="$ctrl.onCloneAccept($response)"
|
||||||
|
question="Do you want to clone this travel?"
|
||||||
|
message="All it's properties will be copied">
|
||||||
|
</vn-confirm>
|
||||||
<vn-scroll-up></vn-scroll-up>
|
<vn-scroll-up></vn-scroll-up>
|
|
@ -1,16 +1,10 @@
|
||||||
import ngModule from '../module';
|
import ngModule from '../module';
|
||||||
|
|
||||||
export default class Controller {
|
export default class Controller {
|
||||||
constructor($scope) {
|
constructor($scope, $state) {
|
||||||
this.$ = $scope;
|
this.$ = $scope;
|
||||||
this.ticketSelected = null;
|
this.ticketSelected = null;
|
||||||
}
|
this.$state = $state;
|
||||||
|
|
||||||
preview(event, travel) {
|
|
||||||
this.travelSelected = travel;
|
|
||||||
this.$.summary.show();
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopImmediatePropagation();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getScopeDates(days) {
|
getScopeDates(days) {
|
||||||
|
@ -35,9 +29,44 @@ export default class Controller {
|
||||||
} else
|
} else
|
||||||
this.$.model.clear();
|
this.$.model.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stopEvent(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopImmediatePropagation();
|
||||||
|
}
|
||||||
|
|
||||||
|
cloneTravel(event, travel) {
|
||||||
|
this.stopEvent(event);
|
||||||
|
this.travelSelected = travel;
|
||||||
|
this.$.clone.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
onCloneAccept(response) {
|
||||||
|
if (!(response == 'accept' && this.travelSelected))
|
||||||
|
return;
|
||||||
|
if (this.travelSelected) {
|
||||||
|
const travel = {
|
||||||
|
ref: this.travelSelected.ref,
|
||||||
|
agencyModeFk: this.travelSelected.agencyFk,
|
||||||
|
shipped: this.travelSelected.shipped,
|
||||||
|
landed: this.travelSelected.landed,
|
||||||
|
warehouseInFk: this.travelSelected.warehouseInFk,
|
||||||
|
warehouseOutFk: this.travelSelected.warehouseOutFk
|
||||||
|
};
|
||||||
|
const queryParams = JSON.stringify(travel);
|
||||||
|
this.$state.go('travel.create', {q: queryParams});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.travelSelected = null;
|
||||||
|
}
|
||||||
|
preview(event, travel) {
|
||||||
|
this.stopEvent(event);
|
||||||
|
this.travelSelected = travel;
|
||||||
|
this.$.summary.show();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Controller.$inject = ['$scope'];
|
Controller.$inject = ['$scope', '$state'];
|
||||||
|
|
||||||
ngModule.component('vnTravelIndex', {
|
ngModule.component('vnTravelIndex', {
|
||||||
template: require('./index.html'),
|
template: require('./index.html'),
|
||||||
|
|
|
@ -61,4 +61,48 @@ describe('Travel Component vnTravelIndex', () => {
|
||||||
expect(range - dayInMilliseconds).toEqual(dayInMilliseconds + millisecondsPerAddedDay);
|
expect(range - dayInMilliseconds).toEqual(dayInMilliseconds + millisecondsPerAddedDay);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('onCloneAccept()', () => {
|
||||||
|
it('should do nothing if response is not accept', () => {
|
||||||
|
jest.spyOn(controller.$state, 'go');
|
||||||
|
|
||||||
|
let response = 'ERROR!';
|
||||||
|
controller.travelSelected = 'check me';
|
||||||
|
|
||||||
|
controller.onCloneAccept(response);
|
||||||
|
|
||||||
|
expect(controller.$state.go).not.toHaveBeenCalledWith();
|
||||||
|
expect(controller.travelSelected).toEqual('check me');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should do nothing if response is accept but travelSelected is not defined in the controller', () => {
|
||||||
|
jest.spyOn(controller.$state, 'go');
|
||||||
|
|
||||||
|
let response = 'accept';
|
||||||
|
controller.travelSelected = undefined;
|
||||||
|
|
||||||
|
controller.onCloneAccept(response);
|
||||||
|
|
||||||
|
expect(controller.$state.go).not.toHaveBeenCalledWith();
|
||||||
|
expect(controller.travelSelected).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call go() then update travelSelected in the controller', () => {
|
||||||
|
jest.spyOn(controller.$state, 'go');
|
||||||
|
|
||||||
|
let response = 'accept';
|
||||||
|
controller.travelSelected = {
|
||||||
|
ref: 1,
|
||||||
|
agencyFk: 1};
|
||||||
|
const travel = {
|
||||||
|
ref: controller.travelSelected.ref,
|
||||||
|
agencyModeFk: controller.travelSelected.agencyFk
|
||||||
|
};
|
||||||
|
const queryParams = JSON.stringify(travel);
|
||||||
|
controller.onCloneAccept(response);
|
||||||
|
|
||||||
|
expect(controller.$state.go).toHaveBeenCalledWith('travel.create', {q: queryParams});
|
||||||
|
expect(controller.travelSelected).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
Do you want to clone this travel?: ¿Desea clonar este envio?
|
||||||
|
All it's properties will be copied: Todas sus propiedades serán copiadas
|
||||||
|
Clone: Clonar
|
|
@ -54,7 +54,7 @@
|
||||||
"component": "vn-travel-log",
|
"component": "vn-travel-log",
|
||||||
"description": "Log"
|
"description": "Log"
|
||||||
}, {
|
}, {
|
||||||
"url": "/create",
|
"url": "/create?q",
|
||||||
"state": "travel.create",
|
"state": "travel.create",
|
||||||
"component": "vn-travel-create",
|
"component": "vn-travel-create",
|
||||||
"description": "New travel"
|
"description": "New travel"
|
||||||
|
|
|
@ -23,12 +23,12 @@ module.exports = Self => {
|
||||||
beginningYear.setHours(0, 0, 0, 0);
|
beginningYear.setHours(0, 0, 0, 0);
|
||||||
|
|
||||||
let holidays = await Self.rawSql(
|
let holidays = await Self.rawSql(
|
||||||
`SELECT lh.dated, chn.name, cht.name, w.id
|
`SELECT clh.dated, chn.name, cht.name, w.id
|
||||||
FROM vn.holiday lh
|
FROM vn.calendarHolidays clh
|
||||||
JOIN vn.workCenter w ON w.id = lh.workcenterFk
|
JOIN vn.workCenter w ON w.id = clh.workcenterFk
|
||||||
LEFT JOIN vn.calendarHolidaysName chn ON chn.id = lh.holidayDetailFk
|
LEFT JOIN vn.calendarHolidaysName chn ON chn.id = clh.calendarHolidaysNameFk
|
||||||
LEFT JOIN vn.calendarHolidaysType cht ON cht.id = lh.holidayTypeFk
|
LEFT JOIN vn.calendarHolidaysType cht ON cht.id = clh.calendarHolidaysTypeFk
|
||||||
WHERE w.warehouseFk = ? AND lh.dated >= ?`, [warehouseFk, beginningYear]);
|
WHERE w.warehouseFk = ? AND clh.dated >= ?`, [warehouseFk, beginningYear]);
|
||||||
|
|
||||||
return holidays.map(holiday => {
|
return holidays.map(holiday => {
|
||||||
holiday.dated = new Date(holiday.dated);
|
holiday.dated = new Date(holiday.dated);
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
"Department": {
|
"Department": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
"Holiday": {
|
"CalendarHoliday": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
"CalendarHolidaysName": {
|
"CalendarHolidaysName": {
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
{
|
{
|
||||||
"name": "Holiday",
|
"name": "CalendarHoliday",
|
||||||
"base": "VnModel",
|
"base": "VnModel",
|
||||||
"options": {
|
"options": {
|
||||||
"mysql": {
|
"mysql": {
|
||||||
"table": "holiday"
|
"table": "calendarHolidays"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"properties": {
|
"properties": {
|
||||||
"holidayDetailFk": {
|
"calendarHolidaysNameFk": {
|
||||||
"id": true,
|
"id": true,
|
||||||
"type": "Number"
|
"type": "Number"
|
||||||
},
|
},
|
||||||
"holidayTypeFk": {
|
"calendarHolidaysTypeFk": {
|
||||||
"id": true,
|
"id": true,
|
||||||
"type": "Number"
|
"type": "Number"
|
||||||
},
|
},
|
|
@ -23,7 +23,7 @@
|
||||||
},
|
},
|
||||||
"holidays": {
|
"holidays": {
|
||||||
"type": "hasMany",
|
"type": "hasMany",
|
||||||
"model": "Holiday",
|
"model": "CalendarHoliday",
|
||||||
"foreignKey": "workCenterFk"
|
"foreignKey": "workCenterFk"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue