salix/modules/ticket/front/sale/index.js

583 lines
16 KiB
JavaScript
Raw Normal View History

2018-03-22 17:02:48 +00:00
import ngModule from '../module';
import './style.scss';
2018-03-22 17:02:48 +00:00
class Controller {
2018-07-17 06:44:31 +00:00
constructor($scope, $state, $http, vnApp, $translate) {
this.$scope = $scope;
this.vnApp = vnApp;
this.$translate = $translate;
2018-07-17 06:44:31 +00:00
this.$state = $state;
this.$stateParams = $state.params;
this.$http = $http;
this.edit = {};
this.moreOptions = [
{
2020-03-11 11:02:12 +00:00
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 = [];
2018-10-22 06:23:10 +00:00
this.imagesPath = '//verdnatura.es/vn-image-data/catalog';
}
2019-07-22 11:14:00 +00:00
get ticket() {
return this._ticket;
}
set ticket(value) {
this._ticket = value;
2019-08-13 12:03:02 +00:00
this.isTicketEditable();
2020-02-27 11:31:38 +00:00
this.isTicketLocked();
2019-07-22 11:14:00 +00:00
}
get sales() {
return this._sales;
}
2018-10-22 06:23:10 +00:00
set sales(value) {
this._sales = value;
2018-10-23 12:33:07 +00:00
this.refreshTotal();
2018-10-22 06:23:10 +00:00
}
get editedPrice() {
return this._editedPrice;
2018-07-02 11:18:22 +00:00
}
2018-07-17 06:44:31 +00:00
set editedPrice(value) {
this._editedPrice = value;
this.updateNewPrice();
}
2018-10-23 12:33:07 +00:00
refreshTotal() {
this.loadSubTotal();
this.loadVAT();
}
2018-10-22 06:23:10 +00:00
loadSubTotal() {
if (!this.$stateParams.id || !this.sales) return;
this.$http.get(`Tickets/${this.$stateParams.id}/subtotal`).then(res => {
this.subtotal = res.data || 0.0;
});
2018-06-19 10:10:38 +00:00
}
2018-07-17 06:44:31 +00:00
2018-10-22 06:23:10 +00:00
getSaleTotal(sale) {
if (!sale.quantity || !sale.price)
return;
2018-10-22 06:23:10 +00:00
return sale.quantity * sale.price * ((100 - sale.discount) / 100);
}
2018-06-19 10:10:38 +00:00
2018-10-22 06:23:10 +00:00
loadVAT() {
this.VAT = 0.0;
if (!this.$stateParams.id || !this.sales) return;
this.$http.get(`Tickets/${this.$stateParams.id}/getVAT`).then(res => {
2018-10-22 06:23:10 +00:00
this.VAT = res.data || 0.0;
2018-06-19 10:10:38 +00:00
});
}
2018-07-17 06:44:31 +00:00
2018-10-22 06:23:10 +00:00
get total() {
return this.subtotal + this.VAT;
2018-10-22 06:23:10 +00:00
}
onMoreOpen() {
2019-05-06 05:40:59 +00:00
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));
});
2018-10-22 06:23:10 +00:00
this.$scope.moreButton.data = options;
}
onMoreChange(callback) {
callback.call(this);
2018-06-19 10:10:38 +00:00
}
2018-07-17 06:44:31 +00:00
get isChecked() {
2018-11-06 12:59:16 +00:00
if (this.sales) {
2018-10-22 06:23:10 +00:00
for (let instance of this.sales)
if (instance.checked) return true;
2018-11-06 12:59:16 +00:00
}
return false;
}
2018-07-17 06:44:31 +00:00
/**
* Returns checked instances
*
* @return {Array} Checked instances
*/
2019-08-09 06:04:44 +00:00
checkedLines() {
if (!this.sales) return;
return this.sales.filter(sale => {
return sale.checked;
});
}
/**
* Returns new instances
*
* @return {Array} New instances
*/
newInstances() {
if (!this.sales) return;
return this.sales.filter(sale => {
return !sale.id;
});
}
2019-08-09 06:04:44 +00:00
/**
* Returns an array of indexes
* from checked instances
*
* @return {Array} Indexes of checked instances
*/
2019-08-09 06:04:44 +00:00
checkedLinesIndex() {
if (!this.sales) return;
let indexes = [];
this.sales.forEach((sale, index) => {
if (sale.checked) indexes.push(index);
});
return indexes;
}
2019-08-09 06:04:44 +00:00
firstCheckedLine() {
const checkedLines = this.checkedLines();
if (checkedLines)
return checkedLines[0];
}
/**
* Returns the total of checked instances
*
* @return {Number} Total checked instances
*/
totalCheckedLines() {
const checkedLines = this.checkedLines();
if (checkedLines)
2020-03-11 11:54:28 +00:00
return checkedLines.length;
2019-08-09 06:04:44 +00:00
}
removeCheckedLines() {
2019-08-09 06:04:44 +00:00
const sales = this.checkedLines();
sales.forEach(sale => {
const index = this.sales.indexOf(sale);
this.sales.splice(index, 1);
});
if (this.newInstances().length === 0)
this.$scope.watcher.updateOriginalData();
this.refreshTotal();
}
2018-07-17 06:44:31 +00:00
onStateOkClick() {
2018-11-06 12:59:16 +00:00
let filter = {where: {code: 'OK'}, fields: ['id']};
let json = encodeURIComponent(JSON.stringify(filter));
return this.$http.get(`States?filter=${json}`).then(res => {
this.onStateChange(res.data[0].id);
});
}
2018-07-17 06:44:31 +00:00
onStateChange(value) {
let params = {ticketFk: this.$state.params.id, stateFk: value};
2020-02-26 12:22:52 +00:00
this.$http.post('TicketTrackings/changeState', params).then(() => {
this.card.reload();
this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
2019-09-09 10:35:59 +00:00
}).finally(() => {
if (this.newInstances().length === 0)
this.$scope.watcher.updateOriginalData();
});
}
2018-07-17 06:44:31 +00:00
onRemoveLinesClick(response) {
2019-10-30 15:57:14 +00:00
if (response === 'accept') {
2019-08-09 06:04:44 +00:00
let sales = this.checkedLines();
// 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();
2018-09-05 14:14:13 +00:00
this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
});
}
}
2018-07-17 06:44:31 +00:00
showRemoveLinesDialog() {
2018-07-17 06:44:31 +00:00
this.$scope.deleteLines.show();
}
2018-07-17 06:44:31 +00:00
showTransferPopover(event) {
2019-08-09 06:04:44 +00:00
this.setTransferParams();
2018-07-17 06:44:31 +00:00
this.$scope.transfer.parent = event.target;
this.$scope.transfer.show();
}
2018-07-17 06:44:31 +00:00
2019-08-09 06:04:44 +00:00
setTransferParams() {
const checkedSales = JSON.stringify(this.checkedLines());
const sales = JSON.parse(checkedSales);
this.transfer = {
lastActiveTickets: [],
sales: sales
};
2019-08-09 06:04:44 +00:00
const params = {ticketId: this.ticket.id};
const query = `clients/${this.ticket.clientFk}/lastActiveTickets`;
2019-08-09 06:04:44 +00:00
this.$http.get(query, {params}).then(res => {
this.transfer.lastActiveTickets = res.data;
});
}
2018-07-17 06:44:31 +00:00
2019-08-09 06:04:44 +00:00
transferSales(ticketId) {
const params = {
ticketId: ticketId,
sales: this.transfer.sales
};
2019-09-24 09:55:36 +00:00
this.$scope.watcher.updateOriginalData();
const query = `tickets/${this.ticket.id}/transferSales`;
2019-08-09 06:04:44 +00:00
this.$http.post(query, params).then(res => {
2019-09-09 10:35:59 +00:00
this.goToTicket(res.data.id);
});
}
2018-07-17 06:44:31 +00:00
2018-09-11 10:49:31 +00:00
createClaim() {
const claim = {
2018-09-11 10:49:31 +00:00
ticketFk: this.ticket.id,
clientFk: this.ticket.clientFk,
2019-03-21 13:56:09 +00:00
ticketCreated: this.ticket.shipped
2018-09-11 10:49:31 +00:00
};
2019-08-09 06:04:44 +00:00
const sales = this.checkedLines();
2019-09-24 09:55:36 +00:00
if (this.newInstances().length === 0)
this.$scope.watcher.updateOriginalData();
this.$http.post(`Claims/createFromSales`, {claim: claim, sales: sales}).then(res => {
2018-11-06 12:59:16 +00:00
this.$state.go('claim.card.basicData', {id: res.data.id});
2018-09-11 10:49:31 +00:00
});
}
2019-08-09 06:04:44 +00:00
goToTicket(ticketId) {
this.$state.go('ticket.card.sale', {id: ticketId});
}
2018-07-17 06:44:31 +00:00
// Slesperson Mana
getManaSalespersonMana() {
this.$http.get(`Tickets/${this.$state.params.id}/getSalesPersonMana`).then(res => {
this.mana = res.data;
});
}
2018-07-17 06:44:31 +00:00
// Item Descriptor
showDescriptor(event, itemFk) {
2018-09-04 09:49:00 +00:00
this.quicklinks = {
btnThree: {
icon: 'icon-transaction',
state: `item.card.diary({
id: ${itemFk},
warehouseFk: ${this.ticket.warehouseFk},
ticketFk: ${this.ticket.id}
2018-09-04 09:49:00 +00:00
})`,
tooltip: 'Item diary'
}
};
2018-07-17 06:44:31 +00:00
this.$scope.descriptor.itemFk = itemFk;
this.$scope.descriptor.parent = event.target;
this.$scope.descriptor.show();
}
2018-07-17 06:44:31 +00:00
onDescriptorLoad() {
2018-07-17 06:44:31 +00:00
this.$scope.popover.relocate();
2018-03-26 12:55:10 +00:00
}
2018-07-17 06:44:31 +00:00
showEditPricePopover(event, sale) {
if (!this.isEditable) return;
this.sale = sale;
this.editedPrice = this.sale.price;
this.edit = {
ticketFk: this.ticket.id,
id: sale.id,
quantity: sale.quantity
};
2018-07-17 06:44:31 +00:00
this.$scope.editPricePopover.parent = event.target;
this.$scope.editPricePopover.show();
}
2018-07-17 06:44:31 +00:00
updatePrice() {
if (this.editedPrice != this.sale.price) {
this.$http.post(`Sales/${this.edit.id}/updatePrice`, {newPrice: this.editedPrice}).then(res => {
this.sale.price = res.data.price;
this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
2019-09-09 10:35:59 +00:00
}).finally(() => {
if (this.newInstances().length === 0)
this.$scope.watcher.updateOriginalData();
});
}
2018-11-06 12:59:16 +00:00
2018-07-17 06:44:31 +00:00
this.$scope.editPricePopover.hide();
}
2018-07-17 06:44:31 +00:00
updateNewPrice() {
this.newPrice = this.sale.quantity * this.editedPrice - ((this.sale.discount * (this.sale.quantity * this.editedPrice)) / 100);
}
showEditDiscountPopover(event, sale) {
2020-02-27 11:31:38 +00:00
if (this.isLocked) return;
this.sale = sale;
this.edit = [{
ticketFk: this.ticket.id,
id: sale.id,
quantity: sale.quantity,
price: sale.price,
discount: sale.discount
}];
2018-07-17 06:44:31 +00:00
this.$scope.editPopover.parent = event.target;
this.$scope.editPopover.show();
}
2018-07-17 06:44:31 +00:00
showEditDialog() {
2019-08-09 06:04:44 +00:00
this.edit = this.checkedLines();
2018-07-17 06:44:31 +00:00
this.$scope.editDialog.show();
}
2018-07-17 06:44:31 +00:00
hideEditDialog() {
2018-07-17 06:44:31 +00:00
this.$scope.model.refresh();
this.$scope.editDialog.hide();
}
2018-07-17 06:44:31 +00:00
hideEditPopover() {
2018-07-17 06:44:31 +00:00
this.$scope.model.refresh();
this.$scope.editPopover.hide();
}
2018-07-17 06:44:31 +00:00
/*
2018-10-23 12:33:07 +00:00
* Unmark sale as reserved
*/
2018-06-19 07:09:49 +00:00
unmarkAsReserved() {
this.setReserved(false);
}
/*
2018-10-23 12:33:07 +00:00
* Mark sale as reserved
*/
markAsReserved() {
this.setReserved(true);
}
2018-06-19 07:09:49 +00:00
setReserved(reserved) {
2019-08-09 06:04:44 +00:00
let selectedSales = this.checkedLines();
let params = {sales: selectedSales, ticketFk: this.ticket.id, reserved: reserved};
2018-06-19 07:09:49 +00:00
let reservedSales = new Map();
this.$http.post(`Sales/reserve`, params).then(res => {
let isReserved = res.config.data.reserved;
res.config.data.sales.forEach(sale => {
reservedSales.set(sale.id, {reserved: isReserved});
});
this.sales.forEach(sale => {
const reservedSale = reservedSales.get(sale.id);
if (reservedSale)
sale.reserved = reservedSale.reserved;
});
2019-09-09 10:35:59 +00:00
}).finally(() => {
if (this.newInstances().length === 0)
this.$scope.watcher.updateOriginalData();
2018-06-19 07:09:49 +00:00
});
}
newOrderFromTicket() {
this.$http.post(`Orders/newFromTicket`, {ticketFk: this.ticket.id}).then(res => {
const path = this.$state.href('order.card.catalog', {id: res.data});
2019-09-19 13:51:39 +00:00
window.open(path, '_blank');
this.vnApp.showSuccess(this.$translate.instant('Order created'));
});
}
showSMSDialog() {
const address = this.ticket.address;
2020-02-21 07:37:37 +00:00
const client = this.ticket.client;
const phone = address.mobile || address.phone ||
client.mobile || client.phone;
2019-08-09 06:04:44 +00:00
const sales = this.checkedLines();
const items = sales.map(sale => {
return `${sale.quantity} ${sale.concept}`;
});
const notAvailables = items.join(', ');
const params = {
ticketFk: this.ticket.id,
created: this.ticket.created,
notAvailables
};
this.newSMS = {
2019-04-16 05:59:12 +00:00
destinationFk: this.ticket.clientFk,
2020-02-21 07:37:37 +00:00
destination: phone,
2020-03-11 11:02:12 +00:00
message: this.$translate.instant('Product not available', params)
};
this.$scope.sms.open();
}
2019-05-06 05:40:59 +00:00
/**
* Inserts a new instance
*/
add() {
this.$scope.model.insert({});
}
/*
* Creates a new sale if it's a new instance
* Updates the sale quantity for existing instance
*/
onChangeQuantity(sale) {
if (!sale.id)
this.addSale(sale);
else
this.updateQuantity(sale);
}
/*
* Updates a sale quantity
*/
updateQuantity(sale) {
const data = {quantity: parseInt(sale.quantity)};
const query = `Sales/${sale.id}/updateQuantity`;
this.$http.post(query, data).then(() => {
this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
}).catch(e => {
this.$scope.model.refresh();
throw e;
2019-09-09 10:35:59 +00:00
}).finally(() => {
if (this.newInstances().length === 0)
this.$scope.watcher.updateOriginalData();
});
}
/*
* Updates a sale concept
*/
updateConcept(sale) {
2019-09-06 09:43:15 +00:00
const data = {newConcept: sale.concept};
const query = `Sales/${sale.id}/updateConcept`;
2019-09-06 09:43:15 +00:00
this.$http.post(query, data).then(() => {
this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
}).catch(e => {
this.$scope.model.refresh();
throw e;
2019-09-09 10:35:59 +00:00
}).finally(() => {
if (this.newInstances().length === 0)
this.$scope.watcher.updateOriginalData();
});
}
/*
* Adds a new sale
*/
addSale(sale) {
const data = {
itemId: sale.itemFk,
quantity: sale.quantity
};
const query = `tickets/${this.ticket.id}/addSale`;
this.$http.post(query, data).then(res => {
if (!res.data) return;
const newSale = res.data;
sale.id = newSale.id;
sale.image = newSale.item.image;
sale.subName = newSale.item.subName;
sale.concept = newSale.concept;
sale.quantity = newSale.quantity;
sale.discount = newSale.discount;
sale.price = newSale.price;
sale.item = newSale.item;
2019-09-09 10:35:59 +00:00
this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
}).finally(() => {
if (this.newInstances().length === 0)
this.$scope.watcher.updateOriginalData();
});
}
isTicketEditable() {
this.$http.get(`Tickets/${this.$state.params.id}/isEditable`).then(res => {
this.isEditable = res.data;
});
}
2020-02-27 11:31:38 +00:00
isTicketLocked() {
this.$http.get(`Tickets/${this.$state.params.id}/isLocked`).then(res => {
this.isLocked = res.data;
});
}
hasOneSaleSelected() {
if (this.totalCheckedLines() === 1)
return true;
return false;
}
calculateSalePrice() {
const sale = this.checkedLines()[0];
2019-11-21 11:00:56 +00:00
const query = `Sales/${sale.id}/recalculatePrice`;
this.$http.post(query).then(res => {
this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
this.$scope.model.refresh();
});
}
2020-03-11 14:56:02 +00:00
itemSearchFunc($search) {
return /^\d+$/.test($search)
? {id: $search}
: {name: {like: '%' + $search + '%'}};
}
2018-03-26 12:55:10 +00:00
}
2018-07-17 06:44:31 +00:00
Controller.$inject = ['$scope', '$state', '$http', 'vnApp', '$translate'];
2018-03-26 12:55:10 +00:00
2018-03-22 17:02:48 +00:00
ngModule.component('vnTicketSale', {
template: require('./index.html'),
controller: Controller,
bindings: {
ticket: '<'
},
require: {
2018-10-22 06:23:10 +00:00
card: '?^vnTicketCard'
}
2018-03-22 17:02:48 +00:00
});