import ngModule from '../module'; import Section from 'salix/components/section'; import './style.scss'; class Controller extends Section { constructor($element, $) { super($element, $); this._sales = []; this.manaCode = 'mana'; this.getConfig(); } sortBy(propertyName) { this.reverse = (this.propertyName === propertyName) ? !this.reverse : false; this.propertyName = propertyName; } get manaCode() { return this._manaCode; } set manaCode(value) { this._manaCode = value; } get ticket() { return this._ticket; } set ticket(value) { this._ticket = value; this.isTicketEditable(); this.isTicketLocked(); } get sales() { if (this._sales) { for (let sale of this._sales) sale.amount = this.getSaleTotal(sale); } return this._sales; } set sales(value) { this._sales = value; } get ticketState() { const ticket = this.ticket; if (!ticket) return null; const ticketState = ticket.ticketState; return ticketState && ticketState.state.code; } getConfig() { let filter = { fields: ['daysForWarningClaim'], }; this.$http.get(`TicketConfigs`, {filter}) .then(res => { this.ticketConfig = res.data; }); } get isClaimable() { if (this.ticket) { const landedPlusWeek = new Date(this.ticket.landed); landedPlusWeek.setDate(landedPlusWeek.getDate() + 7); const hasClaimManagerRole = this.aclService.hasAny(['claimManager']); return landedPlusWeek >= Date.vnNew() || hasClaimManagerRole; } return false; } getSaleTotal(sale) { if (sale.quantity == null || sale.price == null) return null; const price = sale.quantity * sale.price; const discount = (sale.discount * price) / 100; return price - discount; } getMana() { this.$http.get(`Tickets/${this.$params.id}/getSalesPersonMana`) .then(res => { this.edit.mana = res.data; this.$.$applyAsync(() => { this.$.editDiscount.relocate(); this.$.editPricePopover.relocate(); }); }); this.getUsesMana(); } getUsesMana() { this.$http.get(`Sales/usesMana`) .then(res => { this.usesMana = res.data; }); } /** * Returns checked instances * * @return {Array} Checked instances */ selectedSales() { if (!this.sales) return; return this.sales.filter(sale => { return sale.checked; }); } selectedValidSales() { if (!this.sales) return; const selectedSales = this.selectedSales(); return selectedSales.filter(sale => { return sale.id != undefined; }); } /** * Returns the total of checked instances * * @return {Number} Total checked instances */ selectedSalesCount() { const selectedSales = this.selectedSales(); if (selectedSales) return selectedSales.length; return 0; } hasSelectedSales() { return this.selectedSalesCount() > 0; } hasOneSaleSelected() { if (this.selectedSalesCount() === 1) return true; return false; } /** * Returns new instances * * @return {Array} New instances */ newInstances() { if (!this.sales) return; return this.sales.filter(sale => { return !sale.id; }); } resetChanges() { if (this.newInstances().length === 0) this.$.watcher.updateOriginalData(); this.card.reload(); } state(value) { const params = {ticketFk: this.$params.id, code: value}; return this.$http.post('Tickets/state', params).then(() => { this.vnApp.showSuccess(this.$t('Data saved!')); this.card.reload(); }).finally(() => this.resetChanges()); } removeSales() { const sales = this.selectedValidSales(); const params = {sales: sales, ticketId: this.ticket.id}; this.$http.post(`Sales/deleteSales`, params).then(() => { this.removeSelectedSales(); this.vnApp.showSuccess(this.$t('Data saved!')); }).finally(() => this.resetChanges()); } removeSelectedSales() { const sales = this.selectedSales(); sales.forEach(sale => { const index = this.sales.indexOf(sale); this.sales.splice(index, 1); }); } createClaim() { const today = new Date(); today.setHours(0, 0, 0, 0); const timeDifference = today.getTime() - new Date(this.ticket.landed).getTime(); const pastDays = Math.floor(timeDifference / 86400000); if (pastDays >= this.ticketConfig[0].daysForWarningClaim) this.$.claimConfirm.show(); else this.$.claimSure.show(); } onCreateClaimAccepted() { const sales = this.selectedValidSales(); const params = {ticketId: this.ticket.id, sales: sales}; this.resetChanges(); this.$http.post(`Claims/createFromSales`, params) .then(async res => window.location.href = await this.vnApp.getUrl(`claim/${res.data.id}/basic-data`)); } showTransferPopover(event) { this.setTransferParams(); this.$.transfer.show(event); } setTransferParams() { const checkedSales = JSON.stringify(this.selectedValidSales()); const sales = JSON.parse(checkedSales); this.transfer = { lastActiveTickets: [], sales: sales }; const params = {ticketId: this.ticket.id}; const query = `clients/${this.ticket.clientFk}/lastActiveTickets`; this.$http.get(query, {params}).then(res => { this.transfer.lastActiveTickets = res.data; }); } transferSales(ticketId) { const params = { ticketId: ticketId, sales: this.transfer.sales }; this.$.watcher.updateOriginalData(); const query = `tickets/${this.ticket.id}/transferSales`; this.$http.post(query, params) .then(res => { if (res.data && res.data.id === this.ticket.id) { this.$.transfer.hide(); this.$.model.refresh(); } else this.$state.go('ticket.card.sale', {id: res.data.id}); }); } showEditPricePopover(event, sale) { if (!this.isEditable) return; this.edit = { price: sale.price, sale: sale }; this.$.editPricePopover.show(event); } updatePrice() { const sale = this.edit.sale; const newPrice = this.edit.price; if (newPrice != null && newPrice != sale.price) { const query = `Sales/${sale.id}/updatePrice`; this.$http.post(query, {newPrice}).then(res => { sale.price = res.data.price; this.edit = null; this.vnApp.showSuccess(this.$t('Data saved!')); }).finally(() => this.resetChanges()); } this.$.editPricePopover.hide(); } showEditDiscountPopover(event, sale) { if (this.isLocked) return; if (sale) { this.edit = { discount: sale.discount, sale: sale }; } else { this.edit = { discount: null, sales: this.selectedValidSales() }; } this.$.editDiscount.show(event); } changeDiscount() { const sale = this.edit.sale; const newDiscount = this.edit.discount; if (newDiscount != null && newDiscount != sale.discount) this.updateDiscount([sale]); this.$.editDiscount.hide(); } changeMultipleDiscount() { const sales = this.edit.sales; const newDiscount = this.edit.discount; const hasChanges = sales.some(sale => { return sale.discount != newDiscount; }); if (newDiscount != null && hasChanges) this.updateDiscount(sales); this.$.editDiscount.hide(); } updateDiscount(sales) { const saleIds = sales.map(sale => { return sale.id; }); const params = {salesIds: saleIds, newDiscount: this.edit.discount, manaCode: this.manaCode}; const query = `Tickets/${this.$params.id}/updateDiscount`; this.$http.post(query, params).then(() => { this.vnApp.showSuccess(this.$t('Data saved!')); for (let sale of sales) sale.discount = this.edit.discount; this.edit = null; }).finally(() => this.resetChanges()); } getNewPrice() { if (this.edit.sale) { const sale = this.edit.sale; let newDiscount = sale.discount; let newPrice = this.edit.price || sale.price; if (this.edit.discount != null) newDiscount = this.edit.discount; if (this.edit.price != null) newPrice = this.edit.price; const price = sale.quantity * newPrice; const discount = (newDiscount * price) / 100; return price - discount; } return 0; } hasReserves() { return this.sales.some(sale => { return sale.reserved == true; }); } /* * Unmark sale as reserved */ unmarkAsReserved() { this.setReserved(false); } /* * Mark sale as reserved */ markAsReserved() { this.setReserved(true); } setReserved(reserved) { const selectedSales = this.selectedValidSales(); const params = {ticketId: this.ticket.id, sales: selectedSales, reserved: reserved}; this.$http.post(`Sales/reserve`, params).then(() => { selectedSales.forEach(sale => { sale.reserved = reserved; }); }).finally(() => this.resetChanges()); } newOrderFromTicket() { this.$http.post(`Orders/newFromTicket`, {ticketFk: this.ticket.id}).then(res => { const path = this.$state.href('order.card.catalog', {id: res.data}); window.open(path, '_blank'); this.vnApp.showSuccess(this.$t('Order created')); }); } showSMSDialog() { const address = this.ticket.address; const client = this.ticket.client; const phone = address.mobile || address.phone || client.mobile || client.phone; const sales = this.selectedValidSales(); const items = sales.map(sale => { return `${sale.quantity} ${sale.concept}`; }); const notAvailables = items.join(', '); const params = { ticketFk: this.ticket.id, created: this.ticket.updated, landed: this.ticket.landed, notAvailables }; this.newSMS = { ticketId: this.ticket.id, destinationFk: this.ticket.clientFk, destination: phone, message: this.$t('Product not available', params) }; this.$.sms.open(); } onSmsSend(sms) { return this.$http.post(`Tickets/${this.ticket.id}/sendSms`, sms) .then(() => this.vnApp.showSuccess(this.$t('SMS sent'))); } /** * Inserts a new instance */ add() { this.$.model.insert({}); } /* * Creates a new sale if it's a new instance * Updates the sale quantity for existing instance */ changeQuantity(sale) { if (!sale.itemFk || sale.quantity == null) return; if (!sale.id) return this.addSale(sale); this.updateQuantity(sale); } /* * Changes a sale quantity */ updateQuantity(sale) { const data = {quantity: sale.quantity}; this.$http.post(`Sales/${sale.id}/updateQuantity`, data).then(() => { this.vnApp.showSuccess(this.$t('Data saved!')); }).catch(e => { this.$.model.refresh(); throw e; }).finally(() => this.resetChanges()); } /* * Changes a sale concept */ updateConcept(sale) { const data = {newConcept: sale.concept}; this.$http.post(`Sales/${sale.id}/updateConcept`, data).then(() => { this.vnApp.showSuccess(this.$t('Data saved!')); }).catch(e => { this.$.model.refresh(); throw e; }).finally(() => this.resetChanges()); } /* * Adds a new sale */ addSale(sale) { const data = { barcode: 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; this.vnApp.showSuccess(this.$t('Data saved!')); }).finally(() => this.resetChanges()); } isTicketEditable() { this.$http.get(`Tickets/${this.$params.id}/isEditable`) .then(res => this.isEditable = res.data); } isTicketLocked() { this.$http.get(`Tickets/${this.$params.id}/isLocked`) .then(res => this.isLocked = res.data); } calculateSalePrice() { const sales = this.selectedValidSales(); if (!sales) return; const query = `Sales/recalculatePrice`; this.$http.post(query, sales).then(() => { this.vnApp.showSuccess(this.$t('Data saved!')); this.$.model.refresh(); }); } createRefund(withWarehouse) { const sales = this.selectedValidSales(); if (!sales) return; const salesIds = sales.map(sale => sale.id); const params = {salesIds: salesIds, withWarehouse: withWarehouse, negative: true}; const query = 'Sales/clone'; this.$http.post(query, params).then(res => { const [refundTicket] = res.data; this.vnApp.showSuccess(this.$t('The following refund ticket have been created', { ticketId: refundTicket.id })); this.$state.go('ticket.card.sale', {id: refundTicket.id}); this.resetChanges(); }); } itemSearchFunc($search) { return /^\d+$/.test($search) ? {id: $search} : {name: {like: '%' + $search + '%'}}; } save() { if (this.edit.sale) this.changeDiscount(); if (this.edit.sales) this.changeMultipleDiscount(); } cancel() { this.$.editDiscount.hide(); } goToLog(saleId) { this.$state.go('ticket.card.log', { originId: this.$params.id, changedModel: 'Sale', changedModelId: saleId }); } async goToLilium(section, id) { window.location.href = await this.vnApp.getUrl(`claim/${id}/${section}`); } } ngModule.vnComponent('vnTicketSale', { template: require('./index.html'), controller: Controller, bindings: { ticket: '<' }, require: { card: '?^vnTicketCard' } });